(define-module (pp) #:use-module (srfi srfi-1) #:export (pp parse-line count-occurrences valid-password?)) (define (pp str) (count (lambda (x) x) (map (lambda (line) (let ((parsed (parse-line line))) (valid-password? (car parsed) (cadr parsed) (caddr parsed)))) (string-split (string-trim-both str char-set:whitespace) #\newline)))) (define (parse-line str) "Parses a line of the puzzle format into a workable datastructure: (passwd (char (min max)))" (let* ((fields (string-split str char-set:whitespace)) (range (map string->number (string-split (car fields) #\-))) (char (string-ref (cadr fields) 0)) (passwd (caddr fields))) (list passwd char (cons (car range) (cadr range))))) (define (valid-password? passwd char range) "Given PASSWD, checks that CHAR appears within RANGE number of times. RANGE is a cons pair." (let ((occurrences (count-occurrences passwd char))) (and (>= occurrences (car range)) (>= (cdr range) occurrences)))) (define (count-occurrences str char) "Returns the number of times CHR appears in STR." (string-length (string-filter char str)))