From 9978ef9367566fdea7bded0ebb7eb3a4857fcb2f Mon Sep 17 00:00:00 2001 From: Jacopo De Simoi Date: Thu, 17 Apr 2025 16:28:49 -0400 Subject: [PATCH] New attempt --- p16/p16.org | 65 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/p16/p16.org b/p16/p16.org index 8674ace..e307d96 100644 --- a/p16/p16.org +++ b/p16/p16.org @@ -4,7 +4,7 @@ Load map #+begin_src emacs-lisp :results none (require 'dash) (with-temp-buffer - (insert-file-contents "input-test2") + (insert-file-contents "input") (goto-char (point-min)) (replace-regexp "^\\(#.*#\\)$" "\"\\1\"") (goto-char (point-min)) @@ -75,45 +75,72 @@ associated scores; (explore start '(1 0) 0) #+end_src +For debugging, print the map +#+begin_src emacs-lisp + (defun plot (p s) + (goto-line (+ (cadr p) 1)) + (move-to-column (car p)) + (insert s) + (delete-char 1)) + + (defun print-map (p) + (with-temp-buffer + (-each data (lambda (x) (insert x) (insert "\n"))) + (-each book (lambda (x) (if (cdr x) (plot (caar x) ?x) + (plot (caar x) ?!)))) + (plot p ?@) + (write-file "tmp")) ) + + +#+end_src + +#+RESULTS: +: print-map + In principle the above would work as-is, but it is not very efficient. In the version below, we record dead-ends and partial solutions #+begin_src emacs-lisp (defun >nil (a b) - (when b - (or (not a) (> a b)))) + (when (numberp b) + (or (not (numberp a)) (> a b)))) (defun subtract-nil (a b) - (when (and a b) + (when (and (numberp a) (numberp b)) (- a b))) (defun +nil (a b) - (when (and a b) + (when (and (numberp a) (numberp b)) (+ a b))) (defun neighbour-maybe (p dir newdir) (if (not (equal dir newdir)) p (neighbour p newdir))) - (defun explore (p dir score &optional past) + (defun forward-dirs (dir olddir) + (if (not (equal dir olddir)) (list dir) + (cons dir (--filter (= (dot it dir) 0) '((0 1) (0 -1) (-1 0) (1 0)))))) + + (defun explore (p dir old-dir score &optional past) "Explore the maze starting at position P and in the direction DIR. Returns nil if we will dead-end or loop or the score if we reach the end" (if (eq (thing-at p) 'end) score (if (assoc (list p dir) book) (+nil score (cdr (assoc (list p dir) book))) ; check the book for this position and direction - (unless (-contains-p (cdr past) p) ; loop - (let* ((forward-dirs (--filter (>= (dot it dir) 0) '((0 1) (0 -1) (-1 0) (1 0)))) - (acceptable-dirs (--filter (not (eq (thing-at (neighbour p it)) 'wall)) forward-dirs)) - (new-score (-min-by #'>nil (-map (lambda (newdir) - (explore (neighbour-maybe p dir newdir) newdir - (+ score (if (equal newdir dir) 1 1000)) - (cons p past))) - acceptable-dirs)))) - (push (cons (list p dir) (subtract-nil new-score score)) book) - new-score))))) - - (setq book nil) - (explore start '(1 0) 0) + (if (-contains-p (cdr past) p) 'loop + (let* ((acceptable-dirs (--filter (not (eq (thing-at (neighbour p it)) 'wall)) (forward-dirs dir old-dir))) + (new-score (-min-by #'>nil (-map (lambda (newdir) + (explore (neighbour-maybe p dir newdir) newdir dir + (+ score (if (equal newdir dir) 1 1000)) + (-distinct (cons p past)))) + acceptable-dirs)))) + (when (not (eq new-score 'loop)) (push (cons (list p dir) (subtract-nil new-score score)) book)) + new-score))))) + + (setq book nil) + (explore start '(1 0) '(1 0) 0) #+end_src #+RESULTS: : 11048 + +(print-map)