adventofcode2022

My solutions for Advent of Code 2022
Log | Files | Refs

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)