-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path24.ts
executable file
Β·208 lines (189 loc) Β· 5.67 KB
/
24.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// TS playground link: https://tsplay.dev/advent-of-typescript-2023-24
// Santa is stuck!
// Santa is craving cookies! But Alas, he's stuck in a dense North Polar forest.
// Implement Move so Santa ('π
') can find his way to the end of the maze.
// As a reward, if Santa escapes the maze, fill it with DELICIOUS_COOKIES ('πͺ').
// Santa can only move through alleys (' ') and not through the trees ('π').
// Solving the maze
// This challenge is going to be a culmination of all the days that came before.
type Alley = " ";
type Santa = "π
";
type Tree = "π";
type MazeItem = Tree | Santa | Alley;
type DELICIOUS_COOKIES = "πͺ";
type Fill<
Content extends unknown,
Size extends number,
Container extends Array<Content> = [],
> = Container["length"] extends Size ? Container : Fill<Content, Size, [...Container, Content]>;
type MazeRow = Fill<MazeItem, 10>;
type MazeMatrix = Fill<MazeRow, 10>;
type Directions = "up" | "down" | "left" | "right";
// CanSantaMove
type GenerateNextSantaRow2<
Maze extends MazeMatrix,
Row extends number,
Column extends number,
> = Maze[Row] extends infer MazeRow extends Array<unknown>
? {
[Key in keyof MazeRow]: StringToNumber<Key> extends Column
? MazeRow[Key] extends Tree
? Tree
: Santa
: MazeRow[Key] extends Santa
? Alley
: MazeRow[Key];
}
: never;
type IsSantaAtTheEdge<Maze extends MazeMatrix> =
FindCurrentSantaRowIndex<Maze> extends infer CurrentSantaRow extends number
? CurrentSantaRow extends 0
? true
: CurrentSantaRow extends 9
? true
: FindCurrentSantaColumnIndex<
Maze[CurrentSantaRow]
> extends infer CurrentSantaColumn extends number
? CurrentSantaColumn extends 0
? true
: CurrentSantaColumn extends 9
? true
: false
: never
: never;
type CanSantaMove<Maze extends MazeMatrix, Direction extends Directions> = ChangeArrayElement<
ChangeArrayElement<
Maze,
FindCurrentSantaRowIndex<Maze>,
GenerateCurrentSantaRow<Maze[FindCurrentSantaRowIndex<Maze>]>
>,
FindNextSantaRowIndex<Maze, Direction>,
GenerateNextSantaRow2<
Maze,
FindNextSantaRowIndex<Maze, Direction>,
FindNextSantaColumnIndex<
FindCurrentSantaColumnIndex<Maze[FindCurrentSantaRowIndex<Maze>]>,
Direction
>
>
> extends infer NextMaze extends MazeMatrix
? FindCurrentSantaRowIndex<NextMaze> extends never
? IsSantaAtTheEdge<Maze> extends true
? true
: false
: true
: never;
// CanSantaMove
type ChangeArrayElement<A extends Array<unknown>, I extends keyof A, E extends unknown> = {
[Key in keyof A]: Key extends `${I extends number ? I : never}` ? E : A[Key];
};
type Includes<A extends Array<unknown>, E extends unknown> = A extends [infer First, ...infer Rest]
? First extends E
? true
: Includes<Rest, E>
: never;
type StringToNumber<S> = S extends `${infer FirstDigit}${infer RestDigits}`
? S extends `${infer OnlyDigit}`
? OnlyDigit extends infer N
? N extends "0"
? 0
: N extends "1"
? 1
: N extends "2"
? 2
: N extends "3"
? 3
: N extends "4"
? 4
: N extends "5"
? 5
: N extends "6"
? 6
: N extends "7"
? 7
: N extends "8"
? 8
: N extends "9"
? 9
: never
: never
: // TODO: doesn't support two digit numbers
never
: never;
type FindCurrentSantaRowIndex<Maze extends MazeMatrix> = {
[Property in keyof Maze]: Includes<Maze[Property], Santa> extends never
? never
: StringToNumber<Property>;
}[number];
type Increment<N extends number> = [
...Fill<"", N, []>,
"",
]["length"] extends infer IncrementedNumber extends number
? IncrementedNumber
: never;
type Decrement<N extends number> = Fill<"", N, []> extends [infer First, ...infer Rest]
? Rest["length"]
: never;
type FindNextSantaRowIndex<
Maze extends MazeMatrix,
Direction extends Directions,
> = FindCurrentSantaRowIndex<Maze> extends infer CurrentSantaRow extends number
? Direction extends "up"
? Decrement<CurrentSantaRow>
: Direction extends "down"
? Increment<CurrentSantaRow>
: CurrentSantaRow
: never;
type FindCurrentSantaColumnIndex<Row extends MazeRow> = {
[Index in keyof Row]: Row[Index] extends Santa ? StringToNumber<Index> : never;
}[number];
type FindNextSantaColumnIndex<
CurrentSantaColumnIndex extends number,
Direction extends Directions,
> = Direction extends "left"
? Decrement<CurrentSantaColumnIndex>
: Direction extends "right"
? Increment<CurrentSantaColumnIndex>
: CurrentSantaColumnIndex;
type GenerateCurrentSantaRow<Row extends MazeRow> = {
[Property in keyof Row]: Row[Property] extends Santa ? Alley : Row[Property];
};
type GenerateNextSantaRow<
Maze extends MazeMatrix,
Row extends number,
Column extends number,
> = Maze[Row] extends infer MazeRow extends Array<unknown>
? {
[Key in keyof MazeRow]: StringToNumber<Key> extends Column
? Santa
: MazeRow[Key] extends Santa
? Alley
: MazeRow[Key];
}
: never;
type MazeFilledWithCookies = Fill<Fill<DELICIOUS_COOKIES, 10>, 10>;
type Move<Maze extends MazeMatrix, Direction extends Directions> = CanSantaMove<
Maze,
Direction
> extends true
? ChangeArrayElement<
ChangeArrayElement<
Maze,
FindCurrentSantaRowIndex<Maze>,
GenerateCurrentSantaRow<Maze[FindCurrentSantaRowIndex<Maze>]>
>,
FindNextSantaRowIndex<Maze, Direction>,
GenerateNextSantaRow<
Maze,
FindNextSantaRowIndex<Maze, Direction>,
FindNextSantaColumnIndex<
FindCurrentSantaColumnIndex<Maze[FindCurrentSantaRowIndex<Maze>]>,
Direction
>
>
> extends infer NextMaze extends MazeMatrix
? FindCurrentSantaRowIndex<NextMaze> extends never
? MazeFilledWithCookies
: NextMaze
: never
: Maze;