-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
186 lines (167 loc) · 6.65 KB
/
index.ts
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
186
type Point = {
x: number,
y: number
}
// to get height of initial world.. (consider other way to calculate it)
type IntersectionFromUnion<U> =
(U extends any ? (k: U) => void : never) extends (k: infer I) => void
? I
: never
type OverloadedFromUnion<U> = IntersectionFromUnion<
U extends any ? (f: U) => void : never
>
type PopUnion<U> = OverloadedFromUnion<U> extends (a: infer A) => void ? A : never
type IsUnion<T> = [T] extends [IntersectionFromUnion<T>] ? false : true
type TupledUnion<T, A extends unknown[] = []> =
IsUnion<T> extends true
? TupledUnion<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
: [T, ...A]
// from outer
type Length<T extends Array<any>> = T['length']
type Equals<T, U> = [ T ] extends [ U ] ? [ U ] extends [ T ] ? true : false : false
type Modify<T, K extends PropertyKey, V> = {
[_K in keyof T]: _K extends K ? V : T[_K]
};
type Prettify<T> = {
[key in keyof T]: T[key]
}
type ReplaceIndex<S extends string, I extends number, R extends string, _C extends Array<never> = []> =
S extends ''
? S
: Equals<Length<_C>, I> extends true
? S extends `${infer Front}${infer Back}`
? `${R}${Back}`
: never
: S extends `${infer Front}${infer Back}`
? `${Front}${ReplaceIndex<Back, I, R, [..._C, never]>}`
: never;
type StringLength<S extends string, I extends Array<never> = []> =
S extends `` ? Length<I> : S extends `${infer F}${infer Rest}` ? StringLength<Rest, [...I, never]> : never
type Tuple<T, N extends number, _A extends Array<T> = []> =
Equals<N, Length<_A>> extends true ? _A : Tuple<T, N, [..._A, T]>
type Nth<T extends string, N extends number, C extends Array<never> = []> =
Equals<Length<C>, N> extends true ? T extends `${infer F}${infer Rest}` ? F : never : T extends `${infer F}${infer Rest}` ? Nth<Rest, N, [...C, never]> : never
type Shifted<T extends Array<any>> = T extends [infer F, ...infer Rest] ? Rest : never
type Pushed<T extends Array<any>, U> = [...T, U]
// ? C : [] should not happen
type ShouldBeArray<T> = T extends [...infer C] ? C : []
type NeverPushed<T extends Array<any>> = ShouldBeArray<[...T, never]>
type IsLessThan2<T extends Array<never> = []> =
T extends [never] ? true : T extends [] ? true : false
type Is2Or3<T extends Array<never> = []> =
T extends [never, never] ? true : T extends [never, never, never] ? true : false
type IsGreaterThanOr3<T extends Array<never> = []> =
T extends [never, never, never, ...infer Rest] ? true : false
type Is3<T extends Array<never> = []> =
T extends [never, never, never] ? true : false
enum CellNextState {
Alive,
Dead
}
// :R should not happen
type AliveNeighbourCount<
Canvas extends Record<number, string>,
Cell extends Point,
CellMeta extends {x: Array<never>, y: Array<never>} = {
x: Tuple<never, Cell["x"]>,
y: Tuple<never, Cell["y"]>
},
R extends Array<never> = [],
Count extends Array<never> = []
> =
Equals<Length<Count>, 8> extends true ? R : AliveNeighbourCount<
Canvas,
Cell,
CellMeta,
Equals<Length<Count>, 0> extends true
? Equals<Nth<Canvas[Cell["y"]], Length<NeverPushed<CellMeta["x"]>>>, "■"> extends true ? [...R, never] : R
: Equals<Length<Count>, 1> extends true
? Equals<Nth<Canvas[Length<Shifted<CellMeta["y"]>>], Cell["x"]>, "■"> extends true ? [...R, never] : R
: Equals<Length<Count>, 2> extends true
? Equals<Nth<Canvas[Cell["y"]], Length<Shifted<CellMeta["x"]>>>, "■"> extends true ? [...R, never] : R
: Equals<Length<Count>, 3> extends true
? Equals<Nth<Canvas[Length<NeverPushed<CellMeta["y"]>>], Cell["x"]>, "■"> extends true ? [...R, never] : R
: Equals<Length<Count>, 4> extends true
? Equals<Nth<Canvas[Length<Shifted<CellMeta["y"]>>], Length<NeverPushed<CellMeta["x"]>>>, "■"> extends true ? [...R, never] : R
: Equals<Length<Count>, 5> extends true
? Equals<Nth<Canvas[Length<Shifted<CellMeta["y"]>>], Length<Shifted<CellMeta["x"]>>>, "■"> extends true ? [...R, never] : R
: Equals<Length<Count>, 6> extends true
? Equals<Nth<Canvas[Length<NeverPushed<CellMeta["y"]>>], Length<Shifted<CellMeta["x"]>>>, "■"> extends true ? [...R, never] : R
: Equals<Length<Count>, 7> extends true
? Equals<Nth<Canvas[Length<NeverPushed<CellMeta["y"]>>], Length<NeverPushed<CellMeta["x"]>>>, "■"> extends true ? [...R, never] : R
: R,
[...Count, never]
>
type CheckCell<
Canvas extends Record<number, string>,
Cell extends Point,
CountTuple extends Array<never> = AliveNeighbourCount<Canvas, Cell>
> =
Equals<Nth<Canvas[Cell["y"]], Cell["x"]>, " "> extends true
? Is3<CountTuple> extends true
? CellNextState.Alive
: CellNextState.Dead
: Is2Or3<CountTuple> extends true
? CellNextState.Alive
: CellNextState.Dead
type UpdateRow<
Canvas extends Record<number, string>,
Y extends number,
Row extends string = Canvas[Y],
L extends number = StringLength<Row>,
Counter extends Array<never> = []
> =
Equals<Length<Counter>, L> extends true
? Row
: UpdateRow<
Canvas,
Y,
ReplaceIndex<
Row, Length<Counter>,
Equals<
CheckCell<Canvas, {x: Length<Counter>, y: Y}>,
CellNextState.Alive
> extends true
? "■"
: " "
>,
L,
[...Counter, never]
>
type Update<
Canvas extends Record<number, string>,
Counter extends Array<never> = [],
R extends Record<number, string> = Canvas
> =
Equals<Length<Counter>, Length<TupledUnion<keyof Canvas>>> extends true
? R
: Update<
Canvas,
[...Counter, never],
Modify<R, Length<Counter>, UpdateRow<Canvas, Length<Counter>>>
>
/**
* Usage: GameOfLife<InitialMap, Tick>
*/
type GameOfLife<
Canvas extends Record<number, string>,
Tick extends number,
Counter extends Array<never> = []
> =
Equals<Length<Counter>, Tick> extends true
? Prettify<Canvas>
: GameOfLife<
//@ts-ignore <- required because typescript server doesn't like too complexed type such as Update<Canvas>
Update<Canvas>,
Tick,
[...Counter, never]
>
type Game = GameOfLife<{
6: " ■ ",
5: " ",
4: " ■ ",
3: " ■■■ ",
2: " ■ ■ ",
1: " ■ ",
0: " ■ ",
}, 1>