Last active
December 24, 2023 12:58
-
-
Save martinkadlec0/f2b49324ebd5b5859f77f5890127b7d1 to your computer and use it in GitHub Desktop.
Advent of Typescript - Day 24 - Santa Maze
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type Alley = " "; | |
| type MazeItem = "π" | "π " | Alley; | |
| type Maze = MazeItem[][] | |
| type DELICIOUS_COOKIES = "πͺ"; | |
| type MazeMatrix = MazeItem[][]; | |
| type Directions = "up" | "down" | "left" | "right"; | |
| type CoordState = 'win' | 'valid' | 'invalid' | |
| type Inc<N extends number> = [ | |
| 1,2,3,4,5,6,7,8,9,10,11, | |
| ...number[] | |
| ][N] | |
| type Dec<N extends number> = [ | |
| -1,0,1,2,3,4,5,6,7,8,9, | |
| ...number[] | |
| ][N] | |
| // Moves santa to new position and replaces last one with Alley (no validation) | |
| type MoveSanta<TMaze extends Maze, RI extends number, CI extends number> = { | |
| [K in keyof TMaze]: TMaze[K] extends infer Row extends MazeItem[] ? { | |
| [J in keyof Row]: Row[J] extends "π " | |
| ? Alley | |
| : [K, J] extends [`${RI}`, `${CI}`] ? `π ` : Row[J] | |
| } : never | |
| } | |
| // Replaces all cells with a specific item (used for winning cookies) | |
| type FillMaze<TMaze extends Maze, Value extends any> = { | |
| [K in keyof TMaze]: TMaze[K] extends infer Row extends MazeItem[] ? { | |
| [J in keyof Row]: Value | |
| } : never | |
| } | |
| // Finds Cell coordinate of Santa | |
| type FindSantaRow<Row extends MazeItem[], Counter extends number[] = []> = | |
| Row extends [infer Cell, ...infer Rest extends MazeItem[]] | |
| ? Cell extends 'π ' | |
| ? Counter['length'] | |
| : FindSantaRow<Rest, [...Counter, 0]> | |
| : 'nope' | |
| // Finds [Row, Cell] coordinates of Santa | |
| type FindSanta<TMaze extends Maze, Counter extends number[] = []> = | |
| TMaze extends [infer Row extends MazeItem[], ...infer Rest extends Maze] | |
| ? FindSantaRow<Row> extends infer CI extends number | |
| ? [Counter['length'], CI] | |
| : FindSanta<Rest, [...Counter, 0]> | |
| : never | |
| // Takes current Santa's coords and modifies them based on Move | |
| type GetNewCoords<RI extends number, CI extends number, Move extends Directions> = | |
| Move extends 'up' | |
| ? [Dec<RI>, CI] | |
| : Move extends 'down' | |
| ? [Inc<RI>, CI] | |
| : Move extends 'left' | |
| ? [RI, Dec<CI>] | |
| : [RI, Inc<CI>] | |
| // Examines new coordinates and determines if they are valid/invalid or if we got out of maze | |
| type ValidateCoords<TMaze extends Maze, RI extends number, CI extends number> = | |
| RI extends -1 | TMaze['length'] | |
| ? 'win' | |
| : CI extends -1 | TMaze[0]['length'] | |
| ? 'win' | |
| : TMaze[RI][CI] extends 'π' | |
| ? 'invalid' | |
| : 'valid' | |
| // Main logic: Find Santa Coords -> New coords -> Validate coords -> Move Santa / Win / Hit tree | |
| type Move<TMaze extends Maze, Move extends Directions> = | |
| FindSanta<TMaze> extends [infer RI extends number, infer CI extends number] | |
| ? GetNewCoords<RI, CI, Move> extends [infer NewRI extends number, infer NewCI extends number] | |
| ? ValidateCoords<TMaze, NewRI, NewCI> extends infer State extends CoordState | |
| ? State extends 'valid' | |
| ? MoveSanta<TMaze, NewRI, NewCI> | |
| : State extends 'win' | |
| ? FillMaze<TMaze, DELICIOUS_COOKIES> | |
| : TMaze | |
| : never | |
| : never | |
| : TMaze | |
| type Test = [ | |
| ["π", "π", "π", "π", "π", "π"], | |
| ["π", " ", " ", " ", "π", "π"], | |
| ["π", " ", " ", " ", "π ", " "], | |
| ["π", "π", "π", "π", " ", "π"], | |
| ] | |
| type Res = Move<Test, 'right'> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment