Solution to p15 part 1

main
Jacopo De Simoi 11 months ago
parent 328015a33f
commit c7204bf0b4
  1. 152
      p15/p15.org

@ -1,9 +1,10 @@
#+title: Solution to p15
#+begin_src emacs-lisp
Process the input file to create the maps and the sequence of moves
#+begin_src emacs-lisp :results none
(require 'dash)
(with-temp-buffer
(insert-file-contents "input-fuffa")
(insert-file-contents "input")
(goto-char (point-min))
(replace-regexp "^\\(#.*#\\)$" "\"\\1\"")
(goto-char (point-min))
@ -13,7 +14,7 @@
(goto-char (point-min))
(replace-regexp "<" "( -1 0)")
(goto-char (point-min))
(replace-regexp ">" "( 1 0)")
(replace-regexp ">" "( 1 0)")
(goto-char (point-min))
(replace-regexp "v" "( 0 1)")
(goto-char (point-min))
@ -21,106 +22,93 @@
(goto-char (point-max))
(insert "))")
(eval-buffer))
#+end_src
#+RESULTS:
read and parse the map
#+begin_src emacs-lisp
(setq map-things (-map (lambda (str) (-map #'string-to-char (split-string str "\\|.+" t)))
map)
height (length map-things)
width (length (car map-things)))
(defun stuff-coordinates (e)
Read and parse the map to extract the positions of the various
elements
#+begin_src emacs-lisp :results none
(setq map-things (-map
(lambda (str) (-map #'string-to-char (split-string
str "\\|.+" t)))
map)
height (length map-things)
width (length (car map-things)))
(defun coordinates-of (e)
(-map #'cadr
(--filter (eq (car it) e)
(-mapcat #'identity
(-map-indexed (lambda (y l) (-map-indexed (lambda (x el) (list el (list x y))) l)) map-things))))
)
(setq walls (stuff-coordinates ?#)
crates (stuff-coordinates ?O)
robot (car (stuff-coordinates ?@)))
(--filter (eq (car it) e)
(-mapcat #'identity
(-map-indexed (lambda (y l)
(-map-indexed (lambda (x el) (list el (list x y))) l))
map-things)))))
(setq walls (coordinates-of ?#)
crates (coordinates-of ?O)
robot (car (coordinates-of ?@)))
#+end_src
#+RESULTS:
| 2 | 2 |
#+begin_src emacs-lisp
(defun thing-at (p)
(cond
((equal p robot) 'robot)
((-contains-p walls p) 'wall)
((-contains-p crates p) 'crate)
(t nil)))
(defun neigh (p dir)
(list (+ (car p) (car dir)) (+ (cadr p) (cadr dir))))
(defun do-move (what from to)
Implement the move logic. The key function is try-move: it tries to
move stuff in some direction and push anything it can along the way by
calling itself recursively to see if whatever is on the way can itself
be pushed.
#+begin_src emacs-lisp :results none
(defun thing-at (p)
"Returns which object (if any) is present at position P"
(cond
((equal p robot) 'robot)
((-contains-p walls p) 'wall)
((-contains-p crates p) 'crate)
(t nil)))
(defun neighbour (p dir)
"Returns the neighbour to P in the direction DIR"
(list (+ (car p) (car dir))
(+ (cadr p) (cadr dir))))
(defun do-move (from to)
"Updates the content of the warehouse by moving whatever is at
FROM to the position TO"
(cond
((eq (thing-at from) 'crate) (setq crates (-replace from to crates)))
(t (setq robot to))))
(defun try-move (p dir)
"Try to move the object at P in the direction DIR"
(let ((thing (thing-at p)))
(cond
((equal what 'crate) (setq crates (-replace from to crates)))
(t (setq robot to))
(print crates))
)
(defun move (p dir)
(let ((thing (thing-at p)))
(cond
((not thing) t)
((equal thing 'wall))
(t (let ((dest (neigh p dir)))
(when (move dest dir)
(do-move thing p dest)))))))
((not thing) t)
((eq thing 'wall) nil)
(t (let ((dest (neighbour p dir)))
(when (try-move dest dir)
(do-move p dest)))))))
#+end_src
#+RESULTS:
: move
#+begin_src emacs-lisp
This is just to make pretty pictures of the current state
#+begin_src emacs-lisp :results none
(defun make-bg ()
(insert (apply #'concat (-repeat height (concat (concat (-repeat width ?. )) "\n")))))
(defun plot (p s)
(goto-line (- (cadr p) 1))
(move-to-column (car p))
(insert s)
(delete-char 1))
(defun plot-walls ()
(--map (plot it "#") walls))
(defun plot-crates ()
(--map (plot it "O") crates))
(defun plot (p s)
(goto-line (+ (cadr p) 1))
(move-to-column (car p))
(insert s)
(delete-char 1))
(defun save-pic ()
(with-temp-buffer
(make-bg)
(plot-walls)
(plot-crates)
(--map (plot it "#") walls); should use --each
(--map (plot it "O") crates)
(plot robot "@")
(write-file "test-out")))
#+end_src
#+RESULTS:
: save-pic
Finally, implement the moves and compute the result for part 1
#+begin_src emacs-lisp
(move robot (car commands))
(setq commands (cdr commands))
(--map (try-move robot it) commands)
(save-pic)
(-reduce #'+ (--map (+ (car it) (* 100 (cadr it))) crates))
#+end_src
#+RESULTS:
#+begin_src
(--map (move robot it) commands)
; (-reduce #'+ (--map (+ (car it) (* 100 (cadr it))) crates))
#+end_src
#+RESULTS:
: 2024
crates
: 1371036

Loading…
Cancel
Save