const { Glib, Maps, Sets, Vector, twodee } = require('../../lib'); const parse = (input) => { const pairs = Glib.fromLines(input).map((i) => i.split(')')).array; const parents = pairs.glib.map((pair) => pair.safeReverse()).toMap(); const children = pairs.glib.toMapSet(); const points = new Map( pairs.glib .flatMap((i) => i) .unique() .map((point) => [ point, { children: children.get(point), parent: parents.get(point), }, ]), ); return points; }; const count = (map, source = 'COM', depth = 0n) => { return ( (map.get(source).children || []).glib .map((name) => count(map, name, depth + 1n)) .sum() + depth ); }; const distance = (source, destination, info) => { let current = source; let distance = 0n; while (current !== destination && current !== 'COM') { distance++; current = info.get(current).parent; } if (current !== destination) { throw new Error('no link (toward COM)'); } return distance; }; const allParents = (source, input) => new Glib( (function*() { let current = source; while (current !== 'COM') { current = input.get(current).parent; yield current; } })(), ); module.exports = { '1': (input) => count(parse(input), 'COM'), 2: (input) => { input = parse(input); return ( Sets.and(allParents('YOU', input).set, allParents('SAN', input).set) .glib.map( (midpoint) => distance('YOU', midpoint, input) + distance('SAN', midpoint, input), ) .min() - 2n ); }, };