07561-extreme-subtract

Back

// 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

playground

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

type Subtract<M extends number, S extends number> = TrimZero<Minus<M, S>> extends `${infer N extends number}` ? N : never

type TrimZero<S extends string> = S extends `0${infer R extends `${any}${any}`}` ? TrimZero<R> : S

type Minus<M extends number | string, S extends number | string, Suffix extends string = ''>
  = `${M}-${S}` extends
    Match<'00'|'11'|'22'|'33'|'44'|'55'|'66'|'77'|'88'|'99', infer C00, infer D00> |
    Match<'10'|'21'|'32'|'43'|'54'|'65'|'76'|'87'|'98', infer C01, infer D01> | Match<'09', infer C11, infer D11> |
    Match<'20'|'31'|'42'|'53'|'64'|'75'|'86'|'97', infer C02, infer D02> | Match<'08'|'19', infer C12, infer D12> |
    Match<'30'|'41'|'52'|'63'|'74'|'85'|'96', infer C03, infer D03> | Match<'07'|'18'|'29', infer C13, infer D13> |
    Match<'40'|'51'|'62'|'73'|'84'|'95', infer C04, infer D04> | Match<'06'|'17'|'28'|'39', infer C14, infer D14> |
    Match<'50'|'61'|'72'|'83'|'94', infer C05, infer D05> | Match<'05'|'16'|'27'|'38'|'49', infer C15, infer D15> |
    Match<'60'|'71'|'82'|'93', infer C06, infer D06> | Match<'04'|'15'|'26'|'37'|'48'|'59', infer C16, infer D16> |
    Match<'70'|'81'|'92', infer C07, infer D07> | Match<'03'|'14'|'25'|'36'|'47'|'58'|'69', infer C17, infer D17> |
    Match<'80'|'91', infer C08, infer D08> | Match<'02'|'13'|'24'|'35'|'46'|'57'|'68'|'79', infer C18, infer D18> |
    Match<'90', infer C09, infer D09> | Match<'01'|'12'|'23'|'34'|'45'|'56'|'67'|'78'|'89', infer C19, infer D19>
  ? C00 extends `${any}` ? Minus<C00, D00, `0${Suffix}`> :
    C01 extends `${any}` ? Minus<C01, D01, `1${Suffix}`> : C11 extends `${any}` ? Minus<Minus<C11, D11>, 1, `1${Suffix}`> :
    C02 extends `${any}` ? Minus<C02, D02, `2${Suffix}`> : C12 extends `${any}` ? Minus<Minus<C12, D12>, 1, `2${Suffix}`> :
    C03 extends `${any}` ? Minus<C03, D03, `3${Suffix}`> : C13 extends `${any}` ? Minus<Minus<C13, D13>, 1, `3${Suffix}`> :
    C04 extends `${any}` ? Minus<C04, D04, `4${Suffix}`> : C14 extends `${any}` ? Minus<Minus<C14, D14>, 1, `4${Suffix}`> :
    C05 extends `${any}` ? Minus<C05, D05, `5${Suffix}`> : C15 extends `${any}` ? Minus<Minus<C15, D15>, 1, `5${Suffix}`> :
    C06 extends `${any}` ? Minus<C06, D06, `6${Suffix}`> : C16 extends `${any}` ? Minus<Minus<C16, D16>, 1, `6${Suffix}`> :
    C07 extends `${any}` ? Minus<C07, D07, `7${Suffix}`> : C18 extends `${any}` ? Minus<Minus<C18, D18>, 1, `8${Suffix}`> :
    C08 extends `${any}` ? Minus<C08, D08, `8${Suffix}`> : C19 extends `${any}` ? Minus<Minus<C19, D19>, 1, `9${Suffix}`> :
    C09 extends `${any}` ? Minus<C09, D09, `9${Suffix}`> : never
  : `${S}` extends '' ? `${M}${Suffix}` : never

type Match<P extends string, C extends string, D extends string> = P extends `${infer X}${infer Y}` ? `${C}${X}-${D}${Y}` : never

Playground

Solution by teamchong #11577

Can display actual numbers instead of number

image

How is work

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