day 15 p.1: scanners and beacons, bad solution

This commit is contained in:
efim 2022-12-16 12:13:37 +00:00
parent 6757e3ba23
commit 190382eddc
4 changed files with 346 additions and 0 deletions

33
day15-input.txt Normal file
View File

@ -0,0 +1,33 @@
Sensor at x=2302110, y=2237242: closest beacon is at x=2348729, y=1239977
Sensor at x=47903, y=2473047: closest beacon is at x=-432198, y=2000000
Sensor at x=2363579, y=1547888: closest beacon is at x=2348729, y=1239977
Sensor at x=3619841, y=520506: closest beacon is at x=2348729, y=1239977
Sensor at x=3941908, y=3526118: closest beacon is at x=3772294, y=3485243
Sensor at x=3206, y=1564595: closest beacon is at x=-432198, y=2000000
Sensor at x=3123411, y=3392077: closest beacon is at x=2977835, y=3592946
Sensor at x=3279053, y=3984688: closest beacon is at x=2977835, y=3592946
Sensor at x=2968162, y=3938490: closest beacon is at x=2977835, y=3592946
Sensor at x=1772120, y=2862246: closest beacon is at x=2017966, y=3158243
Sensor at x=3283241, y=2619168: closest beacon is at x=3172577, y=2521434
Sensor at x=2471642, y=3890150: closest beacon is at x=2977835, y=3592946
Sensor at x=3163348, y=3743489: closest beacon is at x=2977835, y=3592946
Sensor at x=2933313, y=2919047: closest beacon is at x=3172577, y=2521434
Sensor at x=2780640, y=3629927: closest beacon is at x=2977835, y=3592946
Sensor at x=3986978, y=2079918: closest beacon is at x=3998497, y=2812428
Sensor at x=315464, y=370694: closest beacon is at x=-550536, y=260566
Sensor at x=3957316, y=3968366: closest beacon is at x=3772294, y=3485243
Sensor at x=2118533, y=1074658: closest beacon is at x=2348729, y=1239977
Sensor at x=3494855, y=3378533: closest beacon is at x=3772294, y=3485243
Sensor at x=2575727, y=210553: closest beacon is at x=2348729, y=1239977
Sensor at x=3999990, y=2813525: closest beacon is at x=3998497, y=2812428
Sensor at x=3658837, y=3026912: closest beacon is at x=3998497, y=2812428
Sensor at x=1551619, y=1701155: closest beacon is at x=2348729, y=1239977
Sensor at x=2625855, y=3330422: closest beacon is at x=2977835, y=3592946
Sensor at x=3476946, y=2445098: closest beacon is at x=3172577, y=2521434
Sensor at x=2915568, y=1714113: closest beacon is at x=2348729, y=1239977
Sensor at x=729668, y=3723377: closest beacon is at x=-997494, y=3617758
Sensor at x=3631681, y=3801747: closest beacon is at x=3772294, y=3485243
Sensor at x=2270816, y=3197807: closest beacon is at x=2017966, y=3158243
Sensor at x=3999999, y=2810929: closest beacon is at x=3998497, y=2812428
Sensor at x=3978805, y=3296024: closest beacon is at x=3772294, y=3485243
Sensor at x=1054910, y=811769: closest beacon is at x=2348729, y=1239977

185
day15-scratch.lisp Normal file
View File

@ -0,0 +1,185 @@
;; https://adventofcode.com/2022/day/15
;;
;; oh, wow. i can already imagine the second part of the task
;; so. for arrangements of (sensor closest-beacon)
;; i need to figure out which points are out of rangle for all sensors?
;; where "range" is distance between sensor and the closest-beacon
;;
;; so for each sensor also store distance, and each sensor should be able to answer query for point
;; whether it disproves existence of a beacone there
;; then for ( POINTS x SENSORS ) computations i'll be able to mark all points that aren't covered.
;;
;; doesn't seem like too much
(ql:quickload 'cl-ppcre)
;; poor man's parsing
(rest (mapcar (lambda (str)
(parse-integer str :junk-allowed t))
(cl-ppcre:split "="
"Sensor at x=2, y=18: closest beacon is at x=-2, y=15")))
;; manhattan distance : https://en.wikipedia.org/wiki/Taxicab_geometry
;; sum of abs of coord-diffs
(defclass point ()
((x :initarg :x :reader x)
(y :initarg :y :reader y)))
(defmethod print-object ((obj point) stream)
(print-unreadable-object (obj stream :type t)
(with-slots (x y)
obj
(format stream "x:~a y:~a" x y))))
(defparameter *test-point-1*
(make-instance 'point :x 1 :y 19))
(defparameter *test-point-2*
(make-instance 'point :x -2 :y -20))
(defmethod manh-dist ((one point) (two point))
(+ (abs (- (x one) (x two)))
(abs (- (y one) (y two)))))
(manh-dist *test-point-1* *test-point-2*)
;; i guess this is right
(defclass sensor ()
((self-coord :initarg :self :reader self-coord)
(beacon-coord :initarg :beacon :reader beacon-coord)
(covered-dist :initarg :dist :reader covered-dist)))
(defun make-sensor (sens-x sens-y beac-x beac-y)
(let* ((sensor (make-instance 'point :x sens-x :y sens-y))
(beacon (make-instance 'point :x beac-x :y beac-y))
(dist (manh-dist sensor beacon)))
(make-instance 'sensor :self sensor :beacon beacon :dist dist)))
(defmethod print-object ((obj sensor) stream)
(print-unreadable-object (obj stream :type t)
(with-slots (self-coord beacon-coord covered-dist)
obj
(format stream "at: ~a, linked to: ~a, covering dist: ~a"
self-coord beacon-coord covered-dist))))
(defparameter *test-sensor* (make-sensor 2 18 -2 15))
(defmethod can-have-unknown-beacon-p ((p point) (s sensor))
(> (manh-dist p (self-coord s))
(covered-dist s)))
(manh-dist *test-point-1* (self-coord *test-sensor*))
(can-have-unknown-beacon-p *test-point-1* *test-sensor*)
(manh-dist *test-point-2* (self-coord *test-sensor*))
(can-have-unknown-beacon-p *test-point-2* *test-sensor*)
;; ok. now read in all sensors?
;; and then for line with specified 'y'
;; and from leftmost to rightmost S or B for each point ask each sensor if possible
;; to have an unknown beacon, if any says "no" - then no
;; otherwise - count
(defparameter *day15-input-file* "day15-test.txt")
(defun line-to-coords (line)
(rest (mapcar (lambda (str)
(parse-integer str :junk-allowed t))
(cl-ppcre:split "=" line))))
(defparameter *day15-sensors-list* nil)
(setq *day15-sensors-list*
(mapcar (lambda (coords-list)
(apply #'make-sensor coords-list))
(mapcar #'line-to-coords (uiop:read-file-lines *day15-input-file*))))
;; next - find lovest x and highest x
;; but then i guess i'd also want lovest and highest y overall
;; that's neat
(loop
for sensor in *day15-sensors-list*
minimize (x (self-coord sensor)) into xs
minimize (x (beacon-coord sensor)) into xs
maximize (x (self-coord sensor)) into xm
maximize (x (beacon-coord sensor)) into xm
minimize (y (self-coord sensor)) into ys
minimize (y (beacon-coord sensor)) into ys
maximize (y (self-coord sensor)) into ym
maximize (y (beacon-coord sensor)) into ym
finally (return (list xs xm ys ym)))
;; (-2 25 0 22)
;; now for line y=10 check all x and count how many -for-all- sensors allow new point
(defun all-sensors-allow-for-hidden-beacon (point sensors)
(macroexpand `(and ,@(mapcar (lambda (sensor) (can-have-unknown-beacon-p point sensor))
sensors))))
(defun all-sensors-allow-for-hidden-beacon (point sensors)
(not (position nil (mapcar (lambda (sensor) (can-have-unknown-beacon-p point sensor))
sensors))))
;; well, do i have to write my own function for AND ?
(when (all-sensors-allow-for-hidden-beacon *test-point-2* *day15-sensors-list*)
1)
(when (all-sensors-allow-for-hidden-beacon *test-point-1* *day15-sensors-list*)
1)
;; count how many ARE covered
(loop
for x from -2 to 25
count (not (all-sensors-allow-for-hidden-beacon
(make-instance 'point :x x :y 10)
*day15-sensors-list*)))
;; on the image it's from -2 and till 24, so should be 27, if counting 0
;; well. we're counting posistions "wher beacon can't possibly exist"
;; so removing points which _are_ beacons?
;;
;; and - range needs to be extended significantly, no?
;; what would be enough?
;; doubling into each direction?
(defmethod points-equal ((left point) (right point))
(and (= (x left) (x right))
(= (y left) (y right))))
(points-equal (make-instance 'point :x 1 :y 1)
(make-instance 'point :x 1 :y 1))
(defun possible-to-have-beacon (point sensors)
(let ((all-checks
(mapcar (lambda (sensor)
(if (points-equal point (beacon-coord sensor))
'known-sensor
(can-have-unknown-beacon-p point sensor) ; single NIL means - not possible to have unknown
))
sensors)))
(or (not (position nil all-checks)) ; nil if all sensors allow (said T) presense of unknown beacons
(position 'known-sensor all-checks) ; exists known sensor
)))
;; beacon is possible : either sensor has beacon at that point
;; or position is out of the sensor range
;; but here's the thing. if sencor-beacon is at this point - need to short-circuit T
(possible-to-have-beacon *test-point-2* *day15-sensors-list*)
(possible-to-have-beacon *test-point-1* *day15-sensors-list*)
(possible-to-have-beacon (make-instance 'point :x -2 :y 15) *day15-sensors-list*)
;; i guess that works
;; count how many ARE covered
(loop
for x from -2 to 25
count (not (possible-to-have-beacon
(make-instance 'point :x x :y 10)
*day15-sensors-list*)))
;; ok.

14
day15-test.txt Normal file
View File

@ -0,0 +1,14 @@
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
Sensor at x=9, y=16: closest beacon is at x=10, y=16
Sensor at x=13, y=2: closest beacon is at x=15, y=3
Sensor at x=12, y=14: closest beacon is at x=10, y=16
Sensor at x=10, y=20: closest beacon is at x=10, y=16
Sensor at x=14, y=17: closest beacon is at x=10, y=16
Sensor at x=8, y=7: closest beacon is at x=2, y=10
Sensor at x=2, y=0: closest beacon is at x=2, y=10
Sensor at x=0, y=11: closest beacon is at x=2, y=10
Sensor at x=20, y=14: closest beacon is at x=25, y=17
Sensor at x=17, y=20: closest beacon is at x=21, y=22
Sensor at x=16, y=7: closest beacon is at x=15, y=3
Sensor at x=14, y=3: closest beacon is at x=15, y=3
Sensor at x=20, y=1: closest beacon is at x=15, y=3

114
day15.lisp Normal file
View File

@ -0,0 +1,114 @@
;; https://adventofcode.com/2022/day/15
(ql:quickload 'cl-ppcre)
(defparameter *day15-input-file* "day15-test.txt")
(defclass point ()
((x :initarg :x :reader x)
(y :initarg :y :reader y)))
(defmethod print-object ((obj point) stream)
(print-unreadable-object (obj stream :type t)
(with-slots (x y)
obj
(format stream "x:~a y:~a" x y))))
(defmethod points-equal ((left point) (right point))
(and (= (x left) (x right))
(= (y left) (y right))))
(defclass sensor ()
((self-coord :initarg :self :reader self-coord)
(beacon-coord :initarg :beacon :reader beacon-coord)
(covered-dist :initarg :dist :reader covered-dist)))
(defun make-sensor (sens-x sens-y beac-x beac-y)
(let* ((sensor (make-instance 'point :x sens-x :y sens-y))
(beacon (make-instance 'point :x beac-x :y beac-y))
(dist (manh-dist sensor beacon)))
(make-instance 'sensor :self sensor :beacon beacon :dist dist)))
(defmethod print-object ((obj sensor) stream)
(print-unreadable-object (obj stream :type t)
(with-slots (self-coord beacon-coord covered-dist)
obj
(format stream "at: ~a, linked to: ~a, covering dist: ~a"
self-coord beacon-coord covered-dist))))
(defmethod can-have-unknown-beacon-p ((p point) (s sensor))
(> (manh-dist p (self-coord s))
(covered-dist s)))
(defun line-to-coords (line)
(rest (mapcar (lambda (str)
(parse-integer str :junk-allowed t))
(cl-ppcre:split "=" line))))
(defun get-sensors-list (input-file-name)
(mapcar (lambda (coords-list)
(apply #'make-sensor coords-list))
(mapcar #'line-to-coords (uiop:read-file-lines input-file-name))))
(defun get-limits (sensors-list)
(loop
for sensor in sensors-list
minimize (x (self-coord sensor)) into xs
minimize (x (beacon-coord sensor)) into xs
maximize (x (self-coord sensor)) into xm
maximize (x (beacon-coord sensor)) into xm
minimize (y (self-coord sensor)) into ys
minimize (y (beacon-coord sensor)) into ys
maximize (y (self-coord sensor)) into ym
maximize (y (beacon-coord sensor)) into ym
finally (return (list xs xm ys ym))))
(defun possible-to-have-beacon (point sensors)
(let ((all-checks
(mapcar (lambda (sensor)
(if (points-equal point (beacon-coord sensor))
'known-sensor
(can-have-unknown-beacon-p point sensor) ; single NIL means - not possible to have unknown
))
sensors)))
(or (not (position nil all-checks)) ; nil if all sensors allow (said T) presense of unknown beacons
(position 'known-sensor all-checks) ; exists known sensor
)))
(defun count-certainly-not-beacons (input-file-name)
(let ((sensors (get-sensors-list input-file-name)))
(destructuring-bind (min-x max-x min-y max-y)
(get-limits sensors)
(let ((to-add-x (abs (- max-x min-x)))
;; (to-check-y 10)
(to-check-y 2000000)
)
(loop
for x from (- min-x to-add-x) to (+ max-x to-add-x)
count (not (possible-to-have-beacon
(make-instance 'point :x x :y to-check-y)
sensors))
do (format t "iterating for x:~a y:~a~%" x to-check-y))))))
(count-certainly-not-beacons "day15-test.txt")
(count-certainly-not-beacons "day15-input.txt")
;; well, that's just too slow
;; how do i rewrite it to make it faster?
;; i guess i could exclude the sensors which are too far away from the list?
;;
;; well, optimization here that we move by 1 point toward or away from sensor
;; so, we can kind of calculate when we'll be in it's range?
;; * in what amount of steps
;; ** whoa, org colors
;;
;; so.
;; PART 2 - just start search overnight?
;; for 0 to 4.000.000 by x and y?
;; and collect all such possible x and y?
;; nope, even if it were 5 minutes for 16mil,
;; so 2 minutes per 4 mil, then multiply by 4M - more than a day.
;; think better