|
|
|
@ -115,3 +115,64 @@
|
|
|
|
|
(time (let ((data (read-3 map)))
|
|
|
|
|
(print (solve-3-1 '(1 3) data))
|
|
|
|
|
(print (solve-3-2 '((1 1) (1 3) (1 5) (1 7) (2 1)) data)))))
|
|
|
|
|
|
|
|
|
|
(defvar *passport-fields* (list "byr" "iyr" "eyr" "hgt" "hcl" "ecl" "pid" "cid"))
|
|
|
|
|
(defvar *passport-rules-broken* (list nil nil nil nil nil nil nil (lambda (n) (declare (ignore n)) t)))
|
|
|
|
|
(defvar *passport-rules* nil)
|
|
|
|
|
(setf *passport-rules*
|
|
|
|
|
(list (lambda (n) (and n (let ((nn (ignore-errors (parse-integer n))))
|
|
|
|
|
(and nn (>= nn 1920) (<= nn 2002)))))
|
|
|
|
|
(lambda (n) (and n (let ((nn (ignore-errors (parse-integer n))))
|
|
|
|
|
(and nn (>= nn 2010) (<= nn 2020)))))
|
|
|
|
|
(lambda (n) (and n (let ((nn (ignore-errors (parse-integer n))))
|
|
|
|
|
(and nn (>= nn 2020) (<= nn 2030)))))
|
|
|
|
|
(lambda (h) (and h (multiple-value-bind (n offset) (parse-integer h :junk-allowed t)
|
|
|
|
|
(let ((unit (subseq h offset)))
|
|
|
|
|
(cond ((string= unit "cm")
|
|
|
|
|
(and (>= n 150) (<= n 193)))
|
|
|
|
|
((string= unit "in")
|
|
|
|
|
(and (>= n 59) (<= n 76))))))))
|
|
|
|
|
(lambda (c) (and c
|
|
|
|
|
(= (length c) 7)
|
|
|
|
|
(char= (elt c 0) #\#)
|
|
|
|
|
(parse-integer (subseq c 1) :radix 16)))
|
|
|
|
|
(lambda (c) (and c (member c '("amb" "blu" "brn" "gry" "grn" "hzl" "oth") :test #'equal)))
|
|
|
|
|
(lambda (pid) (and pid
|
|
|
|
|
(= 9
|
|
|
|
|
(length pid)
|
|
|
|
|
(length (remove-if (lambda (n) (not (digit-char-p n))) pid)))))
|
|
|
|
|
(lambda (cid) (declare (ignore cid)) t)))
|
|
|
|
|
|
|
|
|
|
(defun read-passport (stream)
|
|
|
|
|
(let ((passport-list
|
|
|
|
|
(apply #'concatenate 'list
|
|
|
|
|
(loop for line = (read-line stream nil)
|
|
|
|
|
while (and line (not (string= line "")))
|
|
|
|
|
collect (split-sequence:split-sequence #\space line))))
|
|
|
|
|
(current-passport (make-hash-table :test 'equal)))
|
|
|
|
|
(loop for key in passport-list
|
|
|
|
|
do (setf (gethash (subseq key 0 3) current-passport)
|
|
|
|
|
(subseq key 4)))
|
|
|
|
|
current-passport))
|
|
|
|
|
|
|
|
|
|
(defun read-4 (file)
|
|
|
|
|
(with-open-file (stream file)
|
|
|
|
|
(loop while (peek-char nil stream nil)
|
|
|
|
|
collect (read-passport stream))))
|
|
|
|
|
|
|
|
|
|
(defun %solve-4 (data tests)
|
|
|
|
|
(let ((valid-count 0))
|
|
|
|
|
(loop for passport in data
|
|
|
|
|
do (unless (member 'nil
|
|
|
|
|
(map 'list (lambda (field test)
|
|
|
|
|
(if test
|
|
|
|
|
(funcall test (gethash field passport))
|
|
|
|
|
(gethash field passport)))
|
|
|
|
|
*passport-fields* tests))
|
|
|
|
|
(incf valid-count)))
|
|
|
|
|
valid-count))
|
|
|
|
|
|
|
|
|
|
(defun solve-4 (file)
|
|
|
|
|
(let ((data (read-4 file)))
|
|
|
|
|
(time (progn (print (%solve-4 data *passport-rules-broken*))
|
|
|
|
|
(print (%solve-4 data *passport-rules*))))))
|
|
|
|
|