aboutsummaryrefslogtreecommitdiff
path: root/14/2.rkt
blob: 26cdda8cb885f3a889d8d85df46b891d4a31dc9a (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
95
96
97
98
99
100
101
102
103
104
105
#lang racket

(require "../lib/utils.rkt")

(define lines
  (call-with-input-file "input"
    (λ (fp) (get-lines fp))))

(define (mat-copy mat)
  (list->vector (map string-copy (vector->list mat))))

(define (flip-mat mat)
  (list->vector (reverse (map string-copy (vector->list mat)))))

(define mat (list->vector lines))

(define (char-at mat x y)
  (string-ref (vector-ref mat y) x))

(define (set-mat! mat x y c)
  (string-set! (vector-ref mat y) x c))

(define (move-stone mat x1 y1 x2 y2)
  (define t (char-at mat x1 y1))
  (set-mat! mat x1 y1 (char-at mat x2 y2))
  (set-mat! mat x2 y2 t))

(define (find-new-pos mat x y)
  (let loop ((new-y y))
    (if (or (= new-y 0)
            (not (char=? #\. (char-at mat x (- new-y 1)))))
        new-y
        (loop (- new-y 1)))))

(define height (vector-length mat))
(define width (string-length (vector-ref mat 0)))

(define (tilt old-mat)
  (define mat (mat-copy old-mat))
  (do ((y 0 (+ y 1)))
      ((>= y height) (void))
    (do ((x 0 (+ x 1)))
        ((>= x width) (void))
      (when (char=? #\O (char-at mat x y))
        (move-stone mat x y x (find-new-pos mat x y)))))
  mat)

(define (count mat)
  (define sum 0)
  (do ((y 0 (+ y 1)))
      ((>= y height) (void))
    (do ((x 0 (+ x 1)))
        ((>= x width) (void))
      (when (char=? #\O (char-at mat x y))
        (set! sum (+ sum (- height y))))))
  sum)

(define (tilt-north mat)
  (tilt mat))

(define (tilt-south mat)
  (flip-mat (tilt (flip-mat mat))))

(define (transpose linesvec)
  (define lines (vector->list linesvec))
  (define width (string-length (vector-ref linesvec 0)))
  (define new-lines (make-vector width))
  (let loop ((i 0))
    (if (>= i width)
      new-lines
      (let ()
        (define char-list (map (λ (l) (string-ref l i)) lines))
        (vector-set! new-lines i (list->string char-list))
        (loop (+ i 1))))))

(define (tilt-west mat)
  (transpose (tilt (transpose mat))))

(define (tilt-east mat)
  (transpose (flip-mat (tilt (flip-mat (transpose mat))))))

(define mat-dict (make-hash))
(define r-mat-dict (make-hash))

(define (tilt-cycle mat)
  (tilt-east (tilt-south (tilt-west (tilt-north mat)))))

;; return (start . end)
(define (find-loop mat)
  (let loop ((i 1) (cur-mat mat))
    (define m (tilt-cycle cur-mat))
    (if (hash-has-key? mat-dict (vector->list m))
      (cons (hash-ref mat-dict (vector->list m)) i)
      (let ()
        (hash-set! mat-dict (vector->list m) i)
        (hash-set! r-mat-dict i (vector->list m))
        (loop (+ 1 i) m)))))

(define tmp (find-loop mat))
(define loop-start (car tmp))
(define loop-len (- (cdr tmp) (car tmp)))
(define reduced-num
  (+ loop-start (modulo (- 1000000000 loop-start) loop-len)))

(count (list->vector (hash-ref r-mat-dict reduced-num)))