aboutsummaryrefslogtreecommitdiff
path: root/2022/Day09/part-two.cl
blob: 06f66238535698d093a8fe88a1144b51bdd5e317 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
;;; https://gitlab.com/Syndamia/senzill
(require :senzill)
(use-package :senzill.math)
(use-package :senzill.collections)
(use-package :senzill.pair)
(use-package :senzill.io)

(defparameter +rope-length+ 10)

(ask-for-stream (prog-input)
  (let ((rope '()) (visited '((0 . 0))))
  (flet ((norm>sqrt2p (p) ; If c's eucledian length is less than sqrt(2). In other words, if c is outside the 3x3 square.
           "Optimized version of (> (norm p) (sqrt 2))"
           (or (> (abs (car p)) 1) (> (abs (cdr p)) 1)))

         (dir-to-pair (direction)
           (cond ((char= direction #\R) '( 1 .  0))
                 ((char= direction #\L) '(-1 .  0))
                 ((char= direction #\U) '( 0 .  1))
                 ((char= direction #\D) '( 0 . -1)))))

    (dotimes (i +rope-length+)
      (push '(0 . 0) rope))

    (doread-lines (inpt :read-line-options (prog-input NIL))
                  (loop for i from 1 to (parse-integer inpt :start 2)
                        for dirvec = (dir-to-pair (char inpt 0))

                        do
                        (pair+= (first rope) dirvec) ; First knot is the head
                        ;;; We update the knot positions from left to right (from head to tail)
                        ;;; Since each knot depends on the previous, we iterate from head to tail-1
                        ;;; but always update "the second element" (from head+1 to tail)
                        (loop for knot on rope
                              while (cdr knot)
                              for movec = (pair- (first knot) (second knot)) ; head - tail

                              if (norm>sqrt2p movec)
                                do
                                ;; dist-resize so we don't put the knot on top of the other, but behind it
                                (pair+= (second knot) (pair-round (dist-resize-by movec -1)))
                              
                              finally
                                (if (not (member-if (lambda (x) (pair= x (car knot))) visited))
                                  (push (car knot) visited)))))

    (print (length visited)))))