๐Ÿ“ฆ Bogdanp / aoc2020

๐Ÿ“„ day04.rkt ยท 59 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59#lang racket/base

(require racket/match)

(define fld-re #px"^ ?([a-z]+):([^ \n]+)")

(define passports
  (call-with-input-file "input04.txt"
    (lambda (in)
      (for/fold ([passports null]
                 [passport (hash)]
                 #:result (reverse
                           (filter (compose1 not hash-empty?)
                                   (cons passport passports))))
                ([line (in-lines in)])
        (cond
          [(string=? line "")
           (values (cons passport passports) (hash))]
          [else
           (define line-in (open-input-string line))
           (let loop ([passport passport])
             (match (regexp-try-match fld-re line-in)
               [#f (values passports passport)]
               [(list _
                      (app bytes->string/utf-8 fld)
                      (app bytes->string/utf-8 val))
                (loop (hash-set passport fld val))]))])))))

(define (passport-valid?/old p)
  (equal?
   '("byr" "ecl" "eyr" "hcl" "hgt" "iyr" "pid")
   (sort (hash-keys (hash-remove p "cid")) string<?)))

(define byr-re #rx"^(19[2-9][0-9]|2000|2001|2002)$")
(define iyr-re #rx"^(201[0-9]|2020)$")
(define eyr-re #rx"^(202[0-9]|2030)$")
(define hgt-re #rx"^((1[5-8][0-9]|190|191|192|193)cm|(59|6[0-9]|7[0-6])in)$")
(define hcl-re #px"^#[0-9a-f]{6}")
(define ecl-re #rx"^(amb|blu|brn|gry|grn|hzl|oth)$")
(define pid-re #px"^\\d{9}$")

(define (passport-valid?/new p)
  (and (passport-valid?/old p)
       (regexp-match? byr-re (hash-ref p "byr"))
       (regexp-match? iyr-re (hash-ref p "iyr"))
       (regexp-match? eyr-re (hash-ref p "eyr"))
       (regexp-match? hgt-re (hash-ref p "hgt"))
       (regexp-match? hcl-re (hash-ref p "hcl"))
       (regexp-match? ecl-re (hash-ref p "ecl"))
       (regexp-match? pid-re (hash-ref p "pid"))))

(for/sum ([p (in-list passports)]
          #:when (passport-valid?/old p))
  1)

(for/sum ([p (in-list passports)]
          #:when (passport-valid?/new p))
  1)