mirror of
https://github.com/correl/advent-of-code.git
synced 2024-11-21 19:18:35 +00:00
Day 9: All in a Single Night
This commit is contained in:
parent
ff6e5d2ad4
commit
09be9e37d0
1 changed files with 175 additions and 0 deletions
|
@ -4164,3 +4164,178 @@ this puzzle) is =42 - 23 = 19=.
|
|||
#+RESULTS[bb50e3c25f6d0d1247acdefae2e5c755c90fe7a7]:
|
||||
: 2085
|
||||
|
||||
* Day 9: All in a Single Night
|
||||
|
||||
Every year, Santa manages to deliver all of his presents in a single
|
||||
night.
|
||||
|
||||
This year, however, he has some new locations to visit; his elves have
|
||||
provided him the distances between every pair of locations. He can
|
||||
start and end at any two (different) locations he wants, but he must
|
||||
visit each location exactly once. What is the *shortest distance* he
|
||||
can travel to achieve this?
|
||||
|
||||
For example, given the following distances:
|
||||
|
||||
#+name: 9-example
|
||||
#+BEGIN_EXAMPLE
|
||||
London to Dublin = 464
|
||||
London to Belfast = 518
|
||||
Dublin to Belfast = 141
|
||||
#+END_EXAMPLE
|
||||
|
||||
The possible routes are therefore:
|
||||
|
||||
#+BEGIN_EXAMPLE
|
||||
Dublin -> London -> Belfast = 982
|
||||
London -> Dublin -> Belfast = 605
|
||||
London -> Belfast -> Dublin = 659
|
||||
Dublin -> Belfast -> London = 659
|
||||
Belfast -> Dublin -> London = 605
|
||||
Belfast -> London -> Dublin = 982
|
||||
#+END_EXAMPLE
|
||||
|
||||
The shortest of these is =London -> Dublin -> Belfast = 605=, and so
|
||||
the answer is =605= in this example.
|
||||
|
||||
What is the distance of the shortest route?
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
:HIDDEN:
|
||||
#+name: 9-input
|
||||
#+BEGIN_EXAMPLE
|
||||
Tristram to AlphaCentauri = 34
|
||||
Tristram to Snowdin = 100
|
||||
Tristram to Tambi = 63
|
||||
Tristram to Faerun = 108
|
||||
Tristram to Norrath = 111
|
||||
Tristram to Straylight = 89
|
||||
Tristram to Arbre = 132
|
||||
AlphaCentauri to Snowdin = 4
|
||||
AlphaCentauri to Tambi = 79
|
||||
AlphaCentauri to Faerun = 44
|
||||
AlphaCentauri to Norrath = 147
|
||||
AlphaCentauri to Straylight = 133
|
||||
AlphaCentauri to Arbre = 74
|
||||
Snowdin to Tambi = 105
|
||||
Snowdin to Faerun = 95
|
||||
Snowdin to Norrath = 48
|
||||
Snowdin to Straylight = 88
|
||||
Snowdin to Arbre = 7
|
||||
Tambi to Faerun = 68
|
||||
Tambi to Norrath = 134
|
||||
Tambi to Straylight = 107
|
||||
Tambi to Arbre = 40
|
||||
Faerun to Norrath = 11
|
||||
Faerun to Straylight = 66
|
||||
Faerun to Arbre = 144
|
||||
Norrath to Straylight = 115
|
||||
Norrath to Arbre = 135
|
||||
Straylight to Arbre = 127
|
||||
#+END_EXAMPLE
|
||||
:END:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :var example=9-example :var input=9-input :noweb yes
|
||||
(defun day9/make-map ()
|
||||
(make-hash-table :test #'equal))
|
||||
|
||||
(defun day9/store-distance (map a b distance)
|
||||
(puthash (cons a b) distance map))
|
||||
|
||||
(defun day9/distance (map a b)
|
||||
(gethash (cons a b) map
|
||||
(gethash (cons b a) map 0)))
|
||||
|
||||
(defun day9/parse-distance (distance-string)
|
||||
(if (string-match "\\(.*?\\) to \\(.*?\\) = \\([0-9]+\\)"
|
||||
distance-string)
|
||||
(cons (cons (match-string-no-properties 1 distance-string)
|
||||
(match-string-no-properties 2 distance-string))
|
||||
(string-to-number (match-string-no-properties 3 distance-string)))))
|
||||
|
||||
(ert-deftest day9/parse-distance ()
|
||||
(should (equal '(("London" . "Dublin") . 464)
|
||||
(day9/parse-distance "London to Dublin = 464"))))
|
||||
|
||||
(defun day9/build-map (input)
|
||||
(let ((map (day9/make-map)))
|
||||
(-each (-map #'day9/parse-distance
|
||||
(split-string input "\n" t))
|
||||
(lambda (distance)
|
||||
(day9/store-distance map
|
||||
(caar distance)
|
||||
(cdar distance)
|
||||
(cdr distance))))
|
||||
map))
|
||||
|
||||
(defun day9/trip-distance (map trip)
|
||||
(let ((start (first trip))
|
||||
(steps (rest trip)))
|
||||
(if (null steps) 0
|
||||
(+ (day9/distance map start (first steps))
|
||||
(day9/trip-distance map steps)))))
|
||||
|
||||
(defun day9/trip-distance< (min current map trip)
|
||||
(let ((start (first trip))
|
||||
(steps (rest trip)))
|
||||
(cond ((and min (> current min)) nil)
|
||||
((null steps) current)
|
||||
(t (let ((distance (day9/distance map start (first steps))))
|
||||
(day9/trip-distance< min (+ distance current) map
|
||||
steps))))))
|
||||
|
||||
(lexical-let ((example example))
|
||||
(ert-deftest day9/trip-distance ()
|
||||
(let ((map (day9/build-map example)))
|
||||
(should (eq 982 (day9/trip-distance map
|
||||
'("Dublin"
|
||||
"London"
|
||||
"Belfast")))))))
|
||||
|
||||
(defun day9/permutations (lst)
|
||||
(if (not lst) '(nil)
|
||||
(mapcan
|
||||
(lambda (e)
|
||||
(mapcar (lambda (perm) (cons e perm))
|
||||
(day9/permutations (-remove-item e lst))))
|
||||
lst)))
|
||||
|
||||
(defun day9/trips (map)
|
||||
"Don't include reversed location permutations"
|
||||
(cl-loop for perm in (day9/permutations (day9/locations map))
|
||||
with unique-perms = (make-hash-table :test 'equal)
|
||||
unless (gethash (reverse perm) unique-perms)
|
||||
do (puthash perm t unique-perms)
|
||||
finally return (hash-table-keys unique-perms)))
|
||||
|
||||
(defun day9/locations (map)
|
||||
(-distinct
|
||||
(append (-map #'car (hash-table-keys map))
|
||||
(-map #'cdr (hash-table-keys map)))))
|
||||
|
||||
(lexical-let ((example example))
|
||||
(ert-deftest day9/locations ()
|
||||
(let ((map (day9/build-map example)))
|
||||
(should (seq-empty-p
|
||||
(-difference '("Dublin" "London" "Belfast")
|
||||
(day9/locations map)))))))
|
||||
|
||||
(defun day9/min-trip-distance (map)
|
||||
(cl-loop for path in (day9/trips map)
|
||||
with min-distance
|
||||
do (let ((distance (day9/trip-distance< min-distance 0 map path)))
|
||||
(if (and (null min-distance) distance)
|
||||
(setf min-distance distance))
|
||||
(if (and min-distance distance
|
||||
(< distance min-distance))
|
||||
(setf min-distance distance)))
|
||||
finally return min-distance))
|
||||
|
||||
(day9/min-trip-distance
|
||||
(day9/build-map input))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS[052969aa6870de45711d74f55a9ef7dbd058a865]:
|
||||
: 251
|
||||
|
||||
|
|
Loading…
Reference in a new issue