Day 02
Mix.install([:kino_aoc])
Parsing
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2025", "2", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
ranges =
puzzle_input
|> String.trim()
|> String.split(",")
|> Enum.map(fn range ->
range
|> String.split("-")
|> Enum.map(&String.to_integer/1)
|> then(&apply(Range, :new, &1))
end)
|> Enum.sort_by(& &1.last)
Implementation
defmodule ElfRanges do
def valid?(num) do
len = floor(:math.log10(num)) + 1
valid_n?(num, len, 2)
end
def valid_any?(num) do
len = floor(:math.log10(num)) + 1
Enum.all?(2..len//1, &valid_n?(num, len, &1))
end
def valid_n?(num, len, n) do
if rem(len, n) == 0 do
step = 10 ** div(len, n)
Stream.unfold(num, fn
0 -> nil
val -> {rem(val, step), div(val, step)}
end)
|> Enum.dedup()
|> then(&(not match?([_], &1)))
else
true
end
end
end
Part 1
ranges
|> Stream.flat_map(& &1)
|> Stream.reject(&ElfRanges.valid?/1)
|> Enum.sum()
Part 2
ranges
|> Stream.flat_map(& &1)
|> Stream.reject(&ElfRanges.valid_any?/1)
|> Enum.sum()