Advent of Code - Day 5
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Problem
https://adventofcode.com/2024/day/5
I have yet to complete part 2. I feel it could be done with topological sort of rules, but wanted to find another solution.
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2024", "5", System.fetch_env!("LB_AOC_SESSION"))
defmodule Day5 do
def parse_rules(rules) do
String.split(rules, ["\n", "|"], trim: true)
|> Enum.map(&String.to_integer(&1))
|> Enum.chunk_every(2, 2)
|> Enum.reduce(%{}, fn [a,b], map ->
map |> Map.update(a, MapSet.new([b]), fn set -> MapSet.put(set, b) end)
|> Map.update(b, MapSet.new(), fn set -> set end)
end)
end
def parse(str) do
[rules, updates] = String.split(str, "\n\n")
updates = String.split(updates, "\n") |> Enum.map(fn x ->
String.split(x, ",") |> Enum.map(&String.to_integer/1)
end)
rules = parse_rules(rules)
{rules, updates}
end
def correct_order?([], _), do: true
def correct_order?([page | pages], rules) do
rule = Map.fetch!(rules, page)
Enum.all?(pages, &Enum.member?(rule, &1)) and correct_order?(pages, rules)
end
def add_middle_pages(updates) do
Enum.reduce(updates, 0, fn x, acc ->
acc + Enum.at(x, div(length(x),2))
end)
end
def solve_part1(str) do
{rules, updates } = parse(str)
Enum.filter(updates, fn pages ->
correct_order?(pages, rules)
end)
|> add_middle_pages()
end
end
example_input = "47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13
75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47"
Day5.solve_part1(puzzle_input)