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/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) + +