You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

3.0 KiB

Solution to p20

Load map

  (require 'dash)
  (with-temp-buffer
      (insert-file-contents "input")
      (advent/replace-multiple-regex-buffer '(("^\\(#.*#\\)$" . "\"\\1\"")))
      (goto-char (point-min))
      (insert "(setq data '(")
      (goto-char (point-max))
      (insert "))")
      (eval-buffer))

  (setq data-chars (-map #'advent/split-string-into-char-list data)
      height (length data-chars)
      width (length (car data-chars)))
  (defun char-at (p)
    (nth (car p) (nth (cadr p) data-chars)))

  (setq char-things-alist '((?# . wall)
                            (?. . free)
                            (?S . start)
                            (?E . end)))

  (defun thing-at (p)
      "Returns which object (if any) is present at position P"
      (cdr (assoc (char-at p) char-things-alist)))

  (defun starting-pos ()
    (car (advent/coordinates-of ?S data-chars)))

Let the stack burn

  (setq max-lisp-eval-depth 1000000) ; burn baby burn

First, we explore the maze and record the path from START to END

  (defun explore (p dir &optional past)
    "Explore the maze starting at position P and in the direction
  DIR. Returns a list of positions traversed END to START"
    (if (eq (thing-at p) 'end) (cons p past)
      (let* ((forward-dirs (--filter (>= (advent/dot it dir) 0)
                                     '((0 1) (0 -1) (-1 0) (1 0))))
             (new-dir (car (--filter (not (eq (thing-at (advent/neighbour  p it)) 'wall)) forward-dirs))))
        (explore (advent/neighbour  p new-dir) new-dir (cons p past)))))

  (setq distance-alist (-map-indexed (lambda (x y) (cons y x))
                                     (explore (starting-pos) '(0 0))))

Now look for gaps:

  (defun subtract-nil (a b)
    (when a (- a b)))

  (length
   (--filter (>= it 100)
             (--map (- it 2)
                    (-flatten (-non-nil (--map (-non-nil
                                                (-map (lambda (dir) (subtract-nil (cdr (assoc (advent/neighbour  (car it) dir) distance-alist)) (cdr it)))
                                                               '((0 2) (0 -2) (2 0) (-2 0))))
                                                        distance-alist))))))
1426

Alternatively, collect all element of the path that are –in the taxicab distance– closer than 20 to any given element of the path, then compute the time saved by using the cheat and filter only those that save at least 100 picoseconds

  (length
   (--filter (>= it 100)
             (-flatten
              (-map (lambda (x) (--map (- (cdar it) (cdr x) (cdr it))
                                       (--filter (<= (cdr it) 20)
                                                 (--map (cons it (advent/taxicab-distance (car it) (car x))) distance-alist))))
                    distance-alist))))
1000697