Merge branch 'master' of ssh.jacopods.xyz:wilderjds/advent-2025

master
Jacopo De Simoi 3 months ago
commit 34b6995226
  1. 47
      p11/p11.org
  2. 358
      p9/p9.org

@ -0,0 +1,47 @@
#+title: solution to p11
#+begin_src emacs-lisp :results none
(with-temp-buffer
(insert-file-contents "input")
(advent/replace-multiple-regex-buffer
'((":" . " ")
("^" . "(")
("$" . ")")))
(goto-char (point-min))
(insert "(setq data '(")
(goto-char (point-max))
(insert "))")
(eval-buffer))
#+end_src
This is for part 1
#+begin_src emacs-lisp
(defun paths-from (label)
(if (eq label 'out) 1
(-sum (-map 'paths-from (cdr (assq label data))))))
(memoize 'paths-from)
(paths-from 'you)
#+end_src
#+RESULTS:
: 701
And this for part 2; note that there are no paths from dac to fft
(there can be only paths in one direction, otherwise we would get
a loop.
#+begin_src emacs-lisp
(defun paths-from-to (label exit)
(if (eq label exit) 1
(if (eq label 'out) 0
(-sum (--map (paths-from-to it exit) (cdr (assq label data)))))))
(memoize 'paths-from-to)
(* (paths-from-to 'svr 'fft)
(paths-from-to 'fft 'dac)
(paths-from 'dac))
#+end_src
#+RESULTS:
: 390108778818526

@ -1,7 +1,6 @@
#+title: Solution to p9
#+title: Solution to p9, aka the shitshow
Well, this was quite the shitshow…
I need to cleanup this mess
Load the data
#+begin_src emacs-lisp :results none
(with-temp-buffer
(insert-file-contents "input")
@ -16,20 +15,24 @@ I need to cleanup this mess
(eval-buffer))
#+end_src
Find max area
#+begin_src emacs-lisp
General preparation; the area is symmetric so I consider only
half of the pairs of vertices.
#+begin_src emacs-lisp :results none
(defun area (el)
(let ((a (car el))
(b (cdr el)))
(let ((a (car el))
(b (cdr el)))
(* (1+ (abs (- (car a) (car b))))
(1+ (abs (- (cadr a) (cadr b)))))))
(defun symmetric-pairs (list)
(apply #'append (--map-indexed (-map (lambda (other) (cons it other))
(-drop (1+ it-index) list))
list)))
(apply #'append (--map-indexed (-map (lambda (other) (cons it other))
(-drop (1+ it-index) list))
list)))
#+end_src
(-max (-map 'area (symmetric-pairs data)))
This is for part 1. Easy.
#+begin_src emacs-lisp
(-max (-map 'area (symmetric-pairs data)))
#+end_src
#+RESULTS:
@ -97,42 +100,102 @@ if it is -1, then the domain is always to the left of the edges
Now we cook up a function to check if a given point X Y is inside or outside
#+begin_src emacs-lisp :results none
;; The next two functions could be sped up by using bisection. See if it is necessary
(defun vertical-edges-up-to (x)
(--take-while (<= (caar it) x) data-vertical-edges))
(defun horizontal-edges-up-to (y)
(--take-while (<= (cadar it) y) data-horizontal-edges))
(defun vertical-edge-goes-through (edge y)
(let ((miny (min (cadar edge) (cadadr edge)))
(maxy (max (cadar edge) (cadadr edge))))
(and (< miny y) (< y maxy))))
(defun horizontal-edge-goes-through (edge x)
(let ((minx (min (caar edge) (caadr edge)))
(maxx (max (caar edge) (caadr edge))))
(and (< minx x) (< x maxx))))
(defun odd-p (n)
(= 1 (logand n 1)))
(defun even-p (n)
(= 0 (logand n 1)))
(defun inside-p (x y)
(let* ((horizontal-head (horizontal-edges-up-to y))
(vertical-head (vertical-edges-up-to x))
(x (+ x 0.5))
(y (+ y 0.5))
(filtered-horizontal-head (--filter (horizontal-edge-goes-through it x) horizontal-head))
(filtered-vertical-head (--filter (vertical-edge-goes-through it y) vertical-head)))
(and (odd-p (length filtered-horizontal-head))
(odd-p (length filtered-vertical-head)))))
;; The next two functions could be sped up by using bisection.
;; See if it is necessary
(defun vertical-edges-up-to (x)
(--take-while (<= (caar it) x) data-vertical-edges))
(defun horizontal-edges-up-to (y)
(--take-while (<= (cadar it) y) data-horizontal-edges))
(defun vertical-edge-goes-through (edge y)
(let ((miny (min (cadar edge) (cadadr edge)))
(maxy (max (cadar edge) (cadadr edge))))
(and (< miny y) (< y maxy))))
(defun horizontal-edge-goes-through (edge x)
(let ((minx (min (caar edge) (caadr edge)))
(maxx (max (caar edge) (caadr edge))))
(and (< minx x) (< x maxx))))
(defun odd-p (n)
(= 1 (logand n 1)))
(defun even-p (n)
(= 0 (logand n 1)))
(defun inside-p (x y)
(let* ((horizontal-head (horizontal-edges-up-to y))
(vertical-head (vertical-edges-up-to x))
(x (+ x 0.5))
(y (+ y 0.5))
(filtered-horizontal-head (--filter (horizontal-edge-goes-through it x) horizontal-head))
(filtered-vertical-head (--filter (vertical-edge-goes-through it y) vertical-head)))
(and (odd-p (length filtered-horizontal-head))
(odd-p (length filtered-vertical-head)))))
#+end_src
#+RESULTS:
Of course it would be too costly to check for every square in the
candidate rects, so we first remove rectangles that cannot work for a
number of reasons; since vertices are unique, if a vertex sits
strictly inside a rectangle, the rectangle must have some bad tiles
inside. We call a rect _reasonable_ if such a thing does not happen.
#+begin_src emacs-lisp
(setq rects (symmetric-pairs data))
(defun strictly-contains-p (rect p)
(let ((minx (min (caar rect) (cadr rect)))
(maxx (max (caar rect) (cadr rect)))
(miny (min (cadar rect) (caddr rect)))
(maxy (max (cadar rect) (caddr rect)))
(px (car p))
(py (cadr p)))
(and (< minx px) (< px maxx)
(< miny py) (< py maxy))))
(setq reasonable-rects
(-remove (lambda (rect) (--any (strictly-contains-p rect it) data)) rects))
(length reasonable-rects)
#+end_src
Nice, that is an OK number.
Since a rectangle is reasonable, possible edges that cut through it
would have to do through all of it. We can thus check along the edges
only
#+begin_src emacs-lisp
(defun whole-rect-inside-p (rect)
(let ((minx (min (caar rect) (cadr rect)))
(maxx (max (caar rect) (cadr rect)))
(miny (min (cadar rect) (caddr rect)))
(maxy (max (cadar rect) (caddr rect))))
;; Check along the minx column and miny row
(and (--every (inside-p minx it) (-iota (- maxy miny) miny))
(--every (inside-p it miny) (-iota (- maxx minx) minx)))))
(setq sorted-reasonable-rects (--sort (> (area it) (area other)) reasonable-rects))
#+end_src
Let me be silly and draw the thing.
Grab some popcorn, this will take a while
#+begin_src emacs-lisp
(let ((num 0))
(setq largest-good-rect (--first (progn
(message (format "%d" (setq num (1+ num))))
(whole-rect-inside-p it))
sorted-reasonable-rects)))
(area largest-good-rect)
#+end_src
#+RESULTS:
1644094530
what follows is an alternative way... first realize what the shape
looks like
#+begin_src emacs-lisp
(setq svg-preamble "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<svg
@ -180,21 +243,13 @@ Let me be silly and draw the thing.
(scale-coordinate (cadar it))
(scale-coordinate (caadr it))
(scale-coordinate (cadadr it)))))
(insert (format "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" style=\"fill:FF000080\"/>"
(scale-coordinate 5639)
(scale-coordinate 50249)
(scale-coordinate (- 94532 5639))
(scale-coordinate (- 68743 50249))))
(insert "</svg>")
)
(write-file "tmp-2.svg")))
(write-file "tmp.svg")))
(draw-svg)
#+end_src
#+RESULTS:
Oh motherfucker; the domain has a very special shape.
Oh motherfucker;
Find the two possible vertices
#+begin_src emacs-lisp
@ -238,196 +293,5 @@ Find the two possible vertices
#+RESULTS:
| (94532 50249) | 5639 | 68743 |
#+begin_src emacs-lisp
largest-good-rect
#+end_src
#+RESULTS:
| (5639 68743) | 94532 | 50249 |
(area largest-good-rect)
1644057540
Of course it would be too costly to check for every square in the
candidate rects, so we first remove rectangles that cannot work for a
number of reasons; since vertices are unique, if a vertex sits
strictly inside a rectangle, the rectangle must have some bad tiles
inside. We call a rect _reasonable_ if such a thing does not happen.
#+begin_src emacs-lisp
(setq rects (symmetric-pairs data))
(defun strictly-contains-p (rect p)
(let ((minx (min (caar rect) (cadr rect)))
(maxx (max (caar rect) (cadr rect)))
(miny (min (cadar rect) (caddr rect)))
(maxy (max (cadar rect) (caddr rect)))
(px (car p))
(py (cadr p)))
(and (< minx px) (< px maxx)
(< miny py) (< py maxy))))
(setq reasonable-rects
(-remove (lambda (rect) (--any (strictly-contains-p rect it) data)) rects))
(length reasonable-rects)
#+end_src
Nice, that is an OK number.
Since a rectangle is reasonable, possible edges that cut through it
would have to do through all of it. We can thus check along the edges
only
#+begin_src emacs-lisp
(defun whole-rect-inside-p (rect)
(let ((minx (min (caar rect) (cadr rect)))
(maxx (max (caar rect) (cadr rect)))
(miny (min (cadar rect) (caddr rect)))
(maxy (max (cadar rect) (caddr rect))))
;; Check along the minx column and miny row
(and (--every (inside-p minx it) (-iota (- maxy miny) miny))
(--every (inside-p it miny) (-iota (- maxx minx) minx)))))
(setq sorted-reasonable-rects (--sort (> (area it) (area other)) reasonable-rects))
#+end_src
Grab some popcorn, this will take a while
#+begin_src emacs-lisp
(let ((num 0))
(setq largest-good-rect (--first (progn
(message (format "%d" (setq num (1+ num))))
(whole-rect-inside-p it))
sorted-reasonable-rects)))
#+end_src
#+RESULTS:
| (5639 68743) | 94532 | 50249 |
(area largest-good-rect)
1644094530
1644057540 ; it does not work.
*
Then we can go from here...
*
** This is old stuff
#+begin_src emacs-lisp :results none
(defun corner-normal (corner)
(let* ((cor (cdr corner))
(a (caar cor))
(d (caddr cor))
(b (cadar cor))
(c (cadr cor))
(det (* orientation (- (* b c) (* a d)))))
(list det (- c a) (- d b))))
(setq data-normals (--map (cons (car it) (corner-normal it)) data-corners))
(setq rects (symmetric-pairs data))
;; first filter those rectangles that are defined by vertices that
;; have the wrong orientation
(defun compatible-or (u v)
(if (or (= (car u) 0) (= (cadr u) 0)) t
(if (> (car v) 0) (equal u (cdr v)) ;convex corner
(not (equal u (cdr v))) ;concave corner
)))
(defun good-orientation-p (rect)
(let ((a (assoc (car rect) data-normals))
(b (assoc (cdr rect) data-normals)))
(and (compatible-or (cornerize (car b) (car a)) (cdr b))
(compatible-or (cornerize (car a) (car b)) (cdr a)))))
(setq good-rects (-filter #'good-orientation-p rects))
;; then filter away those that strictly contain a vertex
(defun strictly-contains-p (rect p)
(let ((minx (min (caar rect) (cadr rect)))
(maxx (max (caar rect) (cadr rect)))
(miny (min (cadar rect) (caddr rect)))
(maxy (max (cadar rect) (caddr rect)))
(px (car p))
(py (cadr p)))
(and (< minx px) (< px maxx)
(< miny py) (< py maxy))))
(setq rects-sifted (-remove (lambda (rect) (--any (strictly-contains-p rect it) data)) good-rects))
(length rects-sifted)
#+end_src
#+begin_src emacs-lisp :results none
(defun incompatible-p (rect corner)
(let ((minx (min (caar rect) (cadr rect)))
(maxx (max (caar rect) (cadr rect)))
(miny (min (cadar rect) (caddr rect)))
(maxy (max (cadar rect) (caddr rect)))
(px (caar corner))
(py (cadar corner))
(convexity (cadr corner))
(normal (cddr corner)))
(or (and (= px minx) (< miny py) (< py maxy) (< (advent/dot normal (list convexity 0)) 0)) ; on left edge
(and (= px maxx) (< miny py) (< py maxy) (> (advent/dot normal (list convexity 0)) 0))
(and (= py miny) (< minx px) (< px maxx) (< (advent/dot normal (list 0 convexity)) 0))
(and (= py maxy) (< minx px) (< px maxx) (> (advent/dot normal (list 0 convexity)) 0)))))
(setq rects-refined (-remove (lambda (rect) (--any (incompatible-p rect it) data-normals)) rects-sifted))
#+end_src
Now we should have eliminated all corner cases; we just need to remove
those that are cut by an edge
#+begin_src emacs-lisp
(length rects)
(length good-rects)
(length rects-sifted)
(length rects-refined)
(defun cuts-p (rect edge)
(let* ((minx (min (caar rect) (cadr rect)))
(maxx (max (caar rect) (cadr rect)))
(miny (min (cadar rect) (caddr rect)))
(maxy (max (cadar rect) (caddr rect)))
(eminx (min (caar edge) (caadr edge)))
(emaxx (max (caar edge) (caadr edge)))
(eminy (min (cadar edge) (cadadr edge)))
(emaxy (max (cadar edge) (cadadr edge)))
(ver (= eminx emaxx)))
(if ver (and (< minx eminx) (< eminx maxx) (< eminy miny) (< maxy emaxy))
(and (< miny eminy) (< eminy maxy) (< eminx minx) (< maxx emaxx))))
)
(setq rects-uncut (-remove (lambda (rect) (--any (cuts-p rect it) edges)) rects-refined))
(length rects-uncut)
(-max (-map #'area rects-uncut))
#+end_src
#+RESULTS:
: 1644057540
| (11 1) | 7 | 3 |
| (11 7) | 9 | 7 |
| (11 7) | 9 | 5 |
| (11 7) | 2 | 5 |
| (11 7) | 2 | 3 |
| (11 7) | 7 | 3 |
| (9 7) | 9 | 5 |
| (9 7) | 2 | 5 |
| (9 7) | 2 | 3 |
| (9 7) | 7 | 3 |
| (9 5) | 2 | 5 |
| (9 5) | 2 | 3 |
| (9 5) | 7 | 3 |
| (2 5) | 2 | 3 |
| (2 5) | 7 | 3 |
| (2 3) | 7 | 3 |

Loading…
Cancel
Save