Powered by AppSignal & Oban Pro

Advent of code day 02

2025/livebooks/day-02.livemd

Advent of code day 02

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

Setup input

example = Kino.Input.textarea("Please paste your input example:")
input = Kino.Input.textarea("Please paste your real input:")

Part 01

repeated? = fn s ->
  len = String.length(s)
  rem(len, 2) == 0 and
    not String.starts_with?(s, "0") and
    String.slice(s, 0, div(len, 2)) ==
      String.slice(s, div(len, 2), div(len, 2))
end

example
|> Kino.Input.read()
|> String.split(",")
|> Enum.flat_map(fn part ->
  [a, b] = part |> String.split("-") |> Enum.map(&String.trim(&1) |> String.to_integer)
  Enum.to_list(a..b)
end)
|> Enum.chunk_every(50_000) 
|> Task.async_stream(
     fn chunk ->
       Enum.reduce(chunk, 0, fn n, acc ->
         if repeated?.(Integer.to_string(n)) do
           acc + n
         else
           acc
         end
       end)
     end,
     max_concurrency: System.schedulers_online(),
     timeout: :infinity
   )
|> Enum.reduce(0, fn {:ok, partial_sum}, acc -> acc + partial_sum end)

Part 02

# Cute little trick from elixir forum, beautiful 
defmodule Repeatter do 
  
  def repeats?([a, a]), do: true
  def repeats?([a, a, a]), do: true
  def repeats?([a, b, a, b]), do: true
  def repeats?([a, a, a, a, a]), do: true
  def repeats?([a, b, a, b, a, b]), do: true
  def repeats?([a, b, c, a, b, c]), do: true
  def repeats?([a, a, a, a, a, a, a]), do: true
  def repeats?([a, b, a, b, a, b, a, b]), do: true
  def repeats?([a, b, c, d, a, b, c, d]), do: true
  def repeats?([a, a, a, a, a, a, a, a, a]), do: true
  def repeats?([a, b, c, a, b, c, a, b, c]), do: true
  def repeats?([a, b, a, b, a, b, a, b, a, b]), do: true
  def repeats?([a, b, c, d, e, a, b, c, d, e]), do: true
  def repeats?(_), do: false

end

example
|> Kino.Input.read()
|> String.split(",")
|> Enum.flat_map(fn part ->
  [a, b] = part |> String.split("-") |> Enum.map(&String.trim(&1) |> String.to_integer)
  Enum.to_list(a..b)
end)
|> Enum.chunk_every(50_000)    
|> Task.async_stream(
     fn chunk ->
       Enum.reduce(chunk, 0, fn n, acc ->
         if Repeatter.repeats?(Integer.to_string(n) |> String.split("", trim: true)) do
           acc + n
         else
           acc
         end
       end)
     end,
     max_concurrency: System.schedulers_online(),
     timeout: :infinity
   )
|> Enum.reduce(0, fn {:ok, partial_sum}, acc -> acc + partial_sum end)