From 1d6085cd7dfb5d75b89ccf2edd950afec3665f24 Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Tue, 8 Dec 2020 13:11:18 -0300 Subject: Add day 4 --- 2020/day4.raku | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 2020/day4.raku (limited to '2020/day4.raku') diff --git a/2020/day4.raku b/2020/day4.raku new file mode 100644 index 0000000..1790de4 --- /dev/null +++ b/2020/day4.raku @@ -0,0 +1,146 @@ +#!/usr/bin/env raku + +constant \EXAMPLE = q:to/END/; +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 +END + +constant \required-keys = ; + +sub split-input($input) { + $input.split: /^^$$/; +} + +sub valid-passport($passport --> Bool) { + [&&] required-keys.map({ $passport.contains($_) }) +} + +sub valid-passports($input) { + split-input($input).grep(*.&valid-passport) +} + +# Data Validation + +my %validations = ( + byr => sub ($v) { 1920 <= $v <= 2002 }, + iyr => sub ($v) { 2010 <= $v <= 2020 }, + eyr => sub ($v) { 2020 <= $v <= 2030 }, + hgt => sub ($v) { + if $v ~~ m/$ = [\d+] $ = [ cm || in ]/ { + if $ eq 'cm' { return 150 <= $ <= 193 } + else { return 59 <= $ <= 76 } + } + False + }, + hcl => sub ($v) { so $v ~~ m/'#' <[0..9 a..f]> ** 6/ }, + ecl => sub ($v) { so $v ~~ m/amb || blu || brn || gry || grn || hzl || oth/ }, + pid => sub ($v) { so $v ~~ m/^^\d ** 9 $$/ }, + cid => { True } +); + +sub data-validation($passport) { + [&&] $passport.words».split(':').map( + -> ($k, $v) { + %validations{$k}($v) + } + ) +} + +multi sub MAIN('part1', $file) { + say valid-passports(slurp($file)).elems; +} + +multi sub MAIN('part2', $file) { + say +valid-passports(slurp($file)).grep({ $_.&data-validation}) +} + +multi sub MAIN('test') { + use Test; + subtest 'Part1', { + is split-input(EXAMPLE).elems, 4, 'length'; + ok valid-passport(split-input(EXAMPLE)[0]), 'first input'; + nok valid-passport(split-input(EXAMPLE)[1]), 'second input'; + ok valid-passport(split-input(EXAMPLE)[2]), 'third input'; + nok valid-passport(split-input(EXAMPLE)[3]), 'four input'; + + is valid-passports(EXAMPLE).elems, 2, 'validate-passports'; + }; + subtest 'Part 2', { + subtest 'byr', { + ok %validations('2002'), 'valid'; + nok %validations('2003'), 'invalid'; + }; + subtest 'hgt', { + ok %validations('60in'), 'valid in'; + ok %validations('190cm'), 'valid cm'; + nok %validations('190in'), 'invalid in'; + nok %validations('190'), 'invalid'; + }; + subtest 'hcl', { + ok %validations('#123abc'), 'valid'; + nok %validations('#123abz'), 'invalid'; + nok %validations('123abc'), 'missing #'; + }; + subtest 'ecl', { + ok %validations('brn'), 'valid'; + nok %validations('wat'), 'invalid'; + } + subtest 'pid', { + ok %validations('000000001'), 'valid'; + nok %validations('0123456789'), 'valid'; + } + + subtest 'data validation', { + my $invalid-data = q:to/END/; + eyr:1972 cid:100 + hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926 + + iyr:2019 + hcl:#602927 eyr:1967 hgt:170cm + ecl:grn pid:012533040 byr:1946 + + hcl:dab227 iyr:2012 + ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277 + + hgt:59cm ecl:zzz + eyr:2038 hcl:74454a iyr:2023 + pid:3556412378 byr:2007 + END + + for split-input($invalid-data).kv -> $i, $passport { + nok data-validation($passport), "Run invalid $i"; + } + + my $valid-data = q:to/END/; + pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 + hcl:#623a2f + + eyr:2029 ecl:blu cid:129 byr:1989 + iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm + + hcl:#888785 + hgt:164cm byr:2001 iyr:2015 cid:88 + pid:545766238 ecl:hzl + eyr:2022 + + iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719 + END + + for split-input($valid-data).kv -> $i, $passport { + ok data-validation($passport), "Run valid $i"; + } + + } + } +} -- cgit v1.2.3-70-g09d2