aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2023/day13/solver.lisp
blob: 53cc753506cb8e19de29a0428c673ba1c60666b2 (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
84
85
86
87
88
89
90
91
92
93
94
;; 6:34
;; 8:11 part 1
;; 9:36 part 2
(ql:quickload '(fiveam arrows cl-ppcre))

(defparameter eg-vert "#...##..#
#....#..#
..##..###
#####.##.
#####.##.
..##..###
#....#..#")

(defparameter eg-horizontal "#.##..##.
..#.##.#.
##......#
##......#
..#.##.#.
..##..##.
#.#.##.#.")

(defun count-differences (a b)
  (loop for x across a
        for y across (or b "")
        count (not (eq x y))))

(defun v-mirror (rows &optional (max-differences 0))
  (loop
    for idx from 1 below (length rows)
    when
    (= max-differences
       (loop
         for above in (reverse (subseq rows 0 idx))
         for below in (subseq rows idx)
         sum (count-differences above below)))
    do (return idx)))

(defun h-mirror (rows &optional (max-differences 0))
  (v-mirror (transpose-rows rows) max-differences))

(defun transpose-rows (rows)
  (arrows:-<>
   rows
   (mapcar #'string-to-octets <>)
   (apply #'map 'list (lambda (&rest vals)
                        (coerce (mapcar #'code-char vals) 'string)) <>)))

(fiveam:test partials
  (fiveam:is
   (= 4
      (v-mirror
       (cl-ppcre:split "\\n" eg-vert))))
  (fiveam:is
   (= 1
      (v-mirror
       (cl-ppcre:split "\\n" eg-vert) 1)))
  (fiveam:is
   (null (v-mirror
          (cl-ppcre:split "\\n" eg-horizontal))))
  (fiveam:is
   (= 3 (v-mirror
         (cl-ppcre:split "\\n" eg-horizontal) 1)))
  (fiveam:is
   (= 5
      (h-mirror
       (cl-ppcre:split "\\n" eg-horizontal))))
  (fiveam:is
   (null (h-mirror
          (cl-ppcre:split "\\n" eg-horizontal) 1))))

(defun solver (maps &optional (max-differences 0))
  (let ((vertical-mirrors (delete nil (mapcar (lambda (m)
                                                (v-mirror m max-differences))
                                              maps)))
        (horizontal-mirrors (delete nil (mapcar (lambda (m)
                                                  (h-mirror m max-differences))
                                                maps))))
    (+
     (* 100 (apply #'+ vertical-mirrors))
     (apply #'+ horizontal-mirrors))))

(defun parse-input (file)
  (arrows:->>
   (uiop:read-file-string file)
   (cl-ppcre:split "\\n\\n")
   (mapcar (lambda (map) (cl-ppcre:split "\\n" map)))))

(fiveam:test solutions
  (fiveam:is (= 405 (solver (parse-input "eg-in"))))
  (fiveam:is (= 400 (solver (parse-input "eg-in") 1)))
  (fiveam:is (= 35360 (solver (parse-input "input"))))
  (fiveam:is (= 36755 (solver (parse-input "input") 1))))

(fiveam:run!)