Advent of Code - Day 14 - Part 2
https://adventofcode.com/2023/day/14unknown
javascript
2 years ago
4.0 kB
103
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