diff options
Diffstat (limited to 'AoC2022/09')
-rw-r--r-- | AoC2022/09/solver.el | 70 |
1 files changed, 44 insertions, 26 deletions
diff --git a/AoC2022/09/solver.el b/AoC2022/09/solver.el index d1eac37..cf5ac7f 100644 --- a/AoC2022/09/solver.el +++ b/AoC2022/09/solver.el @@ -25,14 +25,13 @@ (defsubst solver-diagonal (vec) (and (= 1 (abs (car vec))) (= 1 (abs (cdr vec))))) - (defun solver-move (direction) (cl-ecase direction ('R (lambda (x) (cl-incf (car x)))) ('L (lambda (x) (cl-decf (car x)))) ('U (lambda (x) (cl-incf (cdr x)))) ('D (lambda (x) (cl-decf (cdr x)))))) -;; WARN This need to be bytecompiled otherwise the lambda is not capturing diff-v in the closure + (defun solver-puller (diff-v) (let ((distance (solver-distance-1 diff-v))) (cond @@ -42,37 +41,56 @@ (pcase diff-v (`(0 . ,d) (solver-move (if (= d 2) 'U 'D))) (`(,d . 0) (solver-move (if (= d 2) 'R 'L))))) - ((= distance 3) + ((<= 3 distance 4) (lambda (x) (funcall (solver-move (if (< 0 (car diff-v)) 'R 'L)) x) (funcall (solver-move (if (< 0 (cdr diff-v)) 'U 'D)) x))) - (t (error "Head moved too far"))))) + (t (error "Leader moved too far"))))) -(with-temp-buffer - (insert-file-contents "input") -;; (insert "R 4 -;; U 4 -;; L 3 -;; D 1 -;; R 4 -;; D 1 -;; L 5 -;; R 2") +(defun solver-input (data-string) + (thread-last + (split-string data-string "\n" t) + (mapcar (lambda (inst) (let ((move (split-string inst))) + (cons (intern (car move)) + (string-to-number (cadr move)))))))) + +(defun solver (moves rope) (let (path - (head (cons 0 0)) - (tail (cons 0 0)) - (moves - (thread-last - (split-string (buffer-string) "\n" t) - (mapcar (lambda (inst) (let ((move (split-string inst))) - (cons (intern (car move)) - (string-to-number (cadr move)))))) - ))) + (head (car rope)) + (end (car (last rope)))) (dolist (move moves) (dotimes (_ (cdr move)) (funcall (solver-move (car move)) head) - (funcall (solver-puller (solver-diff head tail)) tail) - (push (cons (car tail) (cdr tail)) path))) - (= 6384 (length (cl-remove-duplicates path :test #'equal)))) + (cl-loop for (leader follower) on rope while follower + do (funcall (solver-puller (solver-diff leader follower)) follower)) + ;; (message "%S" rope) + (push (cons (car end) (cdr end)) path))) + (cl-remove-duplicates path :test #'equal))) + +(defconst solver-eg-1 (solver-input "R 4 + U 4 + L 3 + D 1 + R 4 + D 1 + L 5 + R 2")) +(defconst solver-eg-2 (solver-input "R 5 +U 8 +L 8 +D 3 +R 17 +D 10 +L 25 +U 20")) +(defconst solver-problem (solver-input (with-temp-buffer (insert-file-contents "input") (buffer-string)))) +(ert-deftest test-solver () + ;; part 1 + (should (= 13 (length (solver solver-eg-1 (list (cons 0 0) (cons 0 0)))))) + (should (= 6384 (length (solver solver-problem (list (cons 0 0) (cons 0 0)))))) + ;; part 2 + (should (= 1 (length (solver solver-eg-1 (cl-loop repeat 10 collect (cons 0 0)))))) + (should (= 36 (length (solver solver-eg-2 (cl-loop repeat 10 collect (cons 0 0)))))) + (should (= 2734 (length (solver solver-problem (cl-loop repeat 10 collect (cons 0 0))))))) |