Skip to content

Latest commit

 

History

History
145 lines (115 loc) · 3.1 KB

d01.livemd

File metadata and controls

145 lines (115 loc) · 3.1 KB

AoC 2024, Day 1

Mix.install([
  {:kino, "~> 0.11.0"}
])

Solution

defmodule D01 do
  @digits_regex ~r/\d/
  @digits_regex2 ~r/(?<digit>(\d))|(?<digit_name>(one)|(two)|(three)|(four)|(five)|(six)|(seven)|(eight)|(nine))/

  def read_input() do
    Kino.FS.file_path("d01.bin")
    |> File.read!()
    |> String.split("\n", trim: true)
  end

  defp to_calibration_value(line) when is_binary(line) do
    digits = Regex.scan(@digits_regex, line) |> Enum.concat()
    String.to_integer(hd(digits) <> List.last(digits))
  end

  def p1(input) when is_list(input) do
    Enum.map(input, &to_calibration_value/1) |> Enum.sum()
  end

  defp convert_digit(digit) when is_binary(digit) do
    case digit do
      "one" -> 1
      "two" -> 2
      "three" -> 3
      "four" -> 4
      "five" -> 5
      "six" -> 6
      "seven" -> 7
      "eight" -> 8
      "nine" -> 9
      _ -> digit
    end
    |> to_string()
  end

  defp scan_with_overlaps(regex, line) when is_binary(line) do
    scan_with_overlaps(
      regex,
      line,
      Regex.run(regex, line, return: :index, capture: :first),
      []
    )
  end

  defp scan_with_overlaps(regex, line, [{idx, len}], matches) do
    scan_with_overlaps(
      regex,
      line,
      Regex.run(regex, line, return: :index, capture: :first, offset: idx + 1),
      [String.slice(line, idx, len) | matches]
    )
  end

  defp scan_with_overlaps(_regex, _line, nil, matches), do: Enum.reverse(matches)

  defp to_calibration_value2(line) when is_binary(line) do
    digits = scan_with_overlaps(@digits_regex2, line) |> Enum.map(&convert_digit/1)
    String.to_integer(hd(digits) <> List.last(digits))
  end

  def p2(input) do
    Enum.map(input, &to_calibration_value2/1) |> Enum.sum()
  end
end
{:module, D01, <<70, 79, 82, 49, 0, 0, 19, ...>>, {:p2, 1}}
ExUnit.start(autorun: false)

defmodule D01Test do
  use ExUnit.Case, async: true

  test "part 1 works" do
    res =
      D01.p1([
        "1abc2",
        "pqr3stu8vwx",
        "a1b2c3d4e5f",
        "treb7uchet"
      ])

    assert res == 142

    input = D01.read_input()
    assert D01.p1(input) == 55130
  end

  test "part 2 works" do
    res =
      D01.p2([
        "two1nine",
        "eightwothree",
        "abcone2threexyz",
        "xtwone3four",
        "4nineeightseven2",
        "zoneight234",
        "7pqrstsixteen"
      ])

    assert res == 281

    input = D01.read_input()
    assert D01.p2(input) == 54985
  end
end

ExUnit.run()
..
Finished in 0.02 seconds (0.02s async, 0.00s sync)
2 tests, 0 failures

Randomized with seed 647997
%{total: 2, failures: 0, excluded: 0, skipped: 0}