122 lines
3.6 KiB
TypeScript
122 lines
3.6 KiB
TypeScript
import 'mocha';
|
|
import assert from 'assert';
|
|
import { readFileSync } from 'fs';
|
|
|
|
|
|
let input = readFileSync('./input/2020-day-04.txt', 'utf-8')
|
|
let example: string =
|
|
`ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
|
|
byr:1937 iyr:2017 cid:147 hgt:183cm
|
|
|
|
iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
|
|
hcl:#cfa07d byr:1929
|
|
|
|
hcl:#ae17e1 iyr:2013
|
|
eyr:2024
|
|
ecl:brn pid:760753108 byr:1931
|
|
hgt:179cm
|
|
|
|
hcl:#cfa07d eyr:2025 pid:166559648
|
|
iyr:2011 ecl:brn hgt:59in`;
|
|
|
|
let tasksResults: any[] = ['N/A', 'N/A'];
|
|
|
|
describe('Day 04', () => {
|
|
let sample: Passport[];
|
|
let passports: Passport[];
|
|
before(() => {
|
|
sample = filterInvalid(parseData(example));
|
|
passports = filterInvalid(parseData(input));
|
|
})
|
|
describe('task01', () => {
|
|
it('parse data', () => {
|
|
assert.strictEqual(sample.length, 2);
|
|
tasksResults[0] = passports.length;
|
|
})
|
|
});
|
|
describe('test02', () => {
|
|
it('Calculate', () => {
|
|
passports = filterIncorrect(parseData(input));
|
|
tasksResults[1] = passports.length;
|
|
});
|
|
});
|
|
after(() => {
|
|
console.log('\ntask 01:', tasksResults[0]);
|
|
console.log('\ntask 02:', tasksResults[1]);
|
|
});
|
|
});
|
|
|
|
function task01(panels: number, input: string[], down: number = 1, right: number = 3) {
|
|
}
|
|
|
|
function task02(right: number, down: number, input: string[]) {
|
|
}
|
|
|
|
type PassKey = "byr" | "iyr" | "eyr" | "hgt" | "hcl" | "ecl" | "pid" | "cid";
|
|
|
|
function parseData(input: string): Passport[] {
|
|
let passports: Passport[] = [];
|
|
let passport: Passport = new Passport();
|
|
input.split('\n').forEach((line: string) => {
|
|
if (!line.length) {
|
|
passports.push(passport);
|
|
passport = new Passport();
|
|
}
|
|
let fields: string[] = line.split(' ');
|
|
fields.forEach((field: string) => {
|
|
let [key, value]: string[] = field.split(':');
|
|
passport[key as PassKey] = value;
|
|
});
|
|
});
|
|
|
|
return passports;
|
|
}
|
|
|
|
function filterInvalid(input: Passport[]): Passport[] {
|
|
return input.filter(p => p.valid());
|
|
}
|
|
function filterIncorrect(input: Passport[]): Passport[] {
|
|
return input.filter(p => p.correct);
|
|
}
|
|
|
|
class Passport {
|
|
byr?: string; // (Birth Year)
|
|
iyr?: string; // (Issue Year)
|
|
eyr?: string; // (Expiration Year)
|
|
hgt?: string; // (Height)
|
|
hcl?: string; // (Hair Color)
|
|
ecl?: string; // (Eye Color)
|
|
pid?: string; // (Passport ID)
|
|
cid?: string; // (Country ID)
|
|
|
|
valid(): this is Required<Passport> {
|
|
return !!(this.byr && this.iyr && this.eyr && this.hgt && this.hcl &&
|
|
this.ecl && this.pid);
|
|
}
|
|
|
|
get correct() {
|
|
try {
|
|
assert.ok(this.valid());
|
|
let valid: Required<Passport> = this;
|
|
|
|
assert.ok(isInRange(parseInt(valid.byr, 10), 1920, 2002));
|
|
assert.ok(isInRange(parseInt(valid.iyr, 10), 2010, 2020));
|
|
assert.ok(isInRange(parseInt(valid.eyr, 10), 2020, 2030));
|
|
assert.match(valid.hcl, /^#[0-9a-f]{6}$/);
|
|
assert.match(valid.pid, /^\d{9}$/);
|
|
assert.match(valid.ecl, /^(amb|blu|brn|gry|grn|hzl|oth)$/);
|
|
assert.match(valid.hgt, /(\d+)(cm|in)/);
|
|
|
|
let [_, measure, unit] = valid.hgt.match(/(\d+)(cm|in)/) as [string, string, string];
|
|
(unit === 'cm')
|
|
? assert.ok(isInRange(parseInt(measure, 10), 150, 193))
|
|
: assert.ok(isInRange(parseInt(measure, 10), 59, 76));
|
|
} catch (_ignore) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
const isInRange = (i: number, min: number, max: number): boolean => (i - min) * (i - max) <= 0;
|