2020/src/04.rkt

53 lines
2.2 KiB
Racket

#lang racket
(require "../lib.rkt")
(define input (problem-input-grouped 4))
(struct passport
(byr iyr eyr hgt hcl ecl pid cid)
#:transparent)
(define default-passport
(passport #f #f #f #f #f #f #f #f))
(define (passport-set entry pass)
(let ([value (second entry)])
(match (first entry)
['byr (struct-copy passport pass [byr value])]
['iyr (struct-copy passport pass [iyr value])]
['eyr (struct-copy passport pass [eyr value])]
['hgt (struct-copy passport pass [hgt value])]
['hcl (struct-copy passport pass [hcl value])]
['ecl (struct-copy passport pass [ecl value])]
['pid (struct-copy passport pass [pid value])]
['cid (struct-copy passport pass [cid value])]
[else pass])))
(define (hgt? str)
(match str
[(regexp #px"^(\\d{3})cm$" (list _ hgt)) (<= 150 (string->number hgt) 193)]
[(regexp #px"^(\\d{2})in$" (list _ hgt)) (<= 59 (string->number hgt) 76)]
[_ #f]))
(define-values (part1 part2)
(let* ([passport-entries (map (λ~>> (string-split _ #px"[ \n]")
(map (match-lambda [(regexp #rx"(.+):(.+)" (list _ field value))
(list (string->symbol field) value)])))
input)]
[passports (map ( foldl passport-set default-passport) passport-entries)]
[valid-raw? (struct/c passport string? string? string? string? string? string? string? any/c)]
[valid? (struct/c passport
(and/c string? ( (integer-in 1920 2002) string->number))
(and/c string? ( (integer-in 2010 2020) string->number))
(and/c string? ( (integer-in 2020 2030) string->number))
hgt?
(and/c string? ( regexp-match-exact? #px"#[[:xdigit:]]{6}"))
(apply or/c '("amb" "blu" "brn" "gry" "grn" "hzl" "oth"))
(and/c string? ( regexp-match-exact? #px"\\d{9}"))
any/c)])
(values (count valid-raw? passports)
(count valid? passports))))
(show-solution part1 part2)