aoc/2020/16/part2.js

77 lines
2.6 KiB
JavaScript
Raw Normal View History

2020-12-16 19:15:23 +00:00
const fs = require('fs');
const [fields, myTicket, nearbyTickets] = fs.readFileSync('./input.txt', 'utf-8').split('\n\n');
const allValid = new Set(); // a set of all values that are within any of the ranges
const allFieldNames = []; // an array of all names that the fields have
const fieldsValid = fields // an array containing a set of all values within the ranges for each field
.split('\n')
.map(f => {
allFieldNames.push(f.split(':')[0])
return f.match(/\d+-\d+/g)
.reduce((a, v) => {
let [start, end] = v.split('-').map(a=>parseInt(a));
for (let j = start; j <= end; j++) {
a.add(j);
allValid.add(j);
}
return a;
}, new Set())
})
// for example class: 1-3 \ row: 0-1 or 4-5 would become
// allFieldNames = ['class', 'row' ]
// fieldsValid = [{1,2,3}, {0,1,4,5}]
// get all the valid tickets
const tickets = nearbyTickets
.split('\n')
.slice(1)
.map(t => t.split(',').map(v => parseInt(v)))
.filter(ticket =>
ticket.every(e => allValid.has(e))
)
let entrysOptions = [];
// iterate thru each entry of the valid tickets
for (let entryNum = 0; entryNum < tickets[0].length; entryNum++) {
// assume that this entry could be one of any of the fields
let couldBe = new Set(allFieldNames);
// for each value this entry has on all the valid tickets
for (let ticketNum = 0; ticketNum < tickets.length; ticketNum++) {
// if any value doesn't fit into a field, this entry cannot be that field.
fieldsValid.forEach((field,i)=> {
if (!field.has(tickets[ticketNum][entryNum])) {
couldBe.delete(allFieldNames[i]);
}
})
}
// keep track of the possibilities for each entry
entrysOptions.push(couldBe);
}
let found = []
let amtFound = 0;
while (amtFound < allFieldNames.length) {
entrysOptions.forEach((options, i) => {
// if there is only one possibile field for this entry we know what it is
if (options.size == 1) {
let fieldName = options.values().next().value;
// remove this field as a possibility for every other entry
entrysOptions.forEach(allOptions => {allOptions.delete(fieldName)});
// remember which entry correlates to which field
found[i] = fieldName;
amtFound++;
}
})
}
// get the values from my ticket
const myTicketValues = myTicket.split('\n')[1].split(',').map(e => parseInt(e));
// get the multiple of all departure values for the puzzle answer
let departures = 1;
found.forEach((name, i) => {
console.log(name, myTicketValues[i]);
if (name.split(' ')[0] == 'departure') {
departures *= myTicketValues[i]
}
})
console.log('puzzle answer',departures)