9c7cae5986bcc7737a35477dbc05ef33076e7cd1 — Samuel Hunter 4 years ago 967815e
Solve Day 15
2 files changed, 69 insertions(+), 7 deletions(-)

M src/day15.lisp
M src/intcode.lisp
M src/day15.lisp => src/day15.lisp +68 -6
@@ 7,11 7,12 @@
  (:import-from #:queues

(in-package #:aoc2019.15)

(defparameter *tape* (read-day 15))
(defparameter *tape* (read-tape 15))

(defparameter +north+ 1)
(defparameter +south+ 2)

@@ 50,7 51,7 @@
             ;; Bad; already went here before.
             (halt :fail))
         (setf (gethash (cons x y) room) :empty))
        (2 (halt :win x y))))
        (2 (halt :win))))

    (eval-tape arch *tape*)))

@@ 58,15 59,76 @@
  (mapcar (lambda (d) (cons d path))

(defun solve-part1 ()
(defun shortest-path ()
  ;; Use breadth-first-search to find the most efficient route to the oxygen tank
  (loop :with queue := (make-queue :simple-queue)
        :for path := (qpop queue)
        :for (result x y) := (multiple-value-list (run-robot-path path))
        :for result := (run-robot-path path)
        :until (eq result :win)
        :when (eq result :partial)
          :do (dolist (branch (path-branches path))
                (qpush queue branch))
        :finally (return (values (length path) (cons x y)))))
        :finally (return path)))

(defun solve-part1 ()
  (length (shortest-path)))

(defun run-robot-path* (path-to-o2 path)
  (let ((arch (make-architecture *base-arch*))
        (room (make-hash-table :test #'equal))
        (path-to-o2* (reverse path-to-o2))
        (path* (reverse path))
        (x 0) (y 0))

    ;; read
    (defop (arch 03) (dest)

        (path-to-o2* (setf dest (pop path-to-o2*)))
        (path* (setf dest (pop path*)))
        (t (halt t (cons x y))))

      (destructuring-bind (next-x . next-y) (next-position dest x y)
        (setf x next-x
              y next-y)))

    ;; write
    (defop (arch 04) (src)
      (ecase src
        (0 (halt nil)) ;; Bad; hit a wall
        (1 (cond
             (path-to-o2* nil)
             ((gethash (cons x y) room) (halt nil))
             (t (setf (gethash (cons x y) room) t))))
        (2 (cond
             ((gethash (cons x y) room) (halt nil))
             (t (setf (gethash (cons x y) room) t))))))

    (eval-tape arch *tape*)))

(defun largest-value (hash)
  (loop :for key :being :the :hash-keys :of hash
          :using (hash-value val)
        :maximize val))

(defun solve-part2 ())
(defun solve-part2 ()
  (let ((path-to-o2 (shortest-path))
        (queue (make-queue :simple-queue)))
    (format t "Found path to O2; finding space it takes to fill~%")
    (qpush queue ())
    (loop :with solutions := (make-hash-table :test #'equal)
          :until (zerop (qsize queue))
          :for path := (qpop queue)
          :for length := (length path)
          :for (success pos) := (multiple-value-list (run-robot-path* path-to-o2 path))
          :for shortestp := (and success
                                 (or (not (gethash pos solutions))
                                     (< length (gethash pos solutions))))
          :when shortestp
            :do (progn (setf (gethash pos solutions) length)
                       (format t "Found shorter path to ~S: ~S~%"
                               pos length))
          :when shortestp
            :do (dolist (branch (path-branches path))
                  (qpush queue branch))
          :finally (return (largest-value solutions)))))

M src/intcode.lisp => src/intcode.lisp +1 -1
@@ 140,7 140,7 @@
                                   (setf head (dest-addr c))))
                                 (lambda (c)
                                   (return (values (return-values c)))))
                                   (return (values-list (return-values c)))))
                                 (lambda (c)
                                   (incf relative-base (offset c)))))