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

ehayun
I have 2 arrays: a1 can be any combination of value or nil like that a1 = [1,nil,3] and array 2 the same a2 = [4,2, nil] How do I com...
New
sneako
Note by the Moderators: This topic is to talk about the first day of the Advent of Code. For general discussion about the Advent of Code...
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
groovyda
Today’s challenge for me was about using reduce: defmodule Prob5 do def move([[h1 | rest] = _list1, list2]) do [rest, [h1 | list2]...
New
bjorng
Note: This topic is to talk about Day 3 of the Advent of Code 2019 . There is a private leaderboard for elixirforum members. You can jo...
New
cblavier
Hey there :wave: No magic or algorithmic finesse today, I just finished the challenge and I my code is quite slow (1sec for part1, 3se...
New
New
Aetherus
This topic is about Day 16 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/l...
New
kwando
Took a while, but another use case for “move vectors” today and pattern matching. :slight_smile: The trick was to first generate a list...
New
rvnash
Anyone have a solution to Part 2 today? Part 1 was straight forward, but I can’t figure out a programatic way to do part 2. I understand ...
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
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
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
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
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement