blob: 62adac230ac85866ad0907a9bbf51de1eb619e26 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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))))
|