70 lines
1.6 KiB
JavaScript
70 lines
1.6 KiB
JavaScript
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
|
|
);
|
|
},
|
|
};
|