const fs = require('fs'); const file = fs.readFileSync(__dirname + '/input.txt').toString('utf-8'); const passports = file.split('\n\n'); const fieldNames = { byr: 'Birth year', iyr: 'Issue year', eyr: 'Expiration year', hgt: 'Height', hcl: 'Hair color', ecl: 'Eye color', pid: 'Passport ID', cid: 'Country ID' }, passportFields = Object.keys(fieldNames); const bypassed = [ 'cid' ]; // These are ignored const validationFuncs = { byr: value => value >= 1920 && value <= 2002, iyr: value => value >= 2010 && value <= 2020, eyr: value => value >= 2020 && value <= 2030, hgt: value => { let end = value.split(/[0-9]+/)[1]; let num = value.split(end)[0]; if (!end || !num) return false; if (end == 'cm') { return (num >= 150 && num <= 193); } else if (end == 'in') return (num >= 59 && num <= 76); else return false; }, hcl: value => value?.match(/#[0-9|a-f]{6}/) ? true : false, ecl: value => value?.match(/amb|blu|brn|gry|grn|hzl|oth/) ? true : false, pid: value => value?.match(/^[0-9]{9}$/) ? true : false, cid: value => true } let invalid = 0; let invalidStats = {} passportFields.forEach(field => invalidStats[field] = 0); passports.forEach(passport => { passport = passport .replace(/\n/g, ' ') .split(' '); let inv = false; passportFields.forEach(field => { let h = passport.filter(h => h.split(':')[0] == field); if (h?.[0]) h = h[0].split(':'); if (bypassed.indexOf(field) > -1) return; if (!(h[1] && validationFuncs[field](h[1]))) { inv = true; invalidStats[field] += 1; } }); if (inv) invalid++; }); let statsStr = ``; for (const [key, value] of Object.entries(invalidStats)) statsStr += `${fieldNames[key]}: ${value}\n`; console.log(statsStr); console.log(`Invalid passports: ${invalid}`); console.log(`Valid passports: ${passports.length - invalid}`); console.log(`Total passports: ${passports.length}`);