|
| 1 | +// Santa is stuck! |
| 2 | +// Santa is craving cookies! But Alas, he's stuck in a dense North Polar forest. |
| 3 | +// Implement Move so Santa ('🎅') can find his way to the end of the maze. |
| 4 | +// As a reward, if Santa escapes the maze, fill it with DELICIOUS_COOKIES ('🍪'). |
| 5 | +// Santa can only move through alleys (' ') and not through the trees ('🎄'). |
| 6 | +// Solving the maze |
| 7 | +// This challenge is going to be a culmination of all the days that came before. |
| 8 | + |
| 9 | +type Alley = " "; |
| 10 | +type Santa = "🎅"; |
| 11 | +type Tree = "🎄"; |
| 12 | +type MazeItem = Tree | Santa | Alley; |
| 13 | +type DELICIOUS_COOKIES = "🍪"; |
| 14 | + |
| 15 | +type Fill< |
| 16 | + Content extends unknown, |
| 17 | + Size extends number, |
| 18 | + Container extends Array<Content> = [], |
| 19 | +> = Container["length"] extends Size ? Container : Fill<Content, Size, [...Container, Content]>; |
| 20 | + |
| 21 | +type MazeRow = Fill<MazeItem, 10>; |
| 22 | +type MazeMatrix = Fill<MazeRow, 10>; |
| 23 | +type Directions = "up" | "down" | "left" | "right"; |
| 24 | + |
| 25 | +// CanSantaMove |
| 26 | +type GenerateNextSantaRow2< |
| 27 | + Maze extends MazeMatrix, |
| 28 | + Row extends number, |
| 29 | + Column extends number, |
| 30 | +> = Maze[Row] extends infer MazeRow extends Array<unknown> |
| 31 | + ? { |
| 32 | + [Key in keyof MazeRow]: StringToNumber<Key> extends Column |
| 33 | + ? MazeRow[Key] extends Tree |
| 34 | + ? Tree |
| 35 | + : Santa |
| 36 | + : MazeRow[Key] extends Santa |
| 37 | + ? Alley |
| 38 | + : MazeRow[Key]; |
| 39 | + } |
| 40 | + : never; |
| 41 | + |
| 42 | +type IsSantaAtTheEdge<Maze extends MazeMatrix> = |
| 43 | + FindCurrentSantaRowIndex<Maze> extends infer CurrentSantaRow extends number |
| 44 | + ? CurrentSantaRow extends 0 |
| 45 | + ? true |
| 46 | + : CurrentSantaRow extends 9 |
| 47 | + ? true |
| 48 | + : FindCurrentSantaColumnIndex< |
| 49 | + Maze[CurrentSantaRow] |
| 50 | + > extends infer CurrentSantaColumn extends number |
| 51 | + ? CurrentSantaColumn extends 0 |
| 52 | + ? true |
| 53 | + : CurrentSantaColumn extends 9 |
| 54 | + ? true |
| 55 | + : false |
| 56 | + : never |
| 57 | + : never; |
| 58 | + |
| 59 | +type CanSantaMove<Maze extends MazeMatrix, Direction extends Directions> = ChangeArrayElement< |
| 60 | + ChangeArrayElement< |
| 61 | + Maze, |
| 62 | + FindCurrentSantaRowIndex<Maze>, |
| 63 | + GenerateCurrentSantaRow<Maze[FindCurrentSantaRowIndex<Maze>]> |
| 64 | + >, |
| 65 | + FindNextSantaRowIndex<Maze, Direction>, |
| 66 | + GenerateNextSantaRow2< |
| 67 | + Maze, |
| 68 | + FindNextSantaRowIndex<Maze, Direction>, |
| 69 | + FindNextSantaColumnIndex< |
| 70 | + FindCurrentSantaColumnIndex<Maze[FindCurrentSantaRowIndex<Maze>]>, |
| 71 | + Direction |
| 72 | + > |
| 73 | + > |
| 74 | +> extends infer NextMaze extends MazeMatrix |
| 75 | + ? FindCurrentSantaRowIndex<NextMaze> extends never |
| 76 | + ? IsSantaAtTheEdge<Maze> extends true |
| 77 | + ? true |
| 78 | + : false |
| 79 | + : true |
| 80 | + : never; |
| 81 | +// CanSantaMove |
| 82 | + |
| 83 | +type ChangeArrayElement<A extends Array<unknown>, I extends keyof A, E extends unknown> = { |
| 84 | + [Key in keyof A]: Key extends `${I extends number ? I : never}` ? E : A[Key]; |
| 85 | +}; |
| 86 | + |
| 87 | +type Includes<A extends Array<unknown>, E extends unknown> = A extends [infer First, ...infer Rest] |
| 88 | + ? First extends E |
| 89 | + ? true |
| 90 | + : Includes<Rest, E> |
| 91 | + : never; |
| 92 | + |
| 93 | +type StringToNumber<S> = S extends `${infer FirstDigit}${infer RestDigits}` |
| 94 | + ? S extends `${infer OnlyDigit}` |
| 95 | + ? OnlyDigit extends infer N |
| 96 | + ? N extends "0" |
| 97 | + ? 0 |
| 98 | + : N extends "1" |
| 99 | + ? 1 |
| 100 | + : N extends "2" |
| 101 | + ? 2 |
| 102 | + : N extends "3" |
| 103 | + ? 3 |
| 104 | + : N extends "4" |
| 105 | + ? 4 |
| 106 | + : N extends "5" |
| 107 | + ? 5 |
| 108 | + : N extends "6" |
| 109 | + ? 6 |
| 110 | + : N extends "7" |
| 111 | + ? 7 |
| 112 | + : N extends "8" |
| 113 | + ? 8 |
| 114 | + : N extends "9" |
| 115 | + ? 9 |
| 116 | + : never |
| 117 | + : never |
| 118 | + : // TODO: doesn't support two digit numbers |
| 119 | + never |
| 120 | + : never; |
| 121 | + |
| 122 | +type FindCurrentSantaRowIndex<Maze extends MazeMatrix> = { |
| 123 | + [Property in keyof Maze]: Includes<Maze[Property], Santa> extends never |
| 124 | + ? never |
| 125 | + : StringToNumber<Property>; |
| 126 | +}[number]; |
| 127 | + |
| 128 | +type Increment<N extends number> = [ |
| 129 | + ...Fill<"", N, []>, |
| 130 | + "", |
| 131 | +]["length"] extends infer IncrementedNumber extends number |
| 132 | + ? IncrementedNumber |
| 133 | + : never; |
| 134 | +type Decrement<N extends number> = Fill<"", N, []> extends [infer First, ...infer Rest] |
| 135 | + ? Rest["length"] |
| 136 | + : never; |
| 137 | + |
| 138 | +type FindNextSantaRowIndex< |
| 139 | + Maze extends MazeMatrix, |
| 140 | + Direction extends Directions, |
| 141 | +> = FindCurrentSantaRowIndex<Maze> extends infer CurrentSantaRow extends number |
| 142 | + ? Direction extends "up" |
| 143 | + ? Decrement<CurrentSantaRow> |
| 144 | + : Direction extends "down" |
| 145 | + ? Increment<CurrentSantaRow> |
| 146 | + : CurrentSantaRow |
| 147 | + : never; |
| 148 | + |
| 149 | +type FindCurrentSantaColumnIndex<Row extends MazeRow> = { |
| 150 | + [Index in keyof Row]: Row[Index] extends Santa ? StringToNumber<Index> : never; |
| 151 | +}[number]; |
| 152 | + |
| 153 | +type FindNextSantaColumnIndex< |
| 154 | + CurrentSantaColumnIndex extends number, |
| 155 | + Direction extends Directions, |
| 156 | +> = Direction extends "left" |
| 157 | + ? Decrement<CurrentSantaColumnIndex> |
| 158 | + : Direction extends "right" |
| 159 | + ? Increment<CurrentSantaColumnIndex> |
| 160 | + : CurrentSantaColumnIndex; |
| 161 | + |
| 162 | +type GenerateCurrentSantaRow<Row extends MazeRow> = { |
| 163 | + [Property in keyof Row]: Row[Property] extends Santa ? Alley : Row[Property]; |
| 164 | +}; |
| 165 | + |
| 166 | +type GenerateNextSantaRow< |
| 167 | + Maze extends MazeMatrix, |
| 168 | + Row extends number, |
| 169 | + Column extends number, |
| 170 | +> = Maze[Row] extends infer MazeRow extends Array<unknown> |
| 171 | + ? { |
| 172 | + [Key in keyof MazeRow]: StringToNumber<Key> extends Column |
| 173 | + ? Santa |
| 174 | + : MazeRow[Key] extends Santa |
| 175 | + ? Alley |
| 176 | + : MazeRow[Key]; |
| 177 | + } |
| 178 | + : never; |
| 179 | + |
| 180 | +type MazeFilledWithCookies = Fill<Fill<DELICIOUS_COOKIES, 10>, 10>; |
| 181 | + |
| 182 | +type Move<Maze extends MazeMatrix, Direction extends Directions> = CanSantaMove< |
| 183 | + Maze, |
| 184 | + Direction |
| 185 | +> extends true |
| 186 | + ? ChangeArrayElement< |
| 187 | + ChangeArrayElement< |
| 188 | + Maze, |
| 189 | + FindCurrentSantaRowIndex<Maze>, |
| 190 | + GenerateCurrentSantaRow<Maze[FindCurrentSantaRowIndex<Maze>]> |
| 191 | + >, |
| 192 | + FindNextSantaRowIndex<Maze, Direction>, |
| 193 | + GenerateNextSantaRow< |
| 194 | + Maze, |
| 195 | + FindNextSantaRowIndex<Maze, Direction>, |
| 196 | + FindNextSantaColumnIndex< |
| 197 | + FindCurrentSantaColumnIndex<Maze[FindCurrentSantaRowIndex<Maze>]>, |
| 198 | + Direction |
| 199 | + > |
| 200 | + > |
| 201 | + > extends infer NextMaze extends MazeMatrix |
| 202 | + ? FindCurrentSantaRowIndex<NextMaze> extends never |
| 203 | + ? MazeFilledWithCookies |
| 204 | + : NextMaze |
| 205 | + : never |
| 206 | + : Maze; |
0 commit comments