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

Day 1

2023/01.livemd

Day 1

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

Part 1

example = """
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
"""

expected = [12, 38, 15, 77]
[12, 38, 15, 77]
defmodule Part1 do
  def run(values) do
    for value <- String.split(values, "\n", trim: true) do
      digits =
        value
        |> String.to_charlist()
        |> Enum.filter(&amp;(&amp;1 in ?0..?9))

      [List.first(digits), List.last(digits)]
      |> String.Chars.to_string()
      |> String.to_integer()
    end
  end
end

Part1.run(example) == expected
true
input = Kino.Input.textarea("Puzzle Input")
Kino.Input.read(input)
|> Part1.run()
|> Enum.sum()
53921

Part 2

example = """
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
"""

expected = [29, 83, 13, 24, 42, 14, 76]
[29, 83, 13, 24, 42, 14, 76]
defmodule Part2 do
  @regex ~S(\d|zero|one|two|three|four|five|six|seven|eight|nine)

  @digits ~r/#{@regex}/
  # hacky workaround for overlapping matches
  @lastdigits ~r/.*(#{@regex}).*$/

  @integers ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]

  def run(values) do
    for value <- String.split(values, "\n", trim: true) do
      [Regex.run(@digits, value), Regex.run(@lastdigits, value, capture: :all_but_first)]
      |> List.flatten()
      |> Enum.map(&amp;(Enum.find_index(@integers, fn x -> x == &amp;1 end) || String.to_integer(&amp;1)))
      |> then(&amp;(List.first(&amp;1) * 10 + List.last(&amp;1)))
    end
  end
end

Part2.run(example) == expected
true
Kino.Input.read(input)
|> Part2.run()
|> Enum.sum()
54676