aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2023/day18/solver.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'AoC2023/day18/solver.lisp')
-rw-r--r--AoC2023/day18/solver.lisp62
1 files changed, 62 insertions, 0 deletions
diff --git a/AoC2023/day18/solver.lisp b/AoC2023/day18/solver.lisp
new file mode 100644
index 0000000..62adac2
--- /dev/null
+++ b/AoC2023/day18/solver.lisp
@@ -0,0 +1,62 @@
+;;8:16
+;;9:33
+;;10:45
+(ql:quickload '(fiveam arrows cl-ppcre))
+
+(defun move (dir)
+ (ecase dir
+ ((R 0) (list 0 1))
+ ((D 1) (list 1 0))
+ ((L 2) (list 0 -1))
+ ((U 3) (list -1 0))))
+
+(defun parse (filename part)
+ (mapcar (lambda (line)
+ (destructuring-bind (dir len rest)
+ (cl-ppcre:split " " line)
+ (if (eq part 'first)
+ (list (intern dir) (parse-integer len))
+ (list
+ (digit-char-p (aref rest 7))
+ (parse-integer
+ (subseq rest 2 7) :radix 16)))))
+ (uiop:read-file-lines filename)))
+
+(defun polygon-area (points)
+ (destructuring-bind ((fx fy) (lx ly)) (cons (car points) (last points))
+ (arrows:->
+ (loop for ((x y) (nx ny)) on points by #'cdr
+ when nx
+ sum (- (* x ny) (* y nx)))
+ (+ (- (* lx fy) (* ly fx)))
+ (/ 2)
+ (abs))))
+
+(fiveam:test partials
+ (fiveam:is (= 4.5 (polygon-area '((1 1) (3 2) (2 6))))))
+
+(defun solver (filename part &aux (row 0) (col 0) (perimeter 0))
+ (let ((points
+ (loop
+ for (dir len) in (parse filename part)
+ collect
+ (destructuring-bind (dr dc) (move dir)
+ (incf perimeter len)
+ (list
+ (incf row (* dr len))
+ (incf col (* dc len)))))))
+ ;; poligon area is for no width boundary
+ ;; thus add half-perimeter. Think on a square
+ ;; top and left edges contain area, but right & bottom not
+ ;; thus add that part of perimeter as with. Then add 1 because
+ ;; the corner on bottom right
+ (+
+ 1
+ (/ perimeter 2)
+ (polygon-area points))))
+
+(fiveam:test solutions
+ (fiveam:is (= 62 (solver "eg-in" 'first)))
+ (fiveam:is (= 76387 (solver "input" 'first)))
+ (fiveam:is (= 952408144115 (solver "eg-in" 'second)))
+ (fiveam:is (= 250022188522074 (solver "input" 'second))))