;; https://adventofcode.com/2022/day/9 ;; i have been thinking about this in a car on a way home. ;; first check - if any movement of Tail is needed - if any coord is more than 2 away ;; ;; then - if movement is needed - it's always done in 1 step into direction of Head. ;; - if difference is 0, no movement, otherwise (HeadX - TailX) / Abs(HeadX - TailX) ;; ;; and what's left is reading in changes to Head position, update of head position, ;; and calling generation of new Tail position from newHead and prevTail ;; ;; no need to worry about the borders, as Head is always closer to border? ;; so, the field should be considered unbounded. and no coordinates for the starting point are given. ;; we are also to consider that in the beginning Head is on top of Tail. ;; ok. would my math work with negative coordinates? it really should ;; so, let's consider starting coordinates as (0,0) and also keep a set of all preivously visited coordinates by the Tail ;; and return its size (defmacro get-x (pointCoords) `(car ,pointCoords)) (defmacro get-y (pointCoords) `(cadr ,pointCoords)) (setf (get-x '(1 2)) 3) (defparameter *test-list* (list 1 2)) (setf (get-x *test-list*) 2) (setf (get-y *test-list*) 7) (setf (first *test-list*) 3) (get-y '(1 2)) (abs -1) (defun tail-move-needed (headCoords tailCoords) (flet ((diff-more-than-two (num1 num2) (>= (abs (- num1 num2)) 2))) (or (diff-more-than-two (get-x headcoords) (get-x tailcoords)) (diff-more-than-two (get-y headcoords) (get-y tailcoords))))) (>= 2 2) (tail-move-needed '(1 1) '(1 1)) (tail-move-needed '(1 1) '(1 2)) (tail-move-needed '(1 1) '(1 3)) (tail-move-needed '(1 1) '(2 3)) (tail-move-needed '(1 1) '(0 0)) (defun update-big-distance-coord (headcoord tailcoord) (let* ((diff (- headcoord tailcoord)) (change (if (eq diff 0) 0 (/ diff (abs diff))))) (+ tailcoord change))) (defun update-big-distance-coords (headcoords tailcoords) (let ((new-x (update-big-distance-coord (get-x headcoords) (get-x tailcoords))) (new-y (update-big-distance-coord (get-y headcoords) (get-y tailcoords)))) (list new-x new-y))) (update-big-distance-coords '(2 1) '(0 0)) (update-big-distance-coords '(-2 0) '(0 0)) (update-big-distance-coords '(0 -2) '(0 0)) (defun get-new-tail-coords (headcoords tailcoords) (if (tail-move-needed headcoords tailcoords) (update-big-distance-coords headcoords tailcoords) tailcoords)) (get-new-tail-coords '(1 1) '(0 0)) (get-new-tail-coords '(-1 0) '(0 0)) (get-new-tail-coords '(1 -1) '(0 0)) ;; ok, now i need to translate commands of type ;; R 4 (defparameter *test-line* "R 4") (require 'cl-ppcre) (let ((split (cl-ppcre:split " " *test-line*))) (setf (first split) (intern (first split))) (setf (second split) (parse-integer (second split))) split) (defun read-comman (line) (let ((split (cl-ppcre:split " " line))) (setf (first split) (intern (first split))) (setf (second split) (parse-integer (second split))) split)) (read-comman "U 5") (defun modify-head-coords (headcoords direction) (case direction (R (incf (get-x headcoords) 1)) (L (incf (get-x headcoords) -1)) (U (incf (get-y headcoords) 1)) (D (incf (get-y headcoords) -1)))) (defparameter *test-coords* (list 0 0)) (modify-head-coords *test-coords* 'L) (modify-head-coords *test-coords* 'R) (modify-head-coords *test-coords* 'U) (modify-head-coords *test-coords* 'D) ;; seems to work. ;; now loop and addint tail coords into set (ql:quickload 'fset) (defparameter *test-set* (fset:set '(0 0) '(1 1))) (fset:with *test-set* '(3 1)) (fset:with *test-set* '(1 1)) ;; yes, with equal, that's cool (loop for i from 1 to 4 do (print i)) ;; got I forgot most of what there is about input attribute ;; modification, when will that modification become visible on top? ;; when I've defined the value as parameter, so it's dynamic binding, ;; instead of lexical binding? ;; ((tail-coords-set (fset:empty-set)) ;; (headcoords (list 0 0)) ;; (tailcoords (list 0 0))) (progn (defvar tail-coords-set ) (setq tail-coords-set (fset:empty-set)) (defvar headcoords ) (setq headcoords (list 0 0)) (defvar tailcoords ) (setq tailcoords (list 0 0))) (defun run-step (direction) (modify-head-coords headcoords direction) (setf tailcoords (get-new-tail-coords headcoords tailcoords)) (setf tail-coords-set (fset:with tail-coords-set tailcoords)) ;; (print (format t "~S ~S ~S~%" headcoords tailcoords direction)) ) (defun run-command (repetitions direction) (loop for i from 1 to repetitions do (progn (run-step direction) ;; (format t "~S ~S ~S ~S~%" headcoords tailcoords direction tail-coords-set) ))) (progn (defvar tail-coords-set ) (setq tail-coords-set (fset:empty-set)) (defvar headcoords ) (setq headcoords (list 0 0)) (defvar tailcoords ) (setq tailcoords (list 0 0)) (with-open-file (in "day9-input.txt") (loop for line = (read-line in nil nil) while line do (let* ((command (read-comman line)) (direction (first command)) (repetition (second command))) (run-command repetition direction))) (fset:size tail-coords-set))) ;;; PART 2 ;; i kind of predicted that they'd want to generalize to longer rope. ;; ugh. but it still kind of works? ;; just have list of rope points? ;; and each step would be applying same step to some particular point ;; - logging is not much less useful ;; the points are H1234..9 ;; so, array of length 10 (progn (defvar *string-joints*) ;; (setq *string-joints* (make-array 10 :initial-element '(0 0))) ;; wow, here's example of code being AST directly from text ;; now, it's problem with "initial-element" cool (defvar *9-tail-coords-set*) (loop for i from 0 to 9 do (setf (aref *string-joints* i) (list 0 0))) (setq *9-tail-coords-set* (fset:empty-set))) (defun run-step-2 (direction) (modify-head-coords (aref *string-joints* 0) direction) (loop for cur-joint-step from 1 to 9 do (setf (aref *string-joints* cur-joint-step) (get-new-tail-coords (aref *string-joints* (1- cur-joint-step)) (aref *string-joints* cur-joint-step)))) (setf *9-tail-coords-set* (fset:with *9-tail-coords-set* (aref *string-joints* 9)))) (defun run-command-2 (repetitions direction) (loop for i from 1 to repetitions do (progn (run-step-2 direction) ;; (format t "~S ~S ~S ~S~%" headcoords tailcoords direction tail-coords-set) ))) (progn (loop for i from 0 to 9 do (setf (aref *string-joints* i) (list 0 0))) (setq *9-tail-coords-set* (fset:empty-set)) (with-open-file (in "day9-input.txt") (loop for line = (read-line in nil nil) while line do (let* ((command (read-comman line)) (direction (first command)) (repetition (second command))) (run-command-2 repetition direction))) (fset:size *9-tail-coords-set*)))