···
2
+
input = builtins.readFile ../../shared/04/input.txt;
3
+
lines = builtins.filter (s: builtins.isString s && s != "") (builtins.split "\n" input);
5
+
# Parse input into grid of booleans (true = @, false = .)
6
+
paperMap = builtins.map (line:
8
+
len = builtins.stringLength line;
9
+
indices = builtins.genList (i: i) len;
11
+
let ch = builtins.substring i 1 line;
12
+
in if ch == "@" then true else false
16
+
# Count accessible papers and return new map
17
+
accessiblePapers = map:
19
+
numRows = builtins.length map;
21
+
# Process all cells in one pass using foldl'
22
+
result = builtins.foldl' (state: rowIdx:
24
+
rowData = builtins.elemAt map rowIdx;
25
+
numCols = builtins.length rowData;
27
+
rowResult = builtins.foldl' (rowState: colIdx:
29
+
cell = builtins.elemAt rowData colIdx;
32
+
accessible = rowState.accessible;
33
+
newRow = rowState.newRow ++ [false];
37
+
# Check all 8 neighbors inline
39
+
if r < 0 || c < 0 || r >= numRows then false
41
+
let rd = builtins.elemAt map r;
42
+
in if c >= builtins.length rd then false
43
+
else builtins.elemAt rd c;
46
+
(if check (rowIdx - 1) colIdx then 1 else 0) +
47
+
(if check (rowIdx + 1) colIdx then 1 else 0) +
48
+
(if check rowIdx (colIdx + 1) then 1 else 0) +
49
+
(if check rowIdx (colIdx - 1) then 1 else 0) +
50
+
(if check (rowIdx - 1) (colIdx + 1) then 1 else 0) +
51
+
(if check (rowIdx + 1) (colIdx + 1) then 1 else 0) +
52
+
(if check (rowIdx - 1) (colIdx - 1) then 1 else 0) +
53
+
(if check (rowIdx + 1) (colIdx - 1) then 1 else 0);
55
+
isAccessible = fullAdj < 4;
57
+
accessible = rowState.accessible + (if isAccessible then 1 else 0);
58
+
newRow = rowState.newRow ++ [(if isAccessible then false else true)];
60
+
) { accessible = 0; newRow = []; } (builtins.genList (i: i) numCols);
62
+
accessible = state.accessible + rowResult.accessible;
63
+
newMap = state.newMap ++ [rowResult.newRow];
65
+
) { accessible = 0; newMap = []; } (builtins.genList (i: i) numRows);
68
+
# Part 1: Single iteration
69
+
part1 = (accessiblePapers paperMap).accessible;
71
+
# Part 2: Iterate until no more accessible papers
76
+
result = accessiblePapers state.map;
78
+
if result.accessible == 0 then state.total
80
+
map = result.newMap;
81
+
total = state.total + result.accessible;
83
+
in iterate { map = paperMap; total = 0; };
86
+
inherit part1 part2;