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

Day 01

2023/day-01.livemd

Day 01

Mix.install([
  {:kino, "~> 0.11"},
  {:nimble_parsec, "~> 1.4"}
])

example_input =
  Kino.Input.textarea("example input:")
  |> Kino.render()

real_input = Kino.Input.textarea("real input:")

Common

numbers = ~c"0123456789"
filter = &(&1 in numbers)

parse = fn input ->
  input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
end

process = fn input ->
  input
  |> Enum.map(&(to_charlist(&1) |> Enum.filter(filter)))
  |> Enum.map(&[hd(&1), List.last(&1)])
  |> Enum.map(&List.to_integer/1)
  |> Enum.sum()
end

Part 1

real_input
|> then(parse)
|> then(process)

Part 2

defmodule Replacer do
  import NimbleParsec

  replacements =
    for {<>, numeral} <-
          Enum.with_index(~w[one two three four five six seven eight nine], 1) do
      numeral = to_string(numeral)

      choice([
        string(numeral),
        string(head) |> lookahead(string(rest)) |> replace(numeral)
      ])
    end

  ignored = ignore(utf8_string([], 1))

  defparsec(:replace, repeat(choice(replacements ++ [ignored])))
end

real_input
|> then(parse)
|> Enum.map(
  &amp;case Replacer.replace(&amp;1) do
    {:ok, found, "", _, _, _} -> Enum.join(found)
  end
)
|> then(process)