96 lines
2.6 KiB
Nix
96 lines
2.6 KiB
Nix
{lib, ...}: input: let
|
|
|
|
abs = n: if n > 0 then n else -n;
|
|
|
|
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;};
|
|
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;};
|
|
|
|
toCharList = builtins.foldl'
|
|
({y, x, chars}: char:
|
|
if char == "." || char == "#" then {inherit y; x = x + 1; inherit chars;}
|
|
else if char == "\n" then {y = y + 1; x = 0; inherit chars;}
|
|
else {inherit y; x = x + 1; chars = chars ++ [{inherit x y char;}];}
|
|
)
|
|
{y = 0; x = 0; chars = [];}
|
|
;
|
|
|
|
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
|
|
# assumes width == height ¯\_(ツ)_/¯
|
|
size = assert amap.x == amap.y + 1; amap.x;
|
|
in amap.nodes
|
|
|> lib.concatLists
|
|
|> builtins.filter ({x, y}: x >= 0 && y >= 0 && x < size && y < size)
|
|
|> lib.unique
|
|
;
|
|
|
|
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;
|
|
|
|
in {
|
|
inherit addVec subVec toCharList toNodes toDeltas multVec modVec deltaToNodes minNode;
|
|
|
|
part1result = input
|
|
|> lib.trim
|
|
|> lib.stringToCharacters
|
|
|> toCharList
|
|
|> toNodes
|
|
|> getUniqueNodes
|
|
|> builtins.length
|
|
;
|
|
|
|
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
|
|
;
|
|
|
|
}
|