advent-of-code

Entries to advent of code, multiple years
git clone git://git.finwo.net/misc/advent-of-code
Log | Files | Refs

commit 3eefdb2273f806d24906a42adde838478009e9ac
parent 247b36212dd6ce2855956d336deedbf0dbd53917
Author: finwo <finwo@pm.me>
Date:   Wed, 24 Dec 2025 17:42:11 +0100

Completed 2025/04

Diffstat:
A2025/04/example.txt | 10++++++++++
A2025/04/index.js | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/2025/04/example.txt b/2025/04/example.txt @@ -0,0 +1,10 @@ +..@@.@@@@. +@@@.@.@.@@ +@@@@@.@.@@ +@.@@@@..@. +@@.@@@@.@@ +.@@@@@@@.@ +.@.@.@.@@@ +@.@@@.@@@@ +.@@@@@@@@. +@.@.@@@.@. diff --git a/2025/04/index.js b/2025/04/index.js @@ -0,0 +1,111 @@ +#!/usr/bin/env node + +const fs = require('node:fs'); + +const grid = fs + .readFileSync('input', 'utf-8') + .split('\r\n').join('\n') + .split('\r').join('\n') + .split('\n') + .map(str => str.trim()) + .filter(str => str) + .map(str => str.split('')) + .map(row => row.map(c => c === '@')) + ; + +const buildNeighbours = (grid) => { + const neighbours = grid + .map(row => row.map(() => 0)); + + // Mark adjacent locations as having 'current' as neighbour + for(let y = 0; y < grid.length; y++) { + const row = grid[y]; + for(let x = 0; x < row.length ; x++) { + // Skip if we're empty + if (!grid[y][x]) continue; + for(let ny = -1; ny <= 1; ny++) { + if ((y+ny) < 0) continue; + if ((y+ny) >= grid.length) continue; + for(let nx = -1; nx <= 1; nx++) { + if ((x+nx) < 0) continue; + if ((x+nx) >= row.length) continue; + // Skip self + if (nx === 0 && ny === 0) continue; + neighbours[y+ny][x+nx]++; + } + } + } + } + + return neighbours; +}; + +const buildReachable = (grid, neighbours) => { + // Mark reachable rolls in part 1 + let count = 0; + const _map = grid.map(row => row.map(() => false)); + for(let y = 0; y < grid.length; y++) { + const row = grid[y]; + for(let x = 0; x < row.length ; x++) { + // Skip if we're empty + if (!grid[y][x]) continue; + if (neighbours[y][x] >= 4) continue; + _map[y][x] = true; + count++; + } + } + return { + _map, + count, + }; +}; + +const removeReachable = (grid, reachableMap) => { + for(let y = 0; y < grid.length; y++) { + const row = grid[y]; + for(let x = 0; x < row.length ; x++) { + if (reachableMap[y][x]) row[x] = false; + } + } +}; + +// Debug display origin grid +const displayGrid = grid => { + process.stdout.write( + grid.map(row => row.map(c => c ? '@' : '.').join('')).join('\n') + '\n\n' + ); +}; + +// Debug display +const displayReachable = (grid, reachableMap) => { + process.stdout.write( + grid.map( + (row,y) => row.map( + (roll,x) => reachableMap[y][x] ? 'x' : roll ? '@' : '.' + ).join('') + ).join('\n') + '\n\n' + ); +} + +let neighbours = buildNeighbours(grid); +let reachable = buildReachable(grid, neighbours); +const part1 = reachable.count; + +let totalRemoved = 0; + +console.log(`Initial state:`); +displayGrid(grid); + +while(reachable.count) { + console.log(`Remove ${reachable.count} rolls of paper:`); + totalRemoved += reachable.count; + displayReachable(grid, reachable._map); + + removeReachable(grid, reachable._map); + neighbours = buildNeighbours(grid); + reachable = buildReachable(grid, neighbours); +} + +process.stdout.write('\n'); +process.stdout.write(`------[ Part 1: ${part1} ]------\n`); +process.stdout.write(`------[ Part 2: ${totalRemoved} ]------\n`);