02.lisp (1406B)
1 (require "asdf") 2 3 (defun day2-part1 (input-file) 4 (puzzle input-file #'is-invalid-1)) 5 6 (defun day2-part2 (input-file) 7 (puzzle input-file #'is-invalid-2)) 8 9 (defun puzzle (input-file invalid-test) 10 (let* ((s (uiop:read-file-string input-file)) 11 (u (uiop:split-string s :separator ",")) 12 (tot 0)) 13 (dolist (v u) 14 (let* ((w (uiop:split-string v :separator "-")) 15 (x (parse-integer (first w))) 16 (y (parse-integer (second w))) 17 (z (sum-invalids-in-range invalid-test x y))) 18 (setf tot (+ tot z)) )) 19 tot)) 20 21 ; I tried to be clever and step through just invalid numbers, but it's quite fiddly handling all the edge cases 22 ; let's see if the naive thing is fast enough 23 (defun sum-invalids-in-range (invalid-test start end) 24 (do ((x start (1+ x)) 25 (tot 0)) 26 ((> x end) tot) 27 (if (funcall invalid-test x) 28 (setf tot (+ tot x))))) 29 30 (defun is-invalid-1 (x) 31 (let* ((y (write-to-string x)) 32 (l (length y)) 33 (m (floor l 2)) 34 (n1 (subseq y 0 m)) 35 (n2 (subseq y m))) 36 (equal n1 n2))) 37 38 (defun is-invalid-2 (x) 39 (do* ((y (write-to-string x)) 40 (l (length y)) 41 (m (floor l 2)) 42 (n 1 (1+ n)) 43 (s (subseq y 0 n) (subseq y 0 n)) 44 (u (ceiling l n) (ceiling l n))) 45 ((> n m)) 46 (if (equal y (repeat-string u s)) 47 (return t)))) 48 49 (defun repeat-string (n my-string) 50 (with-output-to-string (stream) 51 (dotimes (x n) 52 (write-string my-string stream))))