-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolutionb.ss
185 lines (158 loc) · 5.1 KB
/
solutionb.ss
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
(use-modules (ice-9 hash-table))
(use-modules (ice-9 rdelim))
(define shapes
'(((0 . 0) (1 . 0) (2 . 0) (3 . 0))
( (1 . 2)
(0 . 1) (1 . 1) (2 . 1)
(1 . 0) )
( (2 . 2)
(2 . 1)
(0 . 0) (1 . 0) (2 . 0) )
((0 . 3)
(0 . 2)
(0 . 1)
(0 . 0) )
((0 . 1) (1 . 1)
(0 . 0) (1 . 0) )))
(define convert-direction
(lambda (dir)
(cond
((eqv? dir #\<) -1)
((eqv? dir #\>) +1)
(else (error "Unexpected direction" dir)))))
(define translate
(lambda (rock dx dy)
(map (lambda (p) (cons (+ (car p) dx) (+ (cdr p) dy))) rock)))
(define all
(lambda (l)
(or
(null? l)
(and (car l) (all (cdr l))))))
(define can-place-rock?
(lambda (cave rock)
(and
(all (map (lambda (p) (and (>= (car p) 0) (<= (car p) 6))) rock))
(all (map (lambda (p) (>= (cdr p) 0)) rock))
(all (map (lambda (p) (not (hash-ref cave p))) rock)))))
(define push-rock
(lambda (jet rock)
(translate rock jet 0)))
(define fall-rock
(lambda (rock)
(translate rock 0 -1)))
(define place-rock
(lambda (cave rock)
(if (null? rock)
cave
(begin
(hash-set! cave (car rock) #t)
(place-rock cave (cdr rock))))))
(define drop-rock
(lambda (cave jets rock)
(let*
((pushed-rock (push-rock (car jets) rock))
(next-rock (if (can-place-rock? cave pushed-rock) pushed-rock rock))
(fallen-rock (fall-rock next-rock)))
(if (can-place-rock? cave fallen-rock)
(drop-rock cave (cdr jets) fallen-rock)
(cons (place-rock cave next-rock) (cdr jets))))))
(define find-top
(lambda (cave)
(+ 1 (hash-fold (lambda (k v acc) (max (cdr k) acc)) -1 cave))))
(define spawn-rock
(lambda (cave rock)
(let ((max-y (find-top cave)))
(translate rock 2 (+ 3 max-y)))))
(define step
(lambda (cave jets rocks)
(let*
((spawned-rock (spawn-rock cave (car rocks)))
(dropped-state (drop-rock cave jets spawned-rock)))
(list
(car dropped-state)
(cdr dropped-state)
(cdr rocks)))))
(define profile
(lambda (cave)
(let*
((keys (hash-fold (lambda (k v acc) (cons k acc)) '() cave))
(xs (iota 7 0))
(groups (map (lambda (x) (filter (lambda (p) (= x (car p))) keys)) xs))
(ys (map (lambda (ps) (map cdr ps)) groups))
(non-empty-ys (map (lambda (group) (if (null? group) '(0) group)) ys))
(top-ys (map (lambda (group) (apply max group)) non-empty-ys))
(top (find-top cave)))
(map (lambda (y) (- y top)) top-ys))))
(define states-equal?
(lambda (x y)
(let
((profile0 (profile (car x)))
(profile1 (profile (car y)))
(jets0 (cadr x))
(jets1 (cadr y))
(rocks0 (caddr x))
(rocks1 (caddr y)))
(and (equal? jets0 jets1)
(equal? (car rocks0) (car rocks1))
(equal? profile0 profile1)))))
(define tortoise-hare0
(lambda (f jets rocks)
(letrec
((x0 (make-state jets rocks))
(x1 (make-state jets rocks))
(go (lambda (tortoise hare)
(if (states-equal? tortoise hare) hare
(go (apply f tortoise) (apply f (apply f hare)))))))
(go (apply f x0) (apply f (apply f x1))))))
(define tortoise-hare1
(lambda (f jets rocks h)
(letrec
((x0 (make-state jets rocks))
(go (lambda (mu tortoise hare)
(if (states-equal? tortoise hare)
(cons mu tortoise)
(go (+ 1 mu) (apply f tortoise) (apply f hare))))))
(go 0 x0 h))))
(define tortoise-hare2
(lambda (f t)
(letrec ((go (lambda (lam hare)
(if (states-equal? t hare) lam
(go (+ 1 lam) (apply f hare))))))
(go 1 (apply f t)))))
(define make-state
(lambda (jets rocks)
(list (make-hash-table) jets rocks)))
(define clone-state
(lambda (cave jets rocks)
(list (alist->hash-table (hash-map->list cons cave)) jets rocks)))
(define find-cycle
(lambda (jets rocks)
(let*
((hare (tortoise-hare0 step jets rocks))
(mu-tortoise (tortoise-hare1 step jets rocks hare))
(lam (tortoise-hare2 step (cdr mu-tortoise))))
(cons lam (- (car mu-tortoise) 1)))))
(define simulate
(lambda (n . x0)
(if (= n 0) x0 (apply simulate (- n 1) (apply step x0)))))
(define find-solution
(lambda (jets rocks)
(let*
((n 1000000000000)
(lam-mu (find-cycle jets rocks))
(rem (remainder (- n (cdr lam-mu)) (car lam-mu)))
(quot (quotient (- n (cdr lam-mu)) (car lam-mu)))
(x1 (apply simulate (cdr lam-mu) (make-state jets rocks)))
(x2 (apply simulate (car lam-mu) (apply clone-state x1)))
(x3 (apply simulate rem (apply clone-state x1))))
(+
(* quot (- (find-top (car x2)) (find-top (car x1))))
(find-top (car x3))))))
(let*
((input-line (string->list (read-line)))
(directions (map convert-direction input-line)))
(begin
(set-cdr! (last-pair directions) directions)
(set-cdr! (last-pair shapes) shapes)
(display (find-solution directions shapes))
(newline)))