Powered by AppSignal & Oban Pro

Advent of Code 2023 Day 1 (Another Solution for Part 2)

2023/day-01-alt.livemd

Advent of Code 2023 Day 1 (Another Solution for Part 2)

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

Section

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "1", System.fetch_env!("LB_AOC_SESSION"))
reverse_puzzle_input = String.reverse(puzzle_input)
word_map =
  ~w[
    one
    two
    three
    four
    five
    six
    seven
    eight
    nine
  ]
  |> Enum.zip_with(1..9, fn w, n -> {w, n} end)
  |> Map.new()
  |> Map.merge(Map.new(0..9, &{to_string(&1), &1}))
reverse_word_map =
  Map.new(word_map, fn {k, v} ->
    {String.reverse(k), v}
  end)
regex = word_map |> Map.keys() |> Enum.join("|") |> Regex.compile!()
reverse_regex = reverse_word_map |> Map.keys() |> Enum.join("|") |> Regex.compile!()
get_first_nums = fn input, word_map, regex ->
  input
  |> String.split("\n")
  |> Stream.flat_map(fn line ->
    Regex.run(regex, line)
  end)
  |> Enum.map(&word_map[&1])
end
first_digits = get_first_nums.(puzzle_input, word_map, regex)
last_digits = get_first_nums.(reverse_puzzle_input, reverse_word_map, reverse_regex)
first_digits
# ๐Ÿ‘‡ Here's the interesting thing. You don't need to reverse `last_digits` before zipping.
|> Enum.zip_with(last_digits, &(&1 * 10 + &2))
|> Enum.sum()
# ๐Ÿ‘‡ This works too.
Enum.sum(first_digits) * 10 + Enum.sum(last_digits)