55 lines
2.0 KiB
Nix
55 lines
2.0 KiB
Nix
with import ../../util.nix;
|
|
|
|
let
|
|
input = map (line: map toInt (stringToCharacters line)) (splitString "\n" (readFile ./input));
|
|
input' = transpose input;
|
|
|
|
visibleTrees =
|
|
let
|
|
# counts the number of trees visible from a starting
|
|
hiddenTreesLineDir = l:
|
|
(foldl
|
|
(acc: x:
|
|
if x > acc.highest then { highest = x; out = acc.out ++ [true]; } # visible
|
|
else { inherit (acc) highest; out = acc.out ++ [false]; }) # hidden
|
|
{ highest = -1; out = []; } l).out;
|
|
hiddenTreesLine = l:
|
|
mergeLists or (hiddenTreesLineDir l) (reverseList (hiddenTreesLineDir (reverseList l)));
|
|
hiddenTreesGrid = map hiddenTreesLine;
|
|
hiddenTreesRows = hiddenTreesGrid input;
|
|
hiddenTreesCols = hiddenTreesGrid input';
|
|
mergeGrid = f:
|
|
let
|
|
w = length hiddenTreesCols;
|
|
h = length hiddenTreesRows;
|
|
in genList (i: genList (j: f (elemAt (elemAt hiddenTreesCols i) j) (elemAt (elemAt hiddenTreesRows j) i) ) h) w;
|
|
in mergeGrid or;
|
|
|
|
countVisibleRow = l: sum (map boolToInt l);
|
|
countVisible = sum (map countVisibleRow visibleTrees);
|
|
|
|
# number of trees visible from each point as a score
|
|
visibleScore =
|
|
let
|
|
getCol = x: map (l: elemAt l x) input;
|
|
getRow = y: elemAt input y;
|
|
left = x: l: reverseList (take x l);
|
|
right = x: l: drop (x+1) l;
|
|
visibleCountDir = treeHeight: l:
|
|
(foldl (acc: x:
|
|
if acc.stop == false then
|
|
if x >= treeHeight then { cnt = acc.cnt +1; stop = true; }
|
|
else { cnt = acc.cnt +1; stop = false; }
|
|
else acc) { cnt = 0; stop = false; } l).cnt;
|
|
treeScore = x: y: v:
|
|
(visibleCountDir v (left x (getRow y)))
|
|
* (visibleCountDir v (right x (getRow y)))
|
|
* (visibleCountDir v (left y (getCol x)))
|
|
* (visibleCountDir v (right y (getCol x)));
|
|
in map2D treeScore input;
|
|
maxVisibleScore = foldr (x: max (maxList x)) 0 visibleScore;
|
|
|
|
in rec {
|
|
part1 = countVisible;
|
|
part2 = maxVisibleScore;
|
|
} |