;;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))))