aoc/2021/02/02.lisp

54 lines
1.7 KiB
Common Lisp

(load (merge-pathnames "../common.lisp" *load-truename*))
(defconstant test-data
'("1-3 a: abcde"
"1-3 b: cdefg"
"2-9 c: ccccccccc"))
(defconstant expected-result 2)
(defconstant expected-result-part2 1)
(defstruct password lower upper char pass)
(defun parse-password (line)
(let* ((lower-end (position #\- line))
(upper-end (position #\Space line :start (1+ lower-end))))
(make-password :lower (parse-integer (subseq line 0 lower-end))
:upper (parse-integer (subseq line (1+ lower-end) upper-end))
:char (char line (1+ upper-end))
:pass (subseq line (+ upper-end 4) nil))))
(defun valid-password-part1 (password)
(let ((count (loop for x across (password-pass password)
counting (char= x (password-char password)))))
(and (<= (password-lower password) count)
(<= count (password-upper password)))))
(defun valid-password-part2 (password)
(let* ((pass (password-pass password))
(c (password-char password))
(lower-c (char pass (1- (password-lower password))))
(upper-c (char pass (1- (password-upper password)))))
(not (eq (char= c lower-c)
(char= c upper-c)))))
(defun day (lines p)
(loop for line in lines
counting (funcall p (parse-password line))))
(defun part1 (lines)
(day lines #'valid-password-part1))
(defun part2 (lines)
(day lines #'valid-password-part2))
(assert (= expected-result
(part1 test-data)))
(assert (= expected-result-part2
(part2 test-data)))
(defconstant input (read-data))
(format t "Part 1: ~D~%" (part1 input))
(format t "Part 2: ~D~%" (part2 input))