summaryrefslogtreecommitdiffstats
path: root/src/05.lisp
blob: 607b2903fcb98b6bc261e77286f2bd26e421d978 (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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
(use-package 'cl-ppcre)
(use-package 'trivia)

(defun 05/parse-input-direct (input)
  (mapcar (lambda (i)
            (map 'list #'parse-integer
                 (multiple-value-bind (a b)
                     (scan-to-strings "(.*),(.*) -> (.*),(.*)" i) b)))
          input))

(defun max-coord (c1 c2)
  (match (list c1 c2)
    ((list (list x1 y1) (list x2 y2))
     (list (max x1 x2) (max y1 y2)))))

(defun find-max (l)
  (fold-left #'max-coord '(0 0)
             (mapcar
              (lambda (x)
                (match x
                  ((list x1 y1 x2 y2)
                   (list (max x1 x2) (max y1 y2))))) l)))

(defun 05/parse-input (input-file)
  (05/parse-input-direct (get-file-lines input-file)))

(defun draw-line-x (arr y x1 x2)
  (let ((nx1 (min x1 x2))
        (nx2 (max x1 x2)))
    (loop :for x :from nx1 :to nx2
          :do (incf (aref arr y x)))))

(defun draw-line-y (arr x y1 y2)
  (let ((ny1 (min y1 y2))
        (ny2 (max y1 y2)))
    (loop :for y :from ny1 :to ny2
          :do (incf (aref arr y x)))))

(defun draw-line-diag (arr x1 y1 x2 y2)
  (if (< x1 x2)
      (if (< y1 y2)
          (loop for y from y1 upto y2
                for x from x1 upto x2
                do (incf (aref arr y x)))
          (loop for y from y1 downto y2
                for x from x1 upto x2
                do (incf (aref arr y x))))
      (if (< y1 y2)
          (loop for y from y1 upto y2
                for x from x1 downto x2
                do (incf (aref arr y x)))
          (loop for y from y1 downto y2
                for x from x1 downto x2
                do (incf (aref arr y x))))))

(defun draw-line (b arr coords)
  (match coords
    ((list x1 y1 x2 y2)
     (if (equalp x1 x2)
         (draw-line-y arr x1 y1 y2)
         (if (equalp y1 y2) (draw-line-x arr y1 x1 x2)
             (when b (draw-line-diag arr x1 y1 x2 y2)))))))

(defun 2d-array-to-list (array)
  (loop for i below (array-dimension array 0)
        collect (loop for j below (array-dimension array 1)
                      collect (aref array i j))))

(defun 05/part-a (parsed-input)
  (let ((lines (make-array (match (mapcar #'1+ (find-max parsed-input)) ((list a b) (list b a)))))
        (overlapping 0))
    (loop for x in parsed-input do (draw-line nil lines x))
    (mapcar (lambda (x) (mapcar (lambda (y) (when (> y 1) (incf overlapping))) x))
            (2d-array-to-list lines))
    overlapping))

(defun 05/part-b (parsed-input)
  (let ((lines (make-array (match (mapcar #'1+ (find-max parsed-input)) ((list a b) (list b a)))))
        (overlapping 0))
    (loop for x in parsed-input do (draw-line t lines x))
    (mapcar (lambda (x) (mapcar (lambda (y) (when (> y 1) (incf overlapping))) x))
            (2d-array-to-list lines))
    overlapping))