— Day 5: Cafeteria —
Mix.install([{:kino_aoc, "~> 0.1"}])
Setup
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2025", "5", System.fetch_env!("LB_AOC_SESSION_COOKIE"))
test_input = Kino.Input.textarea("test_input")
test_input = Kino.Input.read(test_input)
defmodule Cafeteria do
def parse_db(input) do
[ranges, ingr_ids] = String.split(input, "\n\n")
fresh_ranges =
for range <- String.split(ranges) do
[low, high] = range |> String.split("-") |> Enum.map(&String.to_integer/1)
low..high
end
ingr_ids = ingr_ids |> String.split() |> Enum.map(&String.to_integer/1)
{fresh_ranges, ingr_ids}
end
def ranges_overlap?(r1, r2), do: !Range.disjoint?(r1, r2)
def merge_ranges(r1, r2), do: min(r1.first, r2.first)..max(r1.last, r2.last)
end
Part 1
import Cafeteria
# {fresh_ranges, ingr_ids} = Cafeteria.parse_db(test_input)
{fresh_ranges, ingr_ids} = Cafeteria.parse_db(puzzle_input)
Enum.sum_by(ingr_ids, fn id ->
if Enum.any?(fresh_ranges, &(id in &1)), do: 1, else: 0
end)
Part 2
import Cafeteria
# {fresh_ranges, _ingr_ids} = Cafeteria.parse_db(test_input)
{fresh_ranges, _ingr_ids} = Cafeteria.parse_db(puzzle_input)
[first_range | fresh_ranges] = Enum.sort(fresh_ranges)
fresh_ranges
|> Enum.reduce([first_range], fn next_range, [previous_range | rest] = acc ->
if ranges_overlap?(previous_range, next_range) do
[merge_ranges(previous_range, next_range) | rest]
else
[next_range | acc]
end
end)
|> Enum.sum_by(&Range.size/1)