no title added by anonymous on Fri Dec 4 20:11:28 2020

#!/usr/bin/env chibi-scheme
;; https://adventofcode.com/2020/day/4

(import (scheme base)
        (scheme char)
        (scheme write)

        (chibi parse)
        (chibi match)
        (srfi 1))

(define (parse-seq-fst fst snd)
  (parse-map (parse-seq fst snd) car))

(define parse-pair
  (let ((f (parse-seq
             (parse-repeat+ (parse-char char-alphabetic?))
             (parse-char #\:)
             (parse-repeat+ (parse-or
                              (parse-char #\#)
                              (parse-char char-alphabetic?)
                              (parse-char char-numeric?))))))
    (parse-map f (lambda (x)
                   (match x ((key _ val)
                     (cons
                       (string->symbol (list->string key))
                       (list->string val))))))))

(define parse-passport
  (parse-repeat+ (parse-seq-fst
                   parse-pair
                   (parse-char char-whitespace?))))

(define parse-batch
  (let* ((parse-eol   (parse-char #\newline))
         (parse-blank (parse-and parse-eol parse-eol)))
    (parse-repeat+ (parse-seq-fst
                     parse-passport
                     (parse-optional parse-blank)))))

(define (is-valid? passport)
  (define required-keys
    '(byr iyr eyr hgt
      hcl ecl pid))

  (call/cc
    (lambda (return)
      (for-each (lambda (x)
                  (unless (assoc x passport)
                    (return #f))) required-keys)
      #t)))

(define (filter-valid port)
  (let* ((stream     (make-parse-stream "stdin" port))
         (passports  (parse parse-batch stream)))
    (if passports
      (filter is-valid? passports)
      (error "invalid input"))))

(display (length (filter-valid (current-input-port))))
(newline)