Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Advent of Code 2024 - Day 03

elixir/2024/day_03.livemd

Advent of Code 2024 - Day 03

Mix.install([
  {:kino_aoc, "~> 0.1.7"}
])

Introduction

2024 - Day 03

Puzzle

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "3", System.fetch_env!("LB_AOC_SESSION"))

Parser

Code - Parser

defmodule Parser do
  def parse(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.join("")
  end
end

Tests - Parser

ExUnit.start(autorun: false)

defmodule ParserTest do
  use ExUnit.Case, async: true
  import Parser

  @input """
  ]sel
  #-#$
  """
  @expected "]sel#-#$"

  test "parse test" do
    actual = parse(@input)
    assert actual == @expected
  end
end

ExUnit.run()

Part One

Code - Part 1

defmodule PartOne do
  @reg ~r/mul\((\d+),(\d+)\)/
  
  def solve(input) do
    IO.puts("--- Part One ---")
    IO.puts("Result: #{run(input)}")
  end

  def run(input) do
    input
    |> Parser.parse()
    |> then(fn line ->
      Regex.scan(@reg, line)
      |> Enum.map(fn [_, a, b] ->
        a = String.to_integer(a)
        b = String.to_integer(b)
        a * b
      end)
      |> Enum.sum()
    end)
  end
end

Tests - Part 1

ExUnit.start(autorun: false)

defmodule PartOneTest do
  use ExUnit.Case, async: true
  import PartOne

  @input "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
  @expected 161

  test "part one" do
    actual = run(@input)
    assert actual == @expected
  end
end

ExUnit.run()

Solution - Part 1

PartOne.solve(puzzle_input)

Part Two

Code - Part 2

defmodule PartTwo do
  @reg ~r/do\(\)|don't\(\)|mul\((\d+),(\d+)\)/
  
  def solve(input) do
    IO.puts("--- Part Two ---")
    IO.puts("Result: #{run(input)}")
  end

  def run(input) do
    input
    |> Parser.parse()
    |> then(fn line ->
      Regex.scan(@reg, line)
      |> Enum.reduce({:do, 0}, fn 
        ["do()"], {_, sum} -> {:do, sum}
        ["don't()"], {_, sum} -> {:dont, sum}
        [_, _, _], {:dont, sum} -> {:dont, sum}
        [_, a, b], {:do, sum} -> 
          a = String.to_integer(a)
          b = String.to_integer(b)
          {:do, sum + a * b}
      end)
    end)
    |> elem(1)
  end
end

Tests - Part 2

ExUnit.start(autorun: false)

defmodule PartTwoTest do
  use ExUnit.Case, async: true
  import PartTwo

  @input "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"
  @expected 48

  test "part two" do
    actual = run(@input)
    assert actual == @expected
  end
end

ExUnit.run()

Solution - Part 2

PartTwo.solve(puzzle_input)