|
|
|
|
@ -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,8 +15,9 @@ 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))) |
|
|
|
|
@ -28,7 +28,10 @@ Find max area |
|
|
|
|
(apply #'append (--map-indexed (-map (lambda (other) (cons it other)) |
|
|
|
|
(-drop (1+ it-index) list)) |
|
|
|
|
list))) |
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
This is for part 1. Easy. |
|
|
|
|
#+begin_src emacs-lisp |
|
|
|
|
(-max (-map 'area (symmetric-pairs data))) |
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
@ -97,7 +100,8 @@ 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 |
|
|
|
|
;; 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)) |
|
|
|
|
@ -132,7 +136,66 @@ Now we cook up a function to check if a given point X Y is inside or outside |
|
|
|
|
(odd-p (length filtered-vertical-head))))) |
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
Let me be silly and draw the thing. |
|
|
|
|
|
|
|
|
|
#+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 |
|
|
|
|
|
|
|
|
|
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. |
|
|
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
** 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)))) |
|
|
|
|
Then we can go from here... |
|
|
|
|
|
|
|
|
|
(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 | |
|
|
|
|
|