Advent of Code - Day 14 - Part 2
https://adventofcode.com/2023/day/14unknown
javascript
a year ago
4.0 kB
93
Indexable
const fs = require('fs'); const path = require('path'); const { DateTime } = require('luxon'); const startTime = DateTime.now(); const inputPath = path.join(__dirname, 'data', 'input.txt'); const lines = fs .readFileSync(inputPath, { encoding: 'utf8' }) .trim() .split('\n') .map((line) => line.trim().split('')); const FINAL_CYCLE = 1_000_000_000; const directions = ['n', 'w', 's', 'e']; let rockRows = []; let uniqueSnapshots = []; let minRunsRequired = FINAL_CYCLE; let run = 0; for (; run < minRunsRequired; ++run) { rockRows.length = 0; for (const direction of directions) { for (let i = 0; direction === 'n' || direction === 's' ? i < lines[0].length : i < lines.length; ++i) { let firstDot = -1; for ( let j = direction === 'n' || direction === 'w' ? 0 : direction === 's' ? lines.length - 1 : lines[0].length - 1; direction === 'n' ? j < lines.length : direction === 'w' ? j < lines[0].length : j >= 0; direction === 'n' || direction === 'w' ? ++j : --j ) { function get(outer, inner) { if (direction === 'n' || direction === 's') return lines[inner][outer]; return lines[outer][inner]; } function getY(outer, inner) { if (direction === 'n' || direction === 's') return inner; return outer; } function set(outer, inner, val) { if (direction === 'n' || direction === 's') { lines[inner][outer] = val; } else { lines[outer][inner] = val; } } function addRockWeight(weight) { if (direction === directions[directions.length - 1]) { rockRows.push(weight); } } if (get(i, j) === '.') { if (firstDot === -1) { firstDot = j; } else { continue; } } else if (get(i, j) === '#') { firstDot = -1; } else if (get(i, j) === 'O') { if (firstDot > -1) { set(i, firstDot, 'O'); set(i, j, '.'); j = firstDot; addRockWeight(lines.length - getY(i, firstDot)); firstDot = -1; } else { addRockWeight(lines.length - getY(i, j)); continue; } } } } } // Try to find a quicker minimum runs required if (minRunsRequired === FINAL_CYCLE) { const snapshot = lines.map((row) => row.reduce((p, c) => p + c)).reduce((p, c) => p + '\n' + c); const index = uniqueSnapshots.indexOf(snapshot); if (index !== -1) { const duplicateItems = uniqueSnapshots.length - index; const itemsIntoDupSet = (FINAL_CYCLE - uniqueSnapshots.length) % duplicateItems; minRunsRequired = uniqueSnapshots.length + // Elements before duplicates start itemsIntoDupSet + // How far into the set of duplicate numbers we will be on the final cycle (itemsIntoDupSet === 0 ? itemsIntoDupSet : 0); // Since we needed an additional run before recognising duplicates, we'll need to pad an extra duplicate set if the final cycle ends at the end of the duplicate set } else { uniqueSnapshots.push(snapshot); } } } console.log('final run', run); console.log(rockRows.reduce((p, c) => p + c, 0)); console.log(DateTime.now().diff(startTime).valueOf() + ' millis');
Editor is loading...
Leave a Comment