const { Glib, Maps } = require('../../lib'); const parse = (input) => { return new Glib( (function*() { let current = null; let awake = true; for (const line of Glib.fromLines(input).array.sort()) { const [datePortion, actionPortion] = line.split('] '); if (actionPortion.endsWith('begins shift')) { if (current != null) { yield current; current = null; } current = { guard: BigInt(actionPortion.split(' ')[1].slice(1)), schedule: [], }; awake = true; } else if (actionPortion === 'wakes up') { if (awake) { continue; } awake = true; current.schedule.push(BigInt(datePortion.split(':')[1])); } else if (actionPortion === 'falls asleep') { if (!awake) { continue; } awake = false; current.schedule.push(BigInt(datePortion.split(':')[1])); } else { throw new Error('bad line'); } } yield current; })(), ); }; module.exports = { '1': (input) => { input = parse(input).array; const chosen = input.glib .map(({ guard, schedule }) => [ guard, schedule.glib .chunk(2) .map(([a, b]) => b - a) .sum(), ]) .reduce((a, pair) => Maps.add(a, new Map([pair])), new Map()) .glibEntries.reduce((a, b) => (a[1] > b[1] ? a : b))[0]; return ( chosen * input.glib .filter(({ guard }) => guard === chosen) .flatMap(({ schedule }) => schedule.glib .chunk(2) .flatMap(([start, end]) => Glib.fromSequence(start, end - 1n)), ) .frequency() .glibEntries.reduce((a, b) => (a[1] > b[1] ? a : b))[0] ); }, 2: (input) => parse(input) .flatMap(({ guard, schedule }) => schedule.glib .chunk(2) .flatMap(([start, end]) => Glib.fromSequence(start, end - 1n)) .map((minute) => `${guard},${minute}`), ) .frequency() .glibEntries.reduce((a, b) => (a[1] > b[1] ? a : b))[0] .split(',') .glib.toInts() .product(), };