aoc/2024/05/solution.nix
2024-12-05 07:41:48 +00:00

70 lines
1.7 KiB
Nix

{lib, ...}: input: rec {
content = lib.trim input;
parts = let
sects = lib.splitString "\n\n" content;
in {
rules = builtins.elemAt sects 0
|> lib.splitString "\n"
|> map (lib.splitString "|")
|> builtins.foldl' (acc: el:
let
b = builtins.elemAt el 0;
a = builtins.elemAt el 1;
in
acc // {
${b} = acc.${b} or [] ++ [a];
}) {};
updates = builtins.elemAt sects 1
|> lib.splitString "\n"
|> map (lib.splitString ",");
}
;
check = {rules, update}: builtins.attrNames rules
|> map
(ruleName: let
i = lib.lists.findFirstIndex (x: x == ruleName) null update;
before = if isNull i then [] else lib.sublist (0) (i) update;
in {
inherit before;
rules = rules.${ruleName};
})
|> builtins.foldl'
(valid: {rules, before}: valid && builtins.all (e: !builtins.any (r: r == e) rules) before)
true
;
getValid = {rules, updates}:
builtins.filter (update: check {inherit rules update;}) updates;
getMiddles = list: list
|> map (row: builtins.elemAt row ((builtins.length row) / 2))
|> map lib.strings.toInt
;
sum = builtins.foldl' (a: n: a + n) 0;
part1result = parts
|> getValid
|> getMiddles
|> sum
;
sortUpdate = rules: update:
builtins.sort (fst: snd: builtins.any (rule: rule == fst) (rules.${snd} or [])) update
;
getInvalid = {rules, updates}:
builtins.filter (update: !check {inherit rules update;}) updates;
part2result = parts
|> getInvalid
|> map (sortUpdate parts.rules)
|> getMiddles
|> sum
;
}