import { solvables } from "../main.ts"; import type { Solvable } from "../solvable.ts"; import { readInput } from "../utils.ts"; class DayFive implements Solvable { input: string[] = readInput('05').split('\n\n') rules: number[][] = this.input[0].split('\n').map((input: string) => input.split('|').map(rule => Number.parseInt(rule))) updates: number[][] = this.input[1].split('\n').map(line => line.split(',').map(update => Number.parseInt(update))) // generated in part 1 for part 2 invalidUpdates: number[][] = [] followsRules = (update: number[]): [boolean, number, number] => { for (const rule of this.rules) { const left = update.findIndex((val) => val === rule[0]) const right = update.findIndex((val) => val === rule[1]) if (left === -1 || right === -1) continue if (left > right) return [false, left, right] } return [true, -1, -1] } middles = (updates: number[][]): number => updates .map((update: number[]) => update[Math.floor(update.length / 2)]) .reduce((prev, curr) => prev + curr) public part1(): Solvable { const validUpdates: number[][] = [] this.updates.forEach(update => { if (this.followsRules(update)[0]) { validUpdates.push(update) } else { // store these for part 2 this.invalidUpdates.push(update) } }) const result = this.middles(validUpdates) console.log(result) return this } public part2(): Solvable { const invalidUpdates = this.invalidUpdates const sort = (update: number[]): number[] => { const [compliant, leftIdx, rightIdx] = this.followsRules(update) if (!compliant) { // remove offending item and just move it to the back const removedLeft = update.splice(leftIdx, 1)[0] const rebuiltUpdate = [...update.slice(0, rightIdx), removedLeft, ...update.slice(rightIdx)] return sort(rebuiltUpdate) } else { return update } } const fixedUpdates = invalidUpdates.map(updates => sort(updates)) const result = this.middles(fixedUpdates) console.log(result) return this } } solvables.push(new DayFive())