aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2023/day14/solver2.lisp
blob: 08fb4509e1d923553d9308f5dfaf7ce64d44c718 (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
;; 13:45
(ql:quickload '(fiveam arrows str))

(defun roll-to-west (line)
  (arrows:->>
   (str:split "#" line)
   (mapcar (lambda (ranges) (sort ranges #'char>)))
   (str:join "#")))

(defun transpose-rows (rows)
  (apply #'map 'list (lambda (&rest vals)
                       (concatenate 'string vals)) rows))

(defun north-load (field)
  (loop
    for row in field
    for weight from (length field) downto 0
    sum (* weight (count #\O row))))

(defun solve1 (input)
  (arrows:->>
   input
   (transpose-rows)
   (mapcar #'roll-to-west)
   (transpose-rows)
   (north-load)))

(defun cycle (field)
  (loop repeat 4
        do (arrows:->>
            field
            (transpose-rows)
            (mapcar #'roll-to-west)
            (mapcar #'nreverse)
            (setf field)))
  field)

(defun value-hash (hash-table value)
  (maphash (lambda (k v)
             (when (equal v value)
               (return-from value-hash k)))
           hash-table))

(defun solve2 (input max-cycles)
  (let ((seen (make-hash-table :test #'equal))
        first-in-series)
    (loop repeat max-cycles
          for i from 0
          for field = input then (cycle field)
          for strf = (str:join #\Newline field)
          until (gethash strf seen)
          do (setf (gethash strf seen) i)
          finally (setf first-in-series strf))
    (let* ((last (hash-table-count seen))
           (first (gethash first-in-series seen))
           (sp (+ first (rem (- max-cycles first) (- last first))))
           (ss (value-hash seen sp)))

      ;; (list last first seen
      ;;       (rem (- max-cycles first) (- last first))
      ;;       ss
      ;;       sp)
      (north-load (str:split #\Newline ss)))))

(fiveam:test solutions
  (fiveam:is (= 136 (solve1 (uiop:read-file-lines "eg-in"))))
  (fiveam:is (= 108935 (solve1 (uiop:read-file-lines "input"))))
  (fiveam:is (= 64 (solve2 (uiop:read-file-lines "eg-in") 1000000000)))
  (fiveam:is (= 100876(solve2 (uiop:read-file-lines "input") 1000000000))))

(time
 (fiveam:run!))