const fs = require('fs') const readline = require('readline'); const readInterface = readline.createInterface({ input: fs.createReadStream('input'), console: false }); let passports = []; let cPass = {}; readInterface.on('line', function(line) { if (line.length == 0) { passports.push(cPass); cPass = {}; return; } line.split(' ').forEach(function(kv) { parts = kv.split(':'); cPass[parts[0]] = parts[1]; }); // console.log(cPass); }); let required = new Set(['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid' ]); let optional = new Set([ 'cid' ]); function validKeys(passport) { let keys = new Set(Object.keys(passport)); let missing = new Set([...required].filter(x => !keys.has(x))) return missing.size == 0; } function validBYR(passport) { let byr = Number(passport['byr']); return byr >= 1920 && byr <= 2002; } function validIYR(passport) { let iyr = Number(passport['iyr']); return iyr >= 2010 && iyr <= 2020; } function validEYR(passport) { let eyr = Number(passport['eyr']); return eyr >= 2020 && eyr <= 2030; } function validHGT(passport) { if (!passport.hasOwnProperty('hgt')) { return false; } let hgt = parseInt(passport['hgt']); if (passport['hgt'].endsWith('cm')) { return hgt >= 150 && hgt <= 193; } // inches return hgt >= 59 && hgt <= 76; } const validHCLs = /^#[a-f0-9]{6}$/; function validHCL(passport) { return validHCLs.test(passport['hcl']); } const validECLs = new Set(['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']); function validECL(passport) { return validECLs.has(passport['ecl']); } const validPIDs = /^[0-9]{9}$/ function validPID(passport) { return validPIDs.test(passport['pid']); } function valid(p) { return (validKeys(p) && validBYR(p) && validIYR(p) && validEYR(p) && validHGT(p) && validHCL(p) && validECL(p) && validPID(p)); } readInterface.on('close', function(line) { // Save the last passport if it has any fields if (Object.keys(cPass).length > 0) { passports.push(cPass); } let count = passports.filter(valid).length; console.log(count); });