Skip to content

Instantly share code, notes, and snippets.

@gigobyte
Created December 14, 2023 12:07
Show Gist options
  • Save gigobyte/775524266192ad4e3c3ef78ba649a83e to your computer and use it in GitHub Desktop.
Save gigobyte/775524266192ad4e3c3ef78ba649a83e to your computer and use it in GitHub Desktop.
Tech night
type input = `Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11`;
type Split<
Str extends string,
Separator extends string,
Result extends string[] = []
> = Str extends `${infer chunk}${Separator}${infer restOfString}`
? Split<restOfString, Separator, [...Result, chunk]>
: [...Result, Str];
type RemovePrefix<
Str extends string,
Prefix extends string
> = Str extends `${Prefix}${infer restOfString}` ? restOfString : Str;
type RemovePrefixes<
Strings extends string[],
Prefix extends string,
Result extends string[] = []
> = Strings extends [infer head extends string, ...infer tail extends string[]]
? RemovePrefixes<tail, Prefix, [...Result, RemovePrefix<head, Prefix>]>
: Result;
type ParseNumber<T extends string> = T extends `${infer n extends number}`
? n
: -1;
type ParseNumbers<
Strings extends string[],
Result extends number[] = []
> = Strings extends [infer head extends string, ...infer tail extends string[]]
? ParseNumbers<tail, [...Result, ParseNumber<head>]>
: Result;
type ParseCard<Str extends string> =
Str extends `${infer winningNumbers} | ${infer pickedNumbers}`
? [
ParseNumbers<Split<winningNumbers, " ">>,
ParseNumbers<Split<pickedNumbers, " ">>
]
: never;
type ParseCards<
Strings extends string[],
Result extends any[] = []
> = Strings extends [infer head extends string, ...infer tail extends string[]]
? ParseCards<tail, [...Result, ParseCard<head>]>
: Result;
type Filter<
Arr extends any[],
Unwanted,
Result extends any[] = []
> = Arr extends [infer head, ...infer tail]
? head extends Unwanted
? Filter<tail, Unwanted, Result>
: Filter<tail, Unwanted, [...Result, head]>
: Result;
type FilterInvalidNumbers<Cards, Result extends any[] = []> = Cards extends [
infer head extends [any[], any[]],
...infer tail
]
? FilterInvalidNumbers<
tail,
[...Result, [Filter<head[0], -1>, Filter<head[1], -1>]]
>
: Result;
type Intersect<
Arr1 extends any[],
Arr2 extends any[],
Result extends any[] = []
> = Arr1 extends [infer fst, ...infer rest]
? fst extends Arr2[number]
? Intersect<rest, Arr2, [...Result, fst]>
: Intersect<rest, Arr2, Result>
: Result;
type GetWinningNumbersCount<
ParsedCards,
Result extends any[] = []
> = ParsedCards extends [infer head extends [any[], any[]], ...infer tail]
? GetWinningNumbersCount<
tail,
[...Result, Intersect<head[0], head[1]>["length"]]
>
: Result;
type ArrayOfNLength<
Length,
Result extends any[] = []
> = Result["length"] extends Length
? Result
: ArrayOfNLength<Length, [...Result, any]>;
type Add<T, U> = [...ArrayOfNLength<T>, ...ArrayOfNLength<U>]["length"];
type Pop<Arr> = Arr extends [infer _, ...infer tail] ? tail : never;
type PopNTimes<
Arr,
Times,
Looper extends any[] = ArrayOfNLength<Times>
> = Looper["length"] extends 0 ? Arr : PopNTimes<Pop<Arr>, Times, Pop<Looper>>;
type Subtract<T, U> = PopNTimes<
ArrayOfNLength<T>,
U
> extends infer result extends any[]
? result["length"]
: never;
type Multiply<T, U> = U extends 1 ? T : Add<T, Multiply<T, Subtract<U, 1>>>;
type Pow<T, U> = U extends 0
? 1
: U extends 1
? T
: Multiply<T, Pow<T, Subtract<U, 1>>>;
type CalculateScore<T extends number> = T extends 0
? 0
: Pow<2, Subtract<T, 1>>;
type GetScores<
Numbers extends any[],
Result extends any[] = []
> = Numbers extends [infer head extends number, ...infer tail]
? GetScores<tail, [...Result, CalculateScore<head>]>
: Result;
type Sum<Arr, Acc extends number = 0> = Arr extends [
infer fst extends number,
...infer rest
]
? Sum<
rest,
Add<fst, Acc> extends infer result extends number ? result : never
>
: Acc;
type result = Sum<
GetScores<
GetWinningNumbersCount<
FilterInvalidNumbers<
ParseCards<RemovePrefixes<Split<input, "\n">, `Card ${string}: `>>
>
>
>
>;
const start = performance.now();
const result: result = 13;
const end = performance.now();
console.log(`Result: ${result}, execution time: ${end - start}ms`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment