type Diff<
N extends number,
O extends 1[],
R extends 1[] = []
> = N extends O['length'] ? R['length'] : Diff<N, [1, ...O], [1, ...R]>;
// M => minuend, S => subtrahend
type Subtract<
M extends number,
S extends number,
O extends 1[] = [],
> = M extends O['length']
? S extends O['length'] ? 0 : never
: S extends O['length'] ? Diff<M, O> : Subtract<M, S, [1, ...O]>;
Solution by alexandroppolus #35324
// type BuildTuple<L extends number, T extends unknown[] = []> =
T['length'] extends L ? T : BuildTuple<L, [...T, unknown]>;
type Subtract<M extends number, S extends number> =
BuildTuple<M> extends [...BuildTuple<S>, ...infer R]
? R['length']
: never;
Solution by Swastik777YT #34917
// M => minuend, S => subtrahend
type _Generator<T, R extends any[] = []> = R["length"] extends T
? R
: _Generator<T, [...R, unknown]>;
type Pop<T extends any[]> = T extends [...infer Next, infer _] ? Next : [];
type Subtract<
T,
S,
_T extends any[] = _Generator<T>,
_S extends any[] = _Generator<S>,
> = _S["length"] extends 0
? _T["length"]
: [Pop<_T>["length"]] extends [0]
? [Pop<_S>["length"]] extends [0]
? Pop<_T>["length"]
: never
: Subtract<T, S, Pop<_T>, Pop<_S>>;
Solution by ickynavigator #33904
type ParseInt<T> = T extends `${infer R extends number}` ? R : T
type RemoveZero<T> = T extends '0'
? T
: T extends `${infer F}${infer R}` ? F extends '0' ? RemoveZero<R> : T : T
type Reverse<T> = T extends `${infer F}${infer R}`
? `${Reverse<R>}${F}`
: ''
type NextNumber = { '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9' }
type PlusOne<T extends string> = T extends `${infer F}${infer R}`
? F extends '9'
? `0${PlusOne<R>}`
: `${NextNumber[F & keyof NextNumber]}${R}`
: '1'
type ReversedSubtract<
M extends string,
S extends string,
> = `${M}` extends `${infer F1}${infer R1}`
? `${S}` extends `${infer F2}${infer R2}`
? F1 extends F2
? `0${ReversedSubtract<R1, R2>}`
: F2 extends '0'
? `${F1}${ReversedSubtract<R1, R2>}`
: ReversedSubtract<PlusOne<M>, PlusOne<S>>
: ''
: `${S}` extends `${infer _}${infer _}` ? never : M
// M => minuend, S => subtrahend
type Subtract<
M extends number,
S extends number,
> = ParseInt<RemoveZero<Reverse<ReversedSubtract<Reverse<`${M}`>, Reverse<`${S}`>>>>>
Solution by Heonys #32510
type Subtract<
Minuend extends number,
Subtrahend extends number,
C extends 0[] = [],
D extends 0[] = []
> = C["length"] extends Minuend
? D["length"] extends 0
? Minuend extends Subtrahend
? 0
: never
: D["length"]
: C["length"] extends Subtrahend
? Subtract<Minuend, Subtrahend, [0, ...C], [0, ...D]>
: D["length"] extends 0
? Subtract<Minuend, Subtrahend, [0, ...C], D>
: Subtract<Minuend, Subtrahend, [0, ...C], [0, ...D]>;
Solution by vangie #32340
type NTuple<N extends number, Arr extends any[] = []> = Arr extends {
length: N;
}
? Arr
: NTuple<N, [...Arr, any]>;
type Substract<N1 extends number, N2 extends number> = NTuple<N1> extends [
...infer R,
...NTuple<N2>
]
? R["length"]
: never;
Solution by slemchik03 #27660
type MakeCounter<N extends number, _Result extends 1[] = []> = _Result[`length`] extends N ? _Result : MakeCounter<N, [..._Result, 1]>;
type Pop<T extends any[]> = T extends [...infer R, any] ? R : [];
type SimpleCounterMinu<C1 extends any[], C2 extends any[]> = C1 extends [] ?
(C2 extends [] ? 0 : never) : //0-0 or Negative
(C2 extends [] ? C1[`length`] /*return*/ : SimpleCounterMinu<Pop<C1>, Pop<C2>>);
type Subtract<M extends number, S extends number> = SimpleCounterMinu<MakeCounter<M>, MakeCounter<S>>;
Solution by E-uler #25875
type NumberToArray<T extends number, Result extends 0[] = []> = Result['length'] extends T
? Result
: NumberToArray<T, [...Result, 0]>
type Subtract<
T extends number,
U extends number,
TCounter extends 0[] = [],
UCounter extends 0[] = []
> = TCounter['length'] extends T
? TCounter extends [...UCounter, ...infer AfterSubtract]
? AfterSubtract['length']
: never
: Subtract<T, U, NumberToArray<T>, NumberToArray<U>>
Solution by NeylonR #24995
type Subtract<T extends number,U extends number,N extends 0[] = [],V extends 0[] = []> =
T extends N['length']
? T extends U
? 0
: V['length'] extends 0
? never
: N extends [...V, ...infer L]
? L['length']
: 0
: U extends N['length']
? Subtract<T, U, [...N, 0], N>
: Subtract<T, U, [...N, 0], V>
Solution by TKBnice #24554
type BuildTuple<T extends number, _TP extends unknown[] = []> =
_TP['length'] extends T
? _TP
: BuildTuple<T, [..._TP, unknown]>
// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> =
BuildTuple<M> extends [...BuildTuple<S>, ...infer Rest]
? Rest['length']
: never
Finally! Last challenge completed!
I don't know why this is marked as extreme, it's so simple...
Solution by zhaoyao91 #23451
type NTuple<N extends number, C extends unknown[]=[]>=C['length'] extends N ? C : NTuple<N, [...C, 0]>;
type Subtract<M extends number, S extends number> = NTuple<M> extends [...NTuple<S> , ...infer Rest] ? Rest['length'] : never;
Solution by Karamuto #22360
// M => minuend, S => subtrahend
type CreateTuple<
N extends number,
Tuple extends 1[] = []
> = Tuple["length"] extends N ? Tuple : CreateTuple<N, [...Tuple, 1]>;
type Subtract<M extends number, S extends number> = CreateTuple<M> extends [
...CreateTuple<S>,
...infer Rest
]
? Rest["length"]
: never;
Solution by wubetter #21037
// Create array of N length
type NArray<N extends number, A extends any[]= []> = A['length'] extends N ? A : NArray<N, [...A, never]>;
type Reduce<M extends any[], S extends any[]> =
S extends [infer S1, ...infer SR]
? M extends [infer M1, ...infer MR]
? Reduce<MR, SR>
: never
: M['length'];
// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> = Reduce<NArray<M>, NArray<S>>
Solution by mdakram28 #20678
type GreaterThan<T extends number, U extends number, K extends any[] = []> = K['length'] extends T
? false
: K['length'] extends U
? true
: GreaterThan<T, U, [...K, any]>;
type NumToArr<Num extends number, Res extends any[] = []> = Res['length'] extends Num ? Res : NumToArr<Num, [1, ...Res]>
type Pop<Arr extends any[], P extends number, Count extends any[] = []> = Arr extends [...infer Head, infer Tail]
? Count['length'] extends P
? Arr : Pop<Head, P, [...Count, 1]>
: GreaterThan<P, Count['length']> extends true ? never : []
type Subtract<M extends number, S extends number, Arr1 extends any[] = NumToArr<M>> = Pop<Arr1, S>['length']
Solution by Zhukov87 #19994
type TenTimesArray<T extends unknown[]> = [
...T,
...T,
...T,
...T,
...T,
...T,
...T,
...T,
...T,
...T
]
type ArrayWithinTen<
T extends string | number,
R extends unknown[] = []
> = `${R['length']}` extends `${T}` ? R : ArrayWithinTen<T, [unknown, ...R]>
type ArrayWithLength<
T extends string | number,
R extends unknown[] = []
> = `${T}` extends `${infer A}${infer B}`
? ArrayWithLength<B, [...TenTimesArray<R>, ...ArrayWithinTen<A>]>
: R
type Subtract<
M extends number,
S extends number
> = `${M}` extends `${number}${number}${number}${number}`
? never
: ArrayWithLength<M> extends [...ArrayWithLength<S>, ...infer R]
? R['length']
: never
Solution by theoolee #19897
// your answers
type Digits =
{
'0':[],
'1':[0],
'2':[0,0],
'3':[0,0,0],
'4':[0,0,0,0],
'5':[0,0,0,0,0],
'6':[0,0,0,0,0,0],
'7':[0,0,0,0,0,0,0],
'8':[0,0,0,0,0,0,0,0],
'9':[0,0,0,0,0,0,0,0,0],
} ;
type _10=[0,0,0,0,0,0,0,0,0,0] ;
type ReverseString<
Str> =
Str extends `${infer R extends string}${infer U extends string}`
? `${ReverseString<U>}${R}`
: '' ;
type Multiply<
A extends readonly any[],
B extends readonly any[]> =
A extends readonly [infer R,...infer U extends readonly any[]]
? [...B,...Multiply<U,B>]
: [] ;
type ReversedStringToTuple<
Str extends string> =
Str extends `${infer R extends keyof Digits}${infer U extends string}`
? [...Digits[R],...Multiply<_10,ReversedStringToTuple<U>>]
: [] ;
type Subtract<
M extends number,
S extends number> =
ReversedStringToTuple<ReverseString<`${M}`>> extends
readonly [...ReversedStringToTuple<ReverseString<`${S}`>>,...infer U extends readonly any[]]
? U['length']
: never ;
Solution by justBadProgrammer #17148
// your answers
type NumberToTuple<T extends number, Result extends 0[] = []> = Result['length'] extends T
? Result
: NumberToTuple<T, [0, ...Result]>
type MinusOne<T extends number, Result extends 0[] = NumberToTuple<T>> = Result extends [infer F, ...infer R]
? R['length']
: 0
type GT<A extends number, B extends number> = A extends B
? false
: A extends 0
? false
: B extends 0
? true
: GT<MinusOne<A>, MinusOne<B>>
type PlusOne<T extends number, Result extends 0[] = NumberToTuple<T>> = [...Result, 0]['length'] & number
type Minus<M extends number, N extends number, Result extends number = 0> = M extends N
? Result
: Minus<M, PlusOne<N>, PlusOne<Result>>
// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> = GT<S, M> extends true
? never
: Minus<M, S>
Solution by humandetail #16699
/*
Return if a number is smaller than another number
Input: 2,1
Output: true
*/
type IsSmallerThan<T extends number, U extends number, US extends number[] = []> =
US['length'] extends T
? US['length'] extends U
? true
: false
:US['length'] extends U
? true
: IsSmallerThan<T, U, [...US, 1]>
/*
Fills an array with ones until the length of the array is the same as the provided number
Input: 5
Output: [1,1,1,1,1]
*/
type FillArray<T extends number, Acc extends 1[] =[]> = Acc['length'] extends T ? Acc : FillArray<T, [...Acc,1]>
/*
Idea (3, 1): Fill an array to the length of the lower number (1 => [1]), then add an temporary array and fill it until the length of the combined arrays [1] and temp[] is [1,1,1] (3)
Solution 1:
Let Typescript do the work by infering via a Rest parameter, and if the condition is meet, return the length of the infered Array
*/
type Subtract<M extends number, S extends number> = FillArray<M> extends [...FillArray<S>, ...infer Rest] ? Rest['length'] : never
/*
Solution 2:
Use an accumulator that stores the current diff between T and U. Fill that accumulator until the union of accumulator and the filled array of the smaller number sums up to the higher number
*/
type Subtract<M extends number, S extends number, MA extends number[]= FillArray<M>, SA extends number[] = FillArray<S>, Temp extends number[] =[]> = IsSmallerThan<M,S> extends false ? never:[...SA, ...Temp]['length'] extends M ? Temp['length'] : Subtract<M,S, MA,SA, [...Temp,1]>
Solution by JohannesSchwegler #16386
// your answers
type Subtract<M extends number, S extends number, P extends unknown[] = [], R extends unknown[] = []> = P['length'] extends S
? (
[...P, ...R]['length'] extends M ? R['length'] : Subtract<M, S, P, [...R, 1]>
)
: (
P['length'] extends M ? never : Subtract<M, S, [...P, 1], R>
)
Solution by fengchunqi #14953
// your answers
type Rang<T extends Number = 0, P extends 1[] = []> =
P['length'] extends T ?
P : Rang<T, [1, ...P]>
type Shift<T extends 1[]> = T extends [infer F, ...infer Rest] ? Rest : []
type Subtract<M extends number, S extends number, L extends 1[] = Rang<M>, R extends 1[] = Rang<S>> =
L['length'] extends 0
? R['length'] extends 0
? 0
: never
: R['length'] extends 0
? L['length']
: Subtract<M, S, Shift<L>, Shift<R>>
Solution by Sliect #14578
type Subtract<M extends number, S extends number> = M extends -1
? never
: S extends 0
? M
: Subtract<MinusOne<M>, MinusOne<S>>;
type MinusOne<T extends number> = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9][T];
Solution by fardolieri #14186
type Number<T extends number> = _while<T, []>
type _while<T extends number, L extends NumberLike> =
Equal<L["length"], T> extends true
? L
: _while<T, [...L, 0]>
type Numbering<T extends NumberLike> = T["length"]
type NumberLike = Array<any>
type Minus<T extends NumberLike, K extends NumberLike> =
T extends [...K, ...infer I] ? I : never
type Subtract<M extends number, S extends number> = Numbering<Minus<Number<M>, Number<S>>>
Solution by DrLee-lihr #11989
// M => minuend, S => subtrahend
type Subtract<M extends string | number | bigint, S extends string | number | bigint>
= `${M},${S}` extends `-${infer M},-${infer S}`
? Difference<S, M>
: `${M},${S}` extends `${infer M},-${infer S}`
? Sum<M, S>
: `${M},${S}` extends `-${infer M},${infer S}`
? ToNum<`-${Sum<M, S>}`>
: Difference<M, S>
type Difference<A extends number | string | bigint, B extends number | string | bigint, C extends string = `${A}`, D extends string = `${B}`, Carry extends 1[] = [], O extends string = ''>
= [ExtractLast<C>, ExtractLast<D>] extends [[`${infer E}`, [...infer I]], [`${infer F}`, [...infer J]]]
? I extends [...J, ...Carry, ...infer Rest]
? Difference<A, B, E, F, [], `${Rest['length']}${O}`>
: Difference<A, B, E, F, [1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...I] extends [...J, ...Carry, ...infer Rest] ? `${Rest['length']}${O}` : never>
: D extends ''
? Carry extends [1]
? Difference<A, B, C, '1', [], O>
: ToNum<Cut<`${C}${O}`>>
: ToNum<`-${Difference<B, A>}`>
type Cut<S extends string, C extends string = '0'> = S extends C ? C : S extends `${C}${infer R}` ? Cut<R, C> : S;
type ToNum<S extends string> = S extends `${infer N extends number}` ? N : never;
type Sum<A extends number | string | bigint, B extends number | string | bigint, Carry extends 1[] = [], O extends string = ''>
= [ExtractLast<A>, ExtractLast<B>] extends [[`${infer C}`, [...infer I]], [`${infer D}`, [...infer J]]]
? [...I, ...J, ...Carry] extends [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...infer Rest]
? Sum<C, D, [1], `${Rest['length']}${O}`>
: Sum<C, D, [], `${[...I, ...J, ...Carry]['length']}${O}`>
: Carry extends [1]
? Sum<`${A}${B}`, 1, [], O>
: ToNum<`${A}${B}${O}`>
type ExtractLast<N extends number | string | bigint, D extends 1[][] = [[], [1], [1, 1], [1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1]]>
= `${N}` extends `${any}${keyof D & `${number}`}`
? {[I in keyof D]: `${N}` extends `${infer L}${I}` ? [L, D[I]] : never}[number]
: []
Solution by teamchong #11577
Can display actual numbers instead of number
type Tuple<T, Res extends 1[] = []> = 0 extends 1 ? never : Res['length'] extends T ? Res : Tuple<T, [...Res, 1]>;
type Subtract<M extends number, S extends number> = Tuple<M> extends [...Tuple<S>, ...infer Rest] ? Rest['length'] : never
Solution by ProsperBao #11216
type CreateArr<T extends number , Res extends any[] = []> = Res['length'] extends T ? Res: CreateArr<T,[...Res,unknown]>
type Subtract<M extends number, S extends number> = CreateArr<M> extends [...start:CreateArr<S>,...end: infer Res] ? Res['length'] : never
Solution by EGyoung #10243
type Length<T extends any[]> = T['length']
type ToArray<T extends number, R extends any[] = []> = Length<R> extends T ? R : ToArray<T, [...R, any]>
type Subtract<M extends number, S extends number> = ToArray<M> extends [...ToArray<S>, ...infer Rest] ? Length<Rest> : never
Solution by xuemanchi #9157
type GetLenTuple<L extends number, R extends any[]=[]> = R['length'] extends L ? R:GetLenTuple<L, [...R,any]>;
type N1 = [any];
type N2 = [any, any];
type N3 = [any, any, any];
type N4 = [any, any, any, any];
type N5 = [any, any, any, any, any];
type N6 = [any, any, any, any, any, any];
type N7 = [any, any, any, any, any, any, any];
type N8 = [any, any, any, any, any, any, any, any];
type N9 = [any, any, any, any, any, any, any, any, any];
type N10 = [...N9, any];
type DigitToTuple<N, L = N extends string | number ? `${N}` : ''> = L extends `${N1['length']}` ? N1
: L extends `2`? N2
: L extends `3`? N3
: L extends `4`? N4
: L extends `5`? N5
: L extends `6`? N6
: L extends `7`? N7
: L extends `8`? N8
: L extends `9`? N9
: [];
type ToTuple<T extends bigint | string | number, S = `${T}`> = S extends `${infer F}${infer O}` ? [F, ...ToTuple<O>] : [];
type TupleTail<T extends any[]> = T extends [...infer F, any] ? F : never;
type TupleLast<T extends any[]> = T extends [...any, infer L] ? L : never;
type Comparator<L extends any[], R extends any[]> = L extends [...R, ...infer O] ? O['length'] extends 0 ? 0 : 1 : -1;
type LowSub<M extends any[], S extends any[]> =
M extends [...S, ...infer N] ? [N['length'], []]
: [...N10, ...M] extends [...S, ...infer N] ? [N['length'],[any]]
: never;
type OrderSub<M extends any[], S extends any[], R extends any[] = [], P extends any[] = [], ML extends any[] =DigitToTuple<TupleLast<M>>, SL extends any [] = [...DigitToTuple<TupleLast<S>>, ...P] > =
M extends [] ? ( P extends [] ? R:never)
: S extends []? R
: LowSub<ML, SL> extends [infer R1, infer N] ? OrderSub<TupleTail<M>, TupleTail<S>, [R1,...R], (N extends any[]?N:[])>
:never;
type TupleRepeat<T extends any[], N extends any, L extends any[] = [any], NS = N extends string | number ? `${N}` : ''> = NS extends '0'
? [] : `${L['length']}` extends NS
? T : [...T, ...TupleRepeat<T, N, [...L, any]>];
type Result<T extends any[], B extends any[] = [any], R extends any[]=[]> = T extends [...infer F, infer L] ? Result<F, TupleRepeat<B, 10>, [...R, ...TupleRepeat<B, L>]> : R['length'];
// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number, Mu extends any[] = ToTuple<M>, Su extends any[] = ToTuple<S>> =
Comparator<GetLenTuple<Mu['length']>, GetLenTuple<Su['length']>> extends -1 ? never
:Result<OrderSub<Mu, Su>>;
Solution by venusliang #8044
// your answers
type NumberToTupleBase<T extends string, R extends any[] = []> = `${T}` extends `${number}`
? `${T}` extends `${R['length']}`
? R
: NumberToTupleBase<T, [...R, unknown]>
: []
type Expand10<T extends any[]> = [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T]
type ConstructTuple<S extends number | string, Res extends any[] = []> = `${S}` extends `${infer L}${infer R}`
? ConstructTuple<R, [...Expand10<Res>, ...NumberToTupleBase<L>]>
: Res
type Subtract<M extends number, S extends number> = ConstructTuple<M> extends [...ConstructTuple<S>, ...infer R] ? R['length'] : never
Solution by ch3cknull #7963
type ConstructTuple<L extends number, R extends unknown[] = []> = R["length"] extends L ? R : ConstructTuple<L, [...R, unknown]>
// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> = ConstructTuple<M> extends [...subtrahend: ConstructTuple<S>, ...rest: infer Rest] ? Rest["length"] : never
Solution by LoTwT #7680
θ½ηΆδ½ζ―γγγζθ§
// @ts-expect-error
Expect<Equal<ExtremeSubtract<1000, 999>, 1>>
δΈεΊθ―₯ζ―ζζζ₯ιε§γγγ
// your answers
type EqualOrGreaterThan<F extends number, S extends number, CountArr extends Array<unknown> = []> =
F extends S
? true
: CountArr['length'] extends F
? false
: CountArr['length'] extends S
? true
: EqualOrGreaterThan<F, S, [...CountArr, unknown]>
type BuildTuple<N extends number, CountArr extends Array<unknown> = []> =
CountArr['length'] extends N ? CountArr : BuildTuple<N, [...CountArr, unknown]>
type SubtractHelper<M extends number, S extends number> =
BuildTuple<M> extends [...infer Rest, ...BuildTuple<S>] ? Rest['length'] : 0
// M => minuend, S => subtrahend
type ExtremeSubtract < M extends number, S extends number > =
EqualOrGreaterThan < M, S > extends true
? SubtractHelper<M, S>
: never
Solution by HongxuanG #7669