Skip to content

Instantly share code, notes, and snippets.

@Friss
Created December 17, 2020 01:18
Show Gist options
  • Save Friss/27ebd341d30f31b76f8c82647f1da1c3 to your computer and use it in GitHub Desktop.
Save Friss/27ebd341d30f31b76f8c82647f1da1c3 to your computer and use it in GitHub Desktop.
const fs = require('fs').promises;
(async () => {
console.log(`Reading input from ${__dirname}/${process.argv[2]}.txt`);
const inputData = await fs.readFile(`${__dirname}/${process.argv[2]}.txt`);
const inputs = inputData
.toString()
.split('\n')
.filter((n) => n);
const rules = [];
const yourTicket = [];
const nearbyTickets = [];
let foundTicket = false;
let foundNearby = false;
const rangeRegex = /(?<rangeName>.+): (?<lowerMin>\d+)-(?<lowerMax>\d+) or (?<upperMin>\d+)-(?<upperMax>\d+)/;
for (let index = 0; index < inputs.length; index++) {
const line = inputs[index];
if (rangeRegex.test(line)) {
const {
rangeName,
lowerMin,
lowerMax,
upperMin,
upperMax,
} = rangeRegex.exec(line).groups;
rules.push({
rangeName,
lowerMax: parseInt(lowerMax, 10),
lowerMin: parseInt(lowerMin, 10),
upperMax: parseInt(upperMax, 10),
upperMin: parseInt(upperMin, 10),
index: [],
});
continue;
}
if (!foundTicket && line.includes('your ticket')) {
foundTicket = true;
}
if (foundTicket && line.includes(',')) {
foundTicket = false;
line.split(',').forEach((l) => yourTicket.push(parseInt(l, 10)));
}
if (!foundNearby && line.includes('nearby tickets')) {
foundNearby = true;
}
if (foundNearby && line.includes(',')) {
nearbyTickets.push(line.split(',').map((l) => parseInt(l, 10)));
}
}
let invalidRange = 0;
const invalidTickets = new Set();
nearbyTickets.forEach((nearByTicket, ticketIndex) => {
for (let index = 0; index < nearByTicket.length; index++) {
const num = nearByTicket[index];
const valid = rules.some((rule) => {
return (
(num <= rule.lowerMax && num >= rule.lowerMin) ||
(num <= rule.upperMax && num >= rule.upperMin)
);
});
if (!valid) {
invalidRange += num;
invalidTickets.add(ticketIndex);
}
}
});
const validTickets = nearbyTickets.filter((_, i) => !invalidTickets.has(i));
const allValues = [];
yourTicket.forEach((value, index) => {
const nums = [value, ...validTickets.map((t) => t[index])];
nums.sort((a, b) => a - b);
allValues.push(nums);
});
const updatedRules = rules.map((rule) => {
for (let index = 0; index < allValues.length; index++) {
const ticketNumbers = allValues[index];
const allValid = ticketNumbers.every((num) => {
return (
(num <= rule.lowerMax && num >= rule.lowerMin) ||
(num <= rule.upperMax && num >= rule.upperMin)
);
});
if (allValid) {
rule.index.push(index);
}
}
return rule;
});
const savedRules = [];
updatedRules
.sort((a, b) => a.index.length - b.index.length)
.map((r) => {
r.index = r.index.filter((i) => !savedRules.includes(i));
savedRules.push(r.index[0]);
});
const part2 = updatedRules
.filter((rule) => rule.rangeName.startsWith('departure'))
.reduce((sum, rule) => {
return sum * yourTicket[rule.index[0]];
}, 1);
console.log('part1', invalidRange);
console.log('---');
console.log('part2', part2);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment