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

  (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