day09.lisp (2332B)
1 (defpackage #:adventofcode2022/day09 2 (:use #:cl #:adventofcode2022) 3 (:import-from #:alexandria #:clamp)) 4 (in-package #:adventofcode2022/day09) 5 6 (defun move-head (head dir) 7 (cond 8 ((char= dir #\U) (decf (cadr head))) 9 ((char= dir #\D) (incf (cadr head))) 10 ((char= dir #\L) (decf (car head))) 11 ((char= dir #\R) (incf (car head))))) 12 13 (defun head-tail-touching-p (head tail) 14 (and 15 (<= (abs (- (car head) (car tail))) 1) 16 (<= (abs (- (cadr head) (cadr tail))) 1))) 17 18 (defun move-tail (tail head) 19 (incf (car tail) 20 (clamp (- (car head) (car tail)) -1 1)) 21 (incf (cadr tail) 22 (clamp (- (cadr head) (cadr tail)) -1 1))) 23 24 (defun task1 (inputs) 25 (loop with visited-positions = (make-hash-table :test 'equal) 26 with pos-head = (list 0 0) 27 with pos-tail = (list 0 0) 28 initially (setf (gethash (copy-seq pos-tail) visited-positions) t) 29 for (dir steps) in inputs 30 do (loop for i from 1 to steps 31 do (move-head pos-head dir) 32 unless (head-tail-touching-p pos-head pos-tail) 33 do (move-tail pos-tail pos-head) 34 and do (setf (gethash (copy-seq pos-tail) visited-positions) t)) 35 finally (return (hash-table-count visited-positions)))) 36 37 (defun task2 (inputs) 38 (loop with visited-positions = (make-hash-table :test 'equal) 39 with positions = (loop repeat 10 collect (list 0 0)) 40 with pos-head = (car positions) 41 with pos-tail = (car (last positions)) 42 initially (setf (gethash (list 0 0) visited-positions) t) 43 for (dir steps) in inputs 44 do (loop for i from 1 to steps 45 do (move-head pos-head dir) 46 do (loop with previous = pos-head 47 for knot in (cdr positions) 48 for i from 1 49 unless (head-tail-touching-p previous knot) 50 do (move-tail knot previous) 51 do (setf previous knot)) 52 do (setf (gethash (copy-seq pos-tail) visited-positions) t)) 53 finally (return (hash-table-count visited-positions)))) 54 55 (define-day 9 56 (:translate-input (lambda (line) 57 (list (aref line 0) 58 (parse-integer (subseq line 2))))) 59 #'task1 60 #'task2)