code-shoily

code-shoily

Advent of Code 2024 - Day 3

Here’s my day 3 code

This was quite easy. I was afraid Part 2 would be “un-regex-able” and was preparing for hand crafting automata but looks like it wasn’t the case. Also, nice to have that Toboggan reference. I love cross-overs.

Most Liked

Flo0807

Flo0807

Hey!

This is my solution for Day 03.

Part 1

Regex.scan(~r/mul\((\d+),(\d+)\)/, puzzle_input, capture: :all_but_first)
|> Enum.map(fn [a, b] ->
  String.to_integer(a) * String.to_integer(b)
end)
|> Enum.sum()

Part 2

Regex.scan(~r/mul\((-?\d+),(-?\d+)\)|do(?:n't)?\(\)/, puzzle_input)
|> Enum.reduce({0, :enabled}, fn
  ["don't()"], {count, _status} ->
    {count, :disabled}

  ["do()"], {count, _status} ->
    {count, :enabled}

  [_text, a, b], {count, :enabled} ->
    result = String.to_integer(a) * String.to_integer(b)

    {result + count, :enabled}

  [_text, _a, _b], {count, :disabled} ->
    {count, :disabled}
end)
|> elem(0)
jswanner

jswanner

I used NimbleParsec to build a parser:

defmodule Parser do
  import NimbleParsec

  disable =
    ignore(string("don't()"))
    |> tag(:disable)

  enable =
    ignore(string("do()"))
    |> tag(:enable)

  operand = integer(max: 3, min: 1)

  mul =
    ignore(string("mul("))
    |> concat(operand)
    |> ignore(string(","))
    |> concat(operand)
    |> ignore(string(")"))
    |> tag(:mul)

  instruction = choice([disable, enable, mul])

  instructions =
    eventually(instruction)
    |> repeat()

  defparsec(:parse, instructions |> eventually(eos()))
end
pehbehbeh

pehbehbeh

Wanted to try out something new and used nimble_parsec for the first time.

bjorng

bjorng

Erlang Core Team

I went for a solution using regexes and regretted it almost immediately. It took me a while to realize that Regex.run/3 with the :global option will not return multiple solutions (as :re.run/3 would), but that I needed to use Regex.scan/3. Fortunately, having invested a lot of time solving part 1 with a regex, it turned out it was possible to solve also part 2 with a regex.

Having tried regexes, I decided to implement a solution in Erlang using the binary syntax to do the parsing:

UPDATE: After looking at the other solutions, I realized that I only looked for do and don't instead of do() and don't(). That happened to produce the correct result (at least for my input), but I’ve now updated my programs to match the parens too.

smaller_infinity

smaller_infinity

I really dont like regex so I used nimble parsec (for the first time):

defmodule Advent2024.Day03 do
  @test_data1 "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
  @test_data2 "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"

  defmodule Parser do
    import NimbleParsec

    defcombinator :int, integer(min: 1, max: 3)

    defcombinator :do, string("do()") |> replace(:do)
    defcombinator :dont, string("don't()") |> replace(:dont)

    defparsec :mul,
              ignore(string("mul("))
              |> parsec(:int)
              |> ignore(string(","))
              |> parsec(:int)
              |> ignore(string(")"))
              |> reduce(:collect_args)

    defp collect_args([a, b]), do: {:mul, a, b}

    defparsec :eval,
              choice([parsec(:do), parsec(:mul), parsec(:dont)]) |> eventually() |> repeat()
  end

  alias Advent2024.Day03.Parser

  defp parse_line(input) do
    {:ok, result, _, _, _, _} = Parser.eval(input)
    result
  end

  defp parse_input(input) do
    input
    |> Enum.take_while(&Kernel.!=(&1, ""))
    |> Enum.flat_map(&parse_line/1)
  end

  def part1(input) do
    input
    |> parse_input()
    |> Enum.map(fn
      {:mul, a, b} -> a * b
      _ -> 0
    end)
    |> Enum.sum()
  end

  defp handle_instructions(:do, {acc, _}), do: {acc, true}
  defp handle_instructions(:dont, {acc, _}), do: {acc, false}
  defp handle_instructions({:mul, a, b}, {acc, true}), do: {acc + a * b, true}
  defp handle_instructions(_, {acc, false}), do: {acc, false}

  def part2(input) do
    input
    |> parse_input()
    |> Enum.reduce({0, true}, &handle_instructions/2)
    |> elem(0)
  end

  def test_input1() do
    [@test_data1]
  end

  def test_input2() do
    [@test_data2]
  end

  def input() do
    File.stream!("data/data_03.txt")
  end
end

Where Next?

Popular in Challenges Top

Qqwy
Note by the Moderators: This topic is to talk about Day 6 of the Advent of Code. For general discussion about the Advent of Code 2018 an...
New
bjorng
Note: This topic is to talk about Day 13 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can joi...
New
New
Aetherus
I tried to use combinatorial to solve today’s puzzles but failed (my brain burned out :exploding_head:). In the end I just used brute for...
New
kwando
Phew, this one took a while to get right. My naive attempts was way to slow so I reached for Dijkstras shortest path algorithm… and that ...
New
New
bjorng
Note: This topic is to talk about Day 23 of the Advent of Code. For general discussion about the Advent of Code 2018 and links to topics...
New
Aetherus
Hello, guys. I’m back again, but only for the weekends, maybe. This topic is about Day 13 of the Advent of Code 2020 . Thanks to @egze,...
New
bjorng
This topic is about Day 6 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums ): https://adve...
New
bjorng
Note: This topic is to talk about Day 4 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can join...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement