type TupleOfLength<N extends number, Result extends 0[] = []> = Result["length"] extends N
? Result
: TupleOfLength<N, [...Result, 0]>;
// if L is greater than R, return true, else false
type Greater<L extends number, R extends number> = `${L}` extends `-${infer AbsL extends number}`
? `${R}` extends `-${infer AbsR extends number}`
? TupleOfLength<AbsL> extends [...TupleOfLength<AbsR>, ...unknown[]]
? false
: true
: false
: `${R}` extends `-${number}`
? true
: TupleOfLength<L> extends [...TupleOfLength<R>, unknown, ...unknown[]]
? true
: false;
type ExtractReversePairs<N extends number, T extends number[]> = T extends [
infer First extends number,
...infer Rest extends number[]
]
? Greater<N, First> extends true
? [[N, First], ...ExtractReversePairs<N, Rest>]
: ExtractReversePairs<N, Rest>
: [];
type CountReversePairs<T extends number[], U extends unknown[] = []> = T extends [
infer First extends number,
...infer Rest extends number[]
]
? CountReversePairs<Rest, [...U, ...ExtractReversePairs<First, Rest>]>
: U["length"];
Solution by yukicountry #34535
type CountReversePairs<T extends number[]>
= CountUnion<keyof {[I in keyof T & `${number}` as keyof {[J in AfterI<T, I>
as GreaterThan<T[I], T[J]> extends true ? `${I}>${J}` : never]: J}]: I}>
type AfterI<T, I extends string, J extends string = keyof T & `${number}`>
= J extends J ? GreaterThan<J, I> extends true ? J : never : never
type CountUnion<U> = [U] extends [never] ? 0 : PlusOne<CountUnion<Exclude<U, ExtractOne<U>>>>
type ExtractOne<U> = (U extends U ? (_: Promise<U>) => U : never) extends (_: infer I) => U ? Awaited<I> : never
type PlusOne<N extends string | number, S extends string = `${N}`>
= (S extends `${infer L}9` ? `${PlusOne<L>}0`
: S extends `${infer L}8` ? `${L}9` : S extends `${infer L}7` ? `${L}8` : S extends `${infer L}6` ? `${L}7` : S extends `${infer L}5` ? `${L}6` : S extends `${infer L}4` ? `${L}` : S extends `${infer L}3` ? `${L}4` : S extends `${infer L}2` ? `${L}3` : S extends `${infer L}1` ? `${L}2` : S extends `${infer L}0` ? `${L}1`
: '1') extends `${infer N extends number}` ? N : never
type GreaterThan<X extends string | number, Y extends string | number, Gt = undefined>
= X extends Y ? Gt extends true | false ? Gt : false
: `${X} ${Y}` extends `${infer A}${infer C} ${infer B}${infer D}` ? GreaterThan<C, D, Gt extends true | false ? Gt : A extends B ? Gt : '9876543210' extends `${any}${A}${any}${B}${any}` ? true : false>
: `${Y}` extends '' ? true : false
Solution by teamchong #32983
enum Comparison {
Greater,
Equal,
Lower,
}
type JudgeMap = [
'1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9',
'2' | '3' | '4' | '5' | '6' | '7' | '8' | '9',
'3' | '4' | '5' | '6' | '7' | '8' | '9',
'4' | '5' | '6' | '7' | '8' | '9',
'5' | '6' | '7' | '8' | '9',
'6' | '7' | '8' | '9',
'7' | '8' | '9',
'8' | '9',
'9',
never
];
type JudgeOne<A extends string, B extends string> = B extends A
? Comparison.Equal
: B extends keyof JudgeMap
? A extends JudgeMap[B]
? Comparison.Greater
: Comparison.Lower
: Comparison.Equal;
type GetEmpty<A extends string> = A extends `${infer E}${infer R}`
? `.${GetEmpty<R>}`
: '';
type JudgeTemplate<A extends string, B extends string> = A extends B
? Comparison.Equal
: A extends `${infer L}${B}${infer R}`
? Comparison.Greater
: Comparison.Lower;
type JudgeLength<A extends string, B extends string> = JudgeTemplate<
GetEmpty<A>,
GetEmpty<B>
>;
type JudgeString<A extends string, B extends string> = JudgeLength<
A,
B
> extends Comparison.Equal
? A extends `${infer A1}${infer A2}`
? B extends `${infer B1}${infer B2}`
? JudgeOne<A1, B1> extends Comparison.Equal
? JudgeString<A2, B2>
: JudgeOne<A1, B1>
: Comparison.Equal
: Comparison.Equal
: JudgeLength<A, B>;
type Comparator<
A extends number,
B extends number
> = `${A}` extends `-${infer T1}`
? `${B}` extends `-${infer T2}`
? JudgeString<T2, T1>
: Comparison.Lower
: `${B}` extends `-${infer T2}`
? Comparison.Greater
: JudgeString<`${A}`, `${B}`>;
type FindGreater<T extends number[], N extends number> = T extends [infer L extends number, ...infer R extends number[]] ?
(Comparator<L, N> extends Comparison.Greater ?
[...FindGreater<R, N>, 1] : FindGreater<R, N>)
: []
// type FindGreaterCount<T extends number[], N extends number> = FindGreater<T, N>['length']
type CountReversePairsArray<T extends number[], C extends number[] = [] > = T extends [infer L extends number, ...infer R extends number[]] ? [...CountReversePairsArray<R, [...C, L]>, ...FindGreater<C, L>] : []
type CountReversePairs<T extends number[]> = CountReversePairsArray<T>['length']
First reuse the answer of Integers Comparator, FindGreater can count how many elements
in T is bigger than N, then in CountResversePairsArray just traverse the array and use FindGreater to get the count of each element.
Solution by Royce-DaDaDa #32966
type Pairs<T extends number[]> = T extends [ infer F extends number, ...infer Rest extends number[] ]
? `${string}${F}${string}${Rest[number]}${string}` | Pairs<Rest>
: never
type Filter<T extends string> = T extends unknown
? '9876543210' extends T
? T
: never
: never
// Previous challenge https://github.com/type-challenges/type-challenges/blob/main/questions/00730-hard-union-to-tuple/README.md
type UnionToIntersectionFn<U> = (U extends unknown ? (arg: () => U) => void : never) extends (arg: infer I) => void ? I : never
type GetUnionLast<U> = UnionToIntersectionFn<U> extends () => infer I ? I : never
type UnionToTuple<U, Last = GetUnionLast<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, Last>>, Last]
type CountReversePairs<
T extends number[],
P extends string = Pairs<T>,
F extends string = Filter<P>
> = UnionToTuple<F>['length']
Solution by lvjiaxuan #32945
type AbsReverses<X extends number, Y extends number, A extends 1[] = []> = A['length'] extends X
? 0
: A['length'] extends Y ? 1 : AbsReverses<X, Y, [...A, 1]>;
type Reverses<A extends number, B extends number> = `${A}` extends `-${infer X extends number}`
? `${B}` extends `-${infer Y extends number}` ? AbsReverses<Y, X> : 0
: `${B}` extends `-${number}` ? 1 : AbsReverses<A, B>;
type CountReverseWith<N extends number, A extends number[], R extends 1[] = []> = A extends [infer F extends number, ...infer T extends number[]]
? CountReverseWith<N, T, Reverses<N, F> extends 0 ? R : [...R, 1]>
: R;
type CountReversePairs<A extends number[], R extends 1[] = []> = A extends [infer F extends number, ...infer T extends number[]]
? CountReversePairs<T, [...R, ...CountReverseWith<F, T>]>
: R['length'];
Solution by alexandroppolus #31758
type SimpleGreaterThan<A extends number, B extends number, _StackA extends 1[] = [], _StackB extends 1[] = []> =
`${A}${B}` extends `-${infer NA extends number}-${infer NB extends number}` ?
SimpleGreaterThan<NB, NA> : //Negative
`${A}` extends `-${number}` ? false : //only A Negative
`${B}` extends `-${number}` ? true : //only B Negative
_StackA[`length`] extends A | 999 ? false :
_StackB[`length`] extends B | 999 ? true :
SimpleGreaterThan<A, B, [..._StackA, 1], [..._StackB, 1]>;
type CountReversePairsOnce<T extends number, U extends number[], _Recorder extends 1[] = []> =
U extends [infer F extends number, ...infer R extends number[]] ?
CountReversePairsOnce<T, R, SimpleGreaterThan<T, F> extends true ? [..._Recorder, 1] : _Recorder> :
_Recorder/*return*/;
type CountReversePairs<T extends number[], _Recorder extends 1[] = []> =
T extends [infer F extends number, ...infer R extends number[]] ?
CountReversePairs<R, [..._Recorder, ...CountReversePairsOnce<F, R>]> :
_Recorder[`length`]/*return*/;
Solution by E-uler #31605
type ParseNumber<
S extends string
> =
S extends `${infer I}.${infer D}`?
[I,D]
:[S,'']
// l -> -1 e->0 g->1
type CompareLength<
A extends string,
B extends string,
> =
A extends `${string}${infer AR}`?
B extends `${string}${infer BR}`?
CompareLength<AR,BR>
:1
:
B extends A?
0:-1
type GreatConfig = {
"0": '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8'| '9'
"1": '2' | '3' | '4' | '5' | '6' | '7' | '8'| '9',
'2': '3' | '4' | '5' | '6' | '7' | '8'| '9',
"3": '4' | '5' | '6' | '7' | '8'| '9',
"4": '5' | '6' | '7' | '8'| '9',
"5": '6' | '7' | '8'| '9',
'6': '7' | '8'| '9',
"7": '8'| '9'
"8": '9',
'9': never,
}
type CompareDigit<
A extends string,
B extends string,
> =
A extends B?
0:
A extends keyof GreatConfig?
B extends GreatConfig[A]?
-1:1
:never
type CompareDigits<
A extends string,
B extends string,
> =
A extends `${infer AF}${infer AR}`?
B extends `${infer BF}${infer BR}`?
CompareDigit<AF, BF> extends infer CR?
CR extends 0?
CompareDigits<AR, BR>
:CR
:never
: 1
:
B extends A?
0:-1
type CompareNonNegetive<
T extends string,
U extends string,
TP extends [string,string] = ParseNumber<T>,
UP extends [string,string] = ParseNumber<U>,
ByLength extends (0 | 1 | -1) = CompareLength<TP[0],UP[0]>
> =
ByLength extends 0?
TP[0] extends UP[0]?
CompareDigits<TP[1],UP[1]>
:CompareDigits<TP[0],UP[0]>
:ByLength
type LTE<
A extends number,
B extends number,
> =
`${A}` extends `-${infer ABS_A}`?
`${B}` extends `-${infer ABS_B}`?
CompareNonNegetive<ABS_B,ABS_A> extends 1?false:true
: true
:
`${B}` extends `-${string}`?
false:
CompareNonNegetive<`${A}`,`${B}`> extends 1? false:true
type SplitArray<T extends number[],L extends number[] = [],R extends number[] = []> =
T extends [infer A extends number,...infer M extends number[],infer B extends number]?
SplitArray<M,[...L,A],[B,...R]>
: T['length'] extends 1?
[[...L,T[0]],R]
:[L,R]
type Merge<A extends number[],B extends number[],R extends number[] = [] > =
[A,B] extends [
[infer FA extends number,...infer RA extends number[]],
[infer FB extends number,...infer RB extends number[]]
]?
LTE<FA,FB> extends true?
Merge<RA,B,[...R,FA]>
:Merge<RB,A,[...R,FB]>
: [...R,...A,...B]
type MergeSort<
T extends number[],
H extends [number[],number[]]= SplitArray<T>,
> =
T['length'] extends (0|1)?
[T,[]]:
[MergeSort<H[0]>,MergeSort<H[1]>] extends [
[infer LSorted extends number[],infer LC extends number[] ],
[infer RSorted extends number[],infer RC extends number[] ]
]?
[Merge<LSorted,RSorted>,[...LC,...RC,...CountSorted<LSorted,RSorted>]]:never
type CountSorted<
T extends number[],
U extends number[],
R extends number[] = []
> =
U extends [infer UF extends number,...infer UR extends number[]]?
T extends [infer TF extends number,...infer TR extends number[]]?
LTE<TF,UF> extends false?
CountSorted<T,UR,[...R,...T]>
:CountSorted<TR,U,R>
: R
: R
type CountReversePairs<T extends number[]> = MergeSort<T>[1]['length'];
Solution by jiangshanmeta #31454