#!/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)