[p21] Part 1

main
Jacopo De Simoi 6 months ago
parent 0cbe285d54
commit ac514c1cbc
  1. 149
      p21/p21.org

@ -0,0 +1,149 @@
#+title: Solution to p21
Load map
#+begin_src emacs-lisp :results none
(require 'dash)
(with-temp-buffer
(insert-file-contents "input-test")
(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)))
#+end_src
#+begin_src emacs-lisp :results none
(setq numeric-keypad '("789"
"456"
"123"
" 0A"))
(setq dir-keypad '(" ^A"
"<v>"))
(setq numeric-keypad-data (-map #'advent/split-string-into-char-list numeric-keypad)
dir-keypad-data (-map #'advent/split-string-into-char-list dir-keypad))
#+end_src
This function takes a string and returns a list of ~(a . b)~, where
these are the adjacent pairs in the string. For instance, if you feed
it with "ABC" it will return ((?A . ?B) (?B . ?C))
#+begin_src emacs-lisp :results none
(defun split-into-char-pairs (s)
(let ((char-list (advent/split-string-into-char-list s)))
(-zip-pair (-drop-last 1 char-list) (-drop 1 char-list))))
(defun char-pairs-to-coordinate-pairs (p keypad)
(cons
(car (advent/coordinates-of (car p) keypad))
(car (advent/coordinates-of (cdr p) keypad))))
#+end_src
This takes a cons cell (p . q) of positions and returns all paths that
go from p to q without getting out of the boundary
#+begin_src emacs-lisp
(defun subtract-vector (a b)
(-zip-with #'- a b))
(defun add-vector (a b)
(-zip-with #'+ a b))
(defun permute-string (s)
"Return a list with all strings that can be obtained by permuting
characters of S"
(--map (apply #'string it)
(-permutations
(advent/split-string-into-char-list s))))
(defun connecting-paths (r keypad)
(--map (concat it "A")
(--filter (path-allowed-p it (car r) keypad)
(let* ((difference (subtract-vector (cdr r) (car r)))
(hor (car difference))
(ver (cadr difference)))
(permute-string (concat
(if (< hor 0) (make-string (- 0 hor) ?<)
(make-string hor ?>))
(if (< ver 0) (make-string (- 0 ver) ?^)
(make-string ver ?v))))))))
(setq dir-alist '((?> .(1 0))
(?< . (-1 0))
(?^ . (0 -1))
(?v . (0 1))))
(defun path-allowed-p (s start keypad)
(not (--any (eq it 32)
(--map (advent/char-at it keypad)
(-reductions-from #'add-vector start (--map (cdr (assoc it dir-alist)) (advent/split-string-into-char-list s)))))))
#+end_src
#+RESULTS:
: path-allowed-p
#+begin_src emacs-lisp
(defun directions-for-string (s keypad-data)
(--map (connecting-paths it keypad-data)
(--map
(char-pairs-to-coordinate-pairs it keypad-data)
(split-into-char-pairs (concat "A" s)))))
(defun pick-shortest-string (l)
"picks the shortest string in the list L"
(-reduce (lambda (a b)
(if (> (length a) (length b)) b a))
l))
(defun shortest-path (s)
(let* ((first-directional-keypad
(directions-for-string s numeric-keypad-data))
(second-directional-keypad
(--map ; this iterates on the possible sequences of the num
(--map (directions-for-string it dir-keypad-data) it)
first-directional-keypad))
(third-directional-keypad
(--map ; this iterates on the possible sequences of the num
(--map ; this iterates on the possible sequences for the dir #1
(--map ; this iterates on the possible sequences for the dir #2
(--map
(directions-for-string it dir-keypad-data)
it)
it)
it)
second-directional-keypad)
))
(let* ((level-two
(--map
(--map
(--map
(--map
(apply #'concat (-map #'pick-shortest-string it))
it)
it)
it)
third-directional-keypad))
(level-one
(--map
(--map
(apply #'concat (-map #'pick-shortest-string it))
it)
level-two)))
(apply #'concat (-map #'pick-shortest-string level-one)))))
(defun replace-in-string (what with in)
(replace-regexp-in-string (regexp-quote what) with in nil 'literal))
(defun complexity (s)
(* (string-to-number (replace-in-string "A" "" s))
(length (shortest-path s))))
(-reduce #'+ (-map #'complexity data))
#+end_src
#+RESULTS:
: 222670
Loading…
Cancel
Save