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

Advent of Code - Day XX

2024/lang-elixir/day01.livemd

Advent of Code - Day XX

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

Introduction

–> Content

Puzzle

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

Parser

Code - Parser

defmodule Parser do
  def parse(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.reduce({[], []}, fn line, {acc1, acc2} ->
      [a, b] = String.split(line, " ", trim: true)

      {[String.to_integer(a) | acc1], [String.to_integer(b) | acc2]}
    end)
  end
end

Tests - Parser

ExUnit.start(autorun: false)

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

  @input """
  3   4
  4   3
  2   5
  1   3
  3   9
  3   3
  """
  @expected {
    [3, 3, 1, 2, 4, 3], 
    [3, 9, 3, 5, 3, 4]
  }

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

ExUnit.run()

Part One

Code - Part 1

defmodule PartOne do
  def solve(input) do
    IO.puts("--- Part One ---")
    IO.puts("Result: #{run(input)}")
  end

  def run(input) do
    {a, b} = Parser.parse(input)
    
    [Enum.sort(a), Enum.sort(b)]
    |> Enum.zip()
    |> Enum.reduce(0, fn {a, b}, acc ->
      acc + abs(a - b)
    end)
  end
end

Tests - Part 1

ExUnit.start(autorun: false)

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

  @input """
  3   4
  4   3
  2   5
  1   3
  3   9
  3   3
  """
  @expected 11

  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
  def solve(input) do
    IO.puts("--- Part Two ---")
    IO.puts("Result: #{run(input)}")
  end

  def run(input) do
    {a, b} = Parser.parse(input)
    freq = Enum.frequencies(b)

    Enum.reduce(a, 0, fn digit, acc ->
      acc + (digit * Map.get(freq, digit, 0))
    end)
  end
end

Tests - Part 2

ExUnit.start(autorun: false)

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

  @input """
  3   4
  4   3
  2   5
  1   3
  3   9
  3   3
  """
  @expected 31

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

ExUnit.run()

Solution - Part 2

PartTwo.solve(puzzle_input)