(in-package :aoc) (defmacro puzzle03/do (wire position &body body) (a:with-gensyms (data dir dist) `(dolist (,data ,wire) (destructuring-bind (,dir . ,dist) ,data (loop :repeat ,dist :do (ecase ,dir (#\U (decf (cdr ,position))) (#\D (incf (cdr ,position))) (#\L (decf (car ,position))) (#\R (incf (car ,position)))) ,@body))))) (defmacro puzzle03/with-crossings (wire1 wire2 crossings &body body) (a:with-gensyms (wire1-pos wire2-pos k) `(let* ((,wire1-pos (puzzle03/collect-positions ,wire1)) (,wire2-pos (puzzle03/collect-positions ,wire2)) (,crossings (u:dict #'equal))) (u:do-hash-keys (,k ,wire1-pos) (when (u:href ,wire2-pos ,k) (setf (u:href ,crossings ,k) ,k))) ,@body))) (defun puzzle03/process-wires () (let ((file (read-puzzle-input/string 3))) (mapcar (lambda (x) (mapcar (lambda (x) (cons (elt x 0) (parse-integer (subseq x 1)))) (uiop:split-string x :separator ","))) (uiop:split-string (string-right-trim '(#\linefeed) file) :separator '(#\linefeed))))) (defun puzzle03/collect-positions (wire) (let ((positions (u:dict #'equal)) (position (cons 0 0))) (puzzle03/do wire position (setf (u:href positions position) position)) positions)) (defun puzzle03/get-distances (wire crossings) (let ((distances (u:dict #'equal)) (distance 0) (position (cons 0 0))) (puzzle03/do wire position (incf distance) (when (u:href crossings position) (setf (u:href distances position) distance))) distances)) (defun puzzle03/get-manhattan-distance (pos) (+ (abs (car pos)) (abs (cdr pos)))) (defun puzzle03/part1 () (destructuring-bind (wire1 wire2) (puzzle03/process-wires) (puzzle03/with-crossings wire1 wire2 crossings (apply #'min (mapcar #'puzzle03/get-manhattan-distance (u:hash-keys crossings)))))) (defun puzzle03/part2 () (destructuring-bind (wire1 wire2) (puzzle03/process-wires) (puzzle03/with-crossings wire1 wire2 crossings (let ((crossings (u:hash-keys crossings)) (cross1 (puzzle03/get-distances wire1 crossings)) (cross2 (puzzle03/get-distances wire2 crossings))) (print crossings) cross1 ;; WHAT THE FUCK #++(loop :for crossing :in crossings :do (print (u:href cross1 crossing)) ;; :minimize (+ (u:href cross1 crossing) ;; (u:href cross2 crossing)) )))))