aoc/2024/08/solution.nix

96 lines
2.6 KiB
Nix
Raw Permalink Normal View History

2024-12-08 15:01:56 +00:00
{lib, ...}: input: let
abs = n: if n > 0 then n else -n;
2024-12-08 13:08:57 +00:00
addVec = a: b: {x = a.x + b.x; y = a.y + b.y;};
subVec = a: b: {x = a.x - b.x; y = a.y - b.y;};
2024-12-08 15:01:56 +00:00
multVec = m: vec: {x = vec.x * m; y = vec.y * m;};
modVec = m: vec: {x = lib.mod vec.x m; y = lib.mod vec.y m;};
2024-12-08 13:08:57 +00:00
toCharList = builtins.foldl'
({y, x, chars}: char:
if char == "." || char == "#" then {inherit y; x = x + 1; inherit chars;}
2024-12-08 15:01:56 +00:00
else if char == "\n" then {y = y + 1; x = 0; inherit chars;}
2024-12-08 13:08:57 +00:00
else {inherit y; x = x + 1; chars = chars ++ [{inherit x y char;}];}
)
2024-12-08 15:01:56 +00:00
{y = 0; x = 0; chars = [];}
2024-12-08 13:08:57 +00:00
;
toNodes = {chars, ...}@amap: amap // {
nodes = map (antenna:
builtins.foldl' (acc: antenna2:
if antenna == antenna2 then acc
else if antenna.char != antenna2.char then acc
else let
delta = subVec antenna antenna2;
in acc ++ [(addVec antenna delta)]
) [] chars
) chars;
};
getUniqueNodes = amap: let
2024-12-08 15:01:56 +00:00
# assumes width == height ¯\_(ツ)_/¯
size = assert amap.x == amap.y + 1; amap.x;
2024-12-08 13:08:57 +00:00
in amap.nodes
|> lib.concatLists
2024-12-08 15:01:56 +00:00
|> builtins.filter ({x, y}: x >= 0 && y >= 0 && x < size && y < size)
2024-12-08 13:08:57 +00:00
|> lib.unique
;
2024-12-08 15:01:56 +00:00
cut = i: list: lib.sublist i (builtins.length list) list;
toDeltas = {chars, ...}@amap: amap // {
deltas = chars |> lib.imap0 (i: antenna: {
pos = {inherit (antenna) x y;};
deltas = chars |> cut i |> builtins.foldl' (acc: antenna2:
if antenna == antenna2 then acc
else if antenna.char != antenna2.char then acc
else let
delta = subVec antenna antenna2;
in acc ++ [delta]
) [];
});
};
deltaToNodes = size: {pos, delta}:
builtins.genList
(i: delta |> multVec i |> subVec (minNode size pos delta))
(size / (lib.max (abs delta.x) (abs delta.y)) + 1)
|> builtins.filter ({x, y}: x >= 0 && y >= 0 && x < size && y < size)
;
minNode = size: pos: delta: let sub = addVec pos delta; in
if sub.x < 0 || sub.y < 0 || sub.x >= size || sub.y >= size then pos
else minNode size sub delta;
2024-12-08 13:08:57 +00:00
in {
2024-12-08 15:01:56 +00:00
inherit addVec subVec toCharList toNodes toDeltas multVec modVec deltaToNodes minNode;
2024-12-08 13:08:57 +00:00
2024-12-08 15:01:56 +00:00
part1result = input
2024-12-08 13:08:57 +00:00
|> lib.trim
|> lib.stringToCharacters
|> toCharList
|> toNodes
|> getUniqueNodes
|> builtins.length
;
2024-12-08 15:01:56 +00:00
part2result = input
|> lib.trim
|> lib.stringToCharacters
|> toCharList
|> toDeltas
|> ({deltas,x,...}: deltas |> map (antenna:
antenna.deltas |> map (delta: deltaToNodes x {
inherit delta;
inherit (antenna) pos;
}
)))
|> lib.concatLists
|> lib.concatLists
|> lib.unique
|> builtins.length
;
2024-12-08 13:08:57 +00:00
}