70 lines
1.7 KiB
Nix
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
|
||
|
;
|
||
|
|
||
|
}
|