diff --git a/2024/11/solution.nix b/2024/11/solution.nix index ccc3769..4411e38 100644 --- a/2024/11/solution.nix +++ b/2024/11/solution.nix @@ -3,6 +3,8 @@ inherit (lib.strings) toIntBase10; in input: rec { + sum = foldl' add 0; + blinkStone = stone: count: if toIntBase10 stone == 0 then [{ "1" = count; }] else let @@ -21,19 +23,17 @@ in input: rec { ; bfast = stones: stones - |> (builtins.mapAttrs (stone: blinkStone stone)) + |> builtins.mapAttrs blinkStone |> attrValues |> concatLists - |> addStones + |> builtins.zipAttrsWith (stone: sum) ; bfastt = times: stones: - if times == 0 then stones |> attrValues |> foldl' add 0 + if times == 0 then stones |> attrValues |> sum else bfastt (times - 1) (bfast stones) ; - addStones = builtins.zipAttrsWith (stone: foldl' add 0); - initialStones = input |> lib.trim |> lib.splitString " " diff --git a/2024/12/example.txt b/2024/12/example.txt new file mode 100644 index 0000000..b41163a --- /dev/null +++ b/2024/12/example.txt @@ -0,0 +1,4 @@ +AAAA +BBCD +BBCC +EEEC diff --git a/2024/12/example2.txt b/2024/12/example2.txt new file mode 100644 index 0000000..50a7304 --- /dev/null +++ b/2024/12/example2.txt @@ -0,0 +1,5 @@ +OOOOO +OXOXO +OOOOO +OXOXO +OOOOO diff --git a/2024/12/example3.txt b/2024/12/example3.txt new file mode 100644 index 0000000..85b768f --- /dev/null +++ b/2024/12/example3.txt @@ -0,0 +1,10 @@ +RRRRIICCFF +RRRRIICCCF +VVRRRCCFFF +VVRCCCJFFF +VVVVCJJCFE +VVIVCCJJEE +VVIIICJJEE +MIIIIIJJEE +MIIISIJEEE +MMMISSJEEE diff --git a/2024/12/example4.txt b/2024/12/example4.txt new file mode 100644 index 0000000..5818d30 --- /dev/null +++ b/2024/12/example4.txt @@ -0,0 +1,5 @@ +EEEEE +EXXXX +EEEEE +EXXXX +EEEEE diff --git a/2024/12/example5.txt b/2024/12/example5.txt new file mode 100644 index 0000000..f7cd38f --- /dev/null +++ b/2024/12/example5.txt @@ -0,0 +1,6 @@ +AAAAAA +AAABBA +AAABBA +ABBAAA +ABBAAA +AAAAAA diff --git a/2024/12/solution.js b/2024/12/solution.js new file mode 100644 index 0000000..72e34a2 --- /dev/null +++ b/2024/12/solution.js @@ -0,0 +1,50 @@ + +const input = (await Bun.file(Bun.argv[2]).text()).trim() + +let map = input.split("\n") + +const dirs = [[-1,0], [1,0], [0, -1], [0, 1]]; +const height = map.length; +const width = height; + +const key = (x,y) => x + y*width; +const visited = new Set(); + +function search(x,y) { + if (visited.has(key(x,y))) { + return {area: 0, perimeter: 0} + } + visited.add(key(x,y)) + const letter = map[y][x] + let perimeter = 0 + let area = 1 + for (const [dx, dy] of dirs) { + const nletter = map[y + dy]?.[x + dx]; + if (letter !== nletter) { + perimeter += 1 + continue + } + const n = search(x + dx, y + dy) + area += n.area + perimeter += n.perimeter + } + + return {area, perimeter} +} + +const regions = []; + +for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + if (visited.has(key(x,y))) continue + regions.push(search(x,y)) + } +} + +let cost = 0 +for (const {area, perimeter} of regions) { + cost += area * perimeter +} +console.log(cost) + + diff --git a/2024/12/solution2.js b/2024/12/solution2.js new file mode 100644 index 0000000..65d71f7 --- /dev/null +++ b/2024/12/solution2.js @@ -0,0 +1,63 @@ + +const input = (await Bun.file(Bun.argv[2]).text()).trim() + +let map = input.split("\n") + +const dirs = [[-1,0], [0,-1], [1,0], [0, 1]]; +const height = map.length; +const width = height; + +const key = (x,y) => x + y*width; +const vkey = (x,y) => y + x*height; +const visited = new Set(); + +function search(x,y) { + if (visited.has(key(x,y))) { + return {area: 0, hsides: new Set()} + } + visited.add(key(x,y)) + const letter = map[y][x] + let area = 1 + let hsides = new Set() + for (const [dx, dy] of dirs) { + const nletter = map[y + dy]?.[x + dx]; + if (letter !== nletter) { + if (dx === 0) { + hsides.add({y: y+dy/2, key: key(x,y)}) + } + continue + } + const n = search(x + dx, y + dy) + area += n.area + hsides = hsides.union(n.hsides) + } + + return {area, hsides} +} + +const regions = []; + +for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + if (visited.has(key(x,y))) continue + regions.push(search(x,y)) + } +} + + +let cost = 0; +for (const {area, hsides} of regions) { + // hacky filter of all perimeter nodes to extract adjacent + const horizontal = Array.from(hsides) + .sort((a, b) => a.key - b.key) + .sort((a, b) => a.y - b.y) + .filter(({y, key}, i, a) => a[i-1]?.key + 1 !== key || a[i-1]?.y !== y) + .length + + // there's always an equal amount of horizontal and vertical sides + cost += area * (horizontal * 2) +} + +console.log(cost) + +