You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.6 KiB
177 lines
4.6 KiB
import type { Equal, Expect } from '@type-challenges/utils'
|
|
|
|
type casesGreaterThan = [
|
|
Expect<Equal<GreaterThan<1, 0>, true>>,
|
|
Expect<Equal<GreaterThan<5, 4>, true>>,
|
|
Expect<Equal<GreaterThan<4, 5>, false>>,
|
|
Expect<Equal<GreaterThan<0, 0>, false>>,
|
|
Expect<Equal<GreaterThan<10, 9>, true>>,
|
|
Expect<Equal<GreaterThan<20, 20>, false>>,
|
|
Expect<Equal<GreaterThan<10, 100>, false>>,
|
|
Expect<Equal<GreaterThan<111, 11>, true>>,
|
|
Expect<Equal<GreaterThan<1234567891011, 1234567891010>, true>>,
|
|
]
|
|
|
|
type casesGreaterDigit = [
|
|
Expect<Equal<GreaterDigit<'0', '1'>, false>>,
|
|
Expect<Equal<GreaterDigit<'1', '1'>, false>>,
|
|
Expect<Equal<GreaterDigit<'2', '1'>, true>>,
|
|
Expect<Equal<GreaterDigit<'7', '1'>, true>>,
|
|
Expect<Equal<GreaterDigit<'5', '3'>, true>>,
|
|
Expect<Equal<GreaterDigit<'9', '6'>, true>>,
|
|
Expect<Equal<GreaterDigit<'4', '8'>, false>>,
|
|
Expect<Equal<GreaterDigit<'6', '6'>, false>>,
|
|
]
|
|
|
|
type casesExclusiveRange = [
|
|
Expect<Equal<ExclusiveRange<0>, []>>,
|
|
Expect<Equal<ExclusiveRange<1>, [0]>>,
|
|
Expect<Equal<ExclusiveRange<10>, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>,
|
|
Expect<Equal<ExclusiveRange<5>, [0, 1, 2, 3, 4]>>,
|
|
]
|
|
|
|
type casesExcludeDigitsUntil = [
|
|
Expect<Equal<ExcludeDigitsUntil<3>, '3' | '4' | '5' | '6' | '7' | '8' | '9'>>,
|
|
Expect<Equal<ExcludeDigitsUntil<8>, '8' | '9'>>,
|
|
Expect<Equal<ExcludeDigitsUntil<10>, never>>,
|
|
]
|
|
|
|
type NaiveGreaterThan<
|
|
T extends number,
|
|
U extends number,
|
|
Acc extends 1[] = []
|
|
> =
|
|
// Check if Acc is same as T
|
|
Acc['length'] extends T
|
|
// Check if T is U
|
|
? Acc['length'] extends U
|
|
// T == U
|
|
? false
|
|
// T < U
|
|
: false
|
|
// Check if Acc is first at U
|
|
: Acc['length'] extends U
|
|
// T > U
|
|
? true
|
|
// Recurse to the next number
|
|
: NaiveGreaterThan<T, U, [1, ...Acc]>
|
|
;
|
|
|
|
// Digits as string union
|
|
type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
|
|
|
|
// Create an exclusive range/tuple up until T
|
|
// Runs in O(N)
|
|
type ExclusiveRange<
|
|
N extends number,
|
|
Range extends number[] = [],
|
|
Acc extends 1[] =[],
|
|
> =
|
|
Range['length'] extends N
|
|
? Range
|
|
: ExclusiveRange<
|
|
N,
|
|
[...Range, Acc['length']],
|
|
[...Acc, 1]
|
|
>
|
|
;
|
|
|
|
// Digit type without the numbers 0 up until but not including U
|
|
type ExcludeDigitsUntil<
|
|
N extends number,
|
|
Digits extends Digit = Digit,
|
|
Range extends number[] = ExclusiveRange<N>,
|
|
> = Digits extends `${Range[number]}` ? never : Digits
|
|
|
|
// Check T is greater than U
|
|
type GreaterDigit<
|
|
T extends Digit,
|
|
U extends Digit,
|
|
> =
|
|
T extends '0'
|
|
? false
|
|
: T extends '1'
|
|
? U extends ExcludeDigitsUntil<1>
|
|
? false
|
|
: true
|
|
: T extends '2'
|
|
? U extends ExcludeDigitsUntil<2>
|
|
? false
|
|
: true
|
|
: T extends '3'
|
|
? U extends ExcludeDigitsUntil<3>
|
|
? false
|
|
: true
|
|
: T extends '4'
|
|
? U extends ExcludeDigitsUntil<4>
|
|
? false
|
|
: true
|
|
: T extends '5'
|
|
? U extends ExcludeDigitsUntil<5>
|
|
? false
|
|
: true
|
|
: T extends '6'
|
|
? U extends ExcludeDigitsUntil<6>
|
|
? false
|
|
: true
|
|
: T extends '7'
|
|
? U extends ExcludeDigitsUntil<7>
|
|
? false
|
|
: true
|
|
: T extends '8'
|
|
? U extends ExcludeDigitsUntil<8>
|
|
? false
|
|
: true
|
|
: T extends '9'
|
|
? U extends ExcludeDigitsUntil<9>
|
|
? false
|
|
: true
|
|
: never
|
|
;
|
|
|
|
// Compare each digit until there is one digit that is greater or smaller
|
|
type GreaterString<
|
|
T extends string,
|
|
U extends string
|
|
> =
|
|
T extends `${infer THead}${infer TTail}`
|
|
? U extends `${infer UHead}${infer UTail}`
|
|
// If both T and U have a Digit in front, compare it
|
|
? GreaterDigit<THead & Digit, UHead & Digit> extends false
|
|
// If not greater, compare the rest of the digits
|
|
? GreaterString<TTail, UTail>
|
|
: true
|
|
: false
|
|
: false
|
|
;
|
|
|
|
type X = GreaterString<'8', '5'>;
|
|
|
|
// Compare the length of both strings,
|
|
// if they have the same length compare each digit
|
|
type GreaterStringLength<
|
|
T extends string,
|
|
U extends string
|
|
> =
|
|
T extends `${Digit}${infer R1}`
|
|
// T has another digit in front
|
|
? U extends `${Digit}${infer R2}`
|
|
// U has another digit in front
|
|
? GreaterStringLength<R1, R2>
|
|
// U ran out of digits
|
|
: true
|
|
// T ran out of digits, either U runs out too or U has more digits,
|
|
// either way GreaterThan returns false
|
|
: false
|
|
;
|
|
|
|
// Runs in O(log(min(N, M)) because it needs to check every digit of the smaller number
|
|
type GreaterThan<
|
|
N extends number,
|
|
M extends number
|
|
> =
|
|
GreaterStringLength<`${N}`, `${M}`> extends true
|
|
? true
|
|
: GreaterString<`${N}`, `${M}`>
|
|
;
|