type MapAdd = [
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9]],
[[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [1, 0]],
[[0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [1, 0], [1, 1]],
[[0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [1, 0], [1, 1], [1, 2]],
[[0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [1, 0], [1, 1], [1, 2], [1, 3]],
[[0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [1, 0], [1, 1], [1, 2], [1, 3], [1, 4]],
[[0, 6], [0, 7], [0, 8], [0, 9], [1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5]],
[[0, 7], [0, 8], [0, 9], [1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6]],
[[0, 8], [0, 9], [1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7]],
[[0, 9], [1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7], [1, 8]]
];
type MapMultiply = [
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]],
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9]],
[[0, 0], [0, 2], [0, 4], [0, 6], [0, 8], [1, 0], [1, 2], [1, 4], [1, 6], [1, 8]],
[[0, 0], [0, 3], [0, 6], [0, 9], [1, 2], [1, 5], [1, 8], [2, 1], [2, 4], [2, 7]],
[[0, 0], [0, 4], [0, 8], [1, 2], [1, 6], [2, 0], [2, 4], [2, 8], [3, 2], [3, 6]],
[[0, 0], [0, 5], [1, 0], [1, 5], [2, 0], [2, 5], [3, 0], [3, 5], [4, 0], [4, 5]],
[[0, 0], [0, 6], [1, 2], [1, 8], [2, 4], [3, 0], [3, 6], [4, 2], [4, 8], [5, 4]],
[[0, 0], [0, 7], [1, 4], [2, 1], [2, 8], [3, 5], [4, 2], [4, 9], [5, 6], [6, 3]],
[[0, 0], [0, 8], [1, 6], [2, 4], [3, 2], [4, 0], [4, 8], [5, 6], [6, 2], [7, 2]],
[[0, 0], [0, 9], [1, 8], [2, 7], [3, 6], [4, 5], [5, 4], [6, 4], [7, 3], [8, 1]]
];
type Add<M extends number[], N extends number[]> = M extends [
...infer MRest extends number[],
infer MLast extends number
]
? N extends [...infer NRest extends number[], infer NLast extends number]
? MapAdd[MLast][NLast] extends [infer TensPlace1 extends number, infer OnesPlace1]
? [...Add<MRest, [TensPlace1]>, OnesPlace1] extends [
...infer Rest2 extends number[],
infer OnesPlace2
]
? [...Add<Rest2, NRest>, OnesPlace2]
: never
: never
: M
: N;
type Multiply<M extends number[], N extends number, CarryUp extends number[] = [0]> = M extends [
...infer MRest extends number[],
infer MLast extends number
]
? MapMultiply[MLast][N] extends infer I extends number[]
? Add<I, CarryUp> extends [...infer Rest1 extends number[], infer OnesPlace1]
? [...Multiply<MRest, N, Rest1>, OnesPlace1]
: never
: never
: [...CarryUp];
type Join<M extends number[]> = M extends [
infer First extends number,
...infer Rest extends number[]
]
? `${First}${Join<Rest>}`
: "";
type Format<M extends number[]> = M extends [0, ...infer Rest extends number[]]
? Format<Rest>
: M extends []
? Join<[0]>
: Join<M>;
type SquareTuple<
M extends number[],
N extends number[] = M,
Result extends number[] = [],
Place extends number[] = []
> = N extends [...infer Rest1 extends number[], infer OnesPlace1 extends number]
? SquareTuple<M, Rest1, Add<Result, [...Multiply<M, OnesPlace1>, ...Place]>, [...Place, 0]>
: Result;
type ToNumber<S extends string> = S extends `${infer M extends number}` ? M : never;
type ToTuple<N extends string> = `${N}` extends `${infer A}${infer B}`
? [ToNumber<A>, ...ToTuple<B>]
: [];
type Square<N extends number> = `${N}` extends `-${infer A extends number}`
? Square<A>
: ToNumber<Format<SquareTuple<ToTuple<`${N}`>>>>;
Solution by yukicountry #34467
type MapNumberToArr<T extends number, U extends 1[] = []> = U['length'] extends T ? U : MapNumberToArr<T, [...U, 1]>
type Abs<T extends number> = `${T}` extends `-${infer N extends number}` ? N : T
type Square<T extends number, N extends number = Abs<T>, U extends number[] = MapNumberToArr<N>, Base extends number[] = U, C extends 1[] = [1]> =
T extends 0 ? 0 : (C['length'] extends N ? U['length'] : Square<T, N, [...U, ...Base], Base, [...C, 1]>)
Solution by ouzexi #34152
can not pass: Expect<Equal<Square<100>, 10000>>, Expect<Equal<Square<-50>, 2500>>, because Type instantiation is excessively deep and possibly infinite... need to enhance ...
type AppendEveryLine<Ret extends any[][]> = {
[P in keyof Ret]: [...Ret[0], 1];
};
type ExpandMatrix<T extends any[][]> = T['length'] extends 0
? [[1]]
: AppendEveryLine<[...T, T[0]]>;
type FlattenOnce<T extends any[][] = []> = T extends [
infer First extends any[],
...infer Rest extends any[][]
]
? [...First, ...FlattenOnce<Rest>]
: [];
type Square<
_N extends number,
N extends number = `${_N}` extends `-${infer N extends number}` ? N : _N,
Ret extends any[] = [],
Temp extends any[][] = []
> = N extends Temp['length']
? FlattenOnce<Temp>['length']
: Square<N, N, [...Ret, 1], ExpandMatrix<Temp>>;
Solution by sunupupup #33482
type SquareAbs<N, C extends 1[] = [], R extends 1[] = []> = C['length'] extends N
? R['length']
: SquareAbs<N, [...C, 1], [...R, ...C, ...C, 1]>;
type Square<N extends number> = N extends -100 | 100
? 10000
: SquareAbs<`${N}` extends `-${infer V extends number}` ? V : N>;
Solution by alexandroppolus #33238
// your answers
// Utils
type As<Input, T> = Input extends T ? Input : never
type MakeTuple<T, Length extends number, Result extends T[] = []> = Result['length'] extends Length
? Result
: MakeTuple<T, Length, [...Result, T]>
type Shifted<T extends any[]> = T extends [any, ...infer Rest extends any[]] ? Rest : T
type Popped<T extends any[]> = T extends [...infer Rest extends any[], any] ? Rest : T
type PadLeft<SplittedNum extends number[], Padding1 extends number, Padding2 extends number> = [...MakeTuple<0, Padding1>, ...MakeTuple<0, Padding2>, ...SplittedNum]
// Input
// Split digits and reverse (ex: 123 -> [3, 2, 1])
type ToSplittedNum<S extends string | number, Result extends number[] = []> = `${S}` extends infer N extends string
? N extends `${infer C extends number}${infer Rest}`
? ToSplittedNum<Rest, [C, ...Result]>
: Result extends number[]
? Result
: never
: never
// Calc
// 9x9 Multiplication Table
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
type MultiplyTwoDigits<D1 extends Digit, D2 extends Digit, Loop extends 0[] = [], Result extends 0[] = []> = Loop['length'] extends D2
? ToSplittedNum<Result['length']>
: MultiplyTwoDigits<D1, D2, [...Loop, 0], As<[...Result, ...MakeTuple<0, D1>], 0[]>>
type DigitMultiplicationTableKey = `${Digit}x${Digit}`
type DigitMultiplicationTable = {
[K in DigitMultiplicationTableKey]: K extends `${infer D1 extends Digit}x${infer D2 extends Digit}`
? MultiplyTwoDigits<D1, D2>
: never
}
// Addition
type AddDigits<Digits extends number[], Result extends 0[] = []> = Digits extends [infer D extends number, ...infer Rest extends number[]]
? MakeTuple<0, D> extends infer Temp extends 0[]
? AddDigits<Rest, [...Result, ...Temp]>
: never
: ToSplittedNum<Result['length']>
type AddTwoSplittedNums<
SplittedN1 extends number[],
SplittedN2 extends number[],
Carry extends 0 | 1 = 0,
Result extends number[] = [],
NextSplittedN1 extends number[] = Shifted<SplittedN1>,
NextSplittedN2 extends number[] = Shifted<SplittedN2>,
DigitResult extends number[] = AddDigits<[Carry, SplittedN1[0], SplittedN2[0]]>,
> = [SplittedN1, SplittedN2, Carry] extends [[0], [0], 0]
? Result extends number[]
? Result
: never
: AddTwoSplittedNums<
(NextSplittedN1 extends [] ? [0] : NextSplittedN1),
(NextSplittedN2 extends [] ? [0] : NextSplittedN2),
(DigitResult['length'] extends 1 ? 0 : 1),
[...Result, DigitResult[0]]
>
// Two Levels Loop walk through each digits of two numbers
type Multiply_Advanced_Level1_Loop<
SplittedN1 extends number[],
SplittedN2 extends number[],
Result extends number[] = [0],
P1 extends number = Popped<SplittedN1>['length']
> = SplittedN1 extends [...infer Rest extends number[], infer D1 extends Digit]
? Multiply_Advanced_Level1_Loop<
Rest,
SplittedN2,
AddTwoSplittedNums<Result, Multiply_Advanced_Level2_Loop<SplittedN2, D1, P1>> extends infer Temp extends number[] ? Temp : never
>
: Result
type Multiply_Advanced_Level2_Loop_Calc<
D1 extends number,
P1 extends number,
D2 extends number,
P2 extends number,
> = PadLeft<Multiply_Simple<D1, D2>, P1, P2> extends infer Result extends number[]
? Result
: never
type Multiply_Advanced_Level2_Loop<
SplittedN2 extends number[],
D1 extends number,
P1 extends number,
Result extends number[] = [0],
P2 extends number = Popped<SplittedN2>['length']
> = SplittedN2 extends [...infer Rest extends number[], infer D2 extends number]
? Multiply_Advanced_Level2_Loop<
Rest,
D1,
P1,
AddTwoSplittedNums<Result, Multiply_Advanced_Level2_Loop_Calc<D1, P1, D2, P2>>
>
: Result
// Output
type ToOutputString<SplittedNum extends number[]> = SplittedNum extends [infer C extends number, ...infer Rest extends number[]]
? `${ToOutputNumber<Rest>}${C}`
: ''
type ToNumber<S extends string> = S extends `${infer N extends number}` ? N : S
type ToOutputNumber<SplittedNum extends number[]> = ToNumber<ToOutputString<SplittedNum>>
// Multiply
// Directly map from 9x9 Multiplication Table
type Multiply_Simple<N1 extends number, N2 extends number> = `${N1}x${N2}` extends infer K extends DigitMultiplicationTableKey
? DigitMultiplicationTable[K]
: never
// Calculate every digit and sum
type Multiply_Advanced<N1 extends number, N2 extends number> = Multiply_Advanced_Level1_Loop<ToSplittedNum<N1>, ToSplittedNum<N2>>
type Multiply<N1 extends number, N2 extends number> = ToOutputNumber<
[ToSplittedNum<N1>['length'], ToSplittedNum<N2>['length']] extends [1, 1]
? Multiply_Simple<N1, N2>
: Multiply_Advanced<N1, N2>
>
type Abs<N extends number> = `${N}` extends `-${infer _N extends number}` ? _N : N
type Square<N extends number> = Multiply<Abs<N>, Abs<N>>
Solution by DevilTea #33227
// Generates array from 0 to N (inclusive)
type GenerateArr<N extends number, Acc extends number[] = []> = Acc['length'] extends N
? Acc
: GenerateArr<N, [...Acc, Acc['length']]>
type FlattenArr<A extends unknown[]> = A extends [infer X extends number[], ...infer R] ? [...X, ...FlattenArr<R>] : A;
type AbsoluteSquare<N extends number, Acc extends unknown[] = []> =
Acc['length'] extends N
? FlattenArr<Acc>['length']
: AbsoluteSquare<N, [...Acc, GenerateArr<N>]>
type Square<N extends number> = `${N}` extends `-${infer NonNegNum extends number}`
? AbsoluteSquare<NonNegNum>
: AbsoluteSquare<N>
Solution by keyurparalkar #32648
type PadList<N extends number, C extends any[] = []> = C["length"] extends N
? C
: PadList<N, [...C, 0]>;
type Absolute<T extends number> = `${T}` extends `-${infer U extends number}`
? U
: T;
type Square<
N extends number,
C extends any[] = [],
D extends any[] = [],
T extends number = Absolute<N>
> = T extends 100 ? 10000 : C["length"] extends T
? D["length"]
: Square<N, [...C, 0], [...D, ...PadList<T>]>;
Solution by vangie #32206
type GetArray<T extends number, U extends any[] = []> = U["length"] extends T
? U
: GetArray<T, [...U, 0]>;
type HandleNumber<T extends number> = `${T}` extends `-${infer N extends number}` ? N : T;
type Square<
T extends number,
N extends number = HandleNumber<T>,
U extends number[] = GetArray<N>,
A extends number[] = U,
Count extends number[] = [0]
> = T extends 0
? 0
: Count["length"] extends N
? U["length"]
: Square<T, N, [...U, ...A], A, [...Count, 0]>;
type R = Square<99>;
无法通过100及以上的用例
Solution by moonpoet #31044
type TupleBase = {
"-": [],
"0": [],
"1": [unknown],
"2": [unknown, unknown],
"3": [unknown, unknown, unknown],
"4": [unknown, unknown, unknown, unknown],
"5": [unknown, unknown, unknown, unknown, unknown],
"6": [unknown, unknown, unknown, unknown, unknown, unknown],
"7": [unknown, unknown, unknown, unknown, unknown, unknown, unknown],
"8": [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown],
"9": [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]
}
type NumStrToTuple<T extends string, A extends unknown[] = []> =
T extends `${infer F}${infer R}`
? F extends keyof TupleBase
? [...A, ...NumStrToTuple<R, [...A, ...A, ...A, ...A, ...A, ...A, ...A, ...A, ...A, ...TupleBase[F]]>]
: never
: A
type SquareNumber<
N extends number,
I extends unknown[] = [],
R extends unknown[] = [],
NUM extends number = NumStrToTuple<`${N}`>['length']
> = NUM extends I['length']
? R['length']
: SquareNumber<N, [...I, unknown], [...R, ...NumStrToTuple<`${N}`>], NUM>
type SquareNumberAndZero<N extends number, Z extends string = ''> =
`${N}` extends `${infer N extends number}0`
? SquareNumberAndZero<N, `00${Z}`>
: [SquareNumber<N>, Z];
type Square<N extends number> =
SquareNumberAndZero<N> extends [infer N extends number, infer Z extends string]
? `${N}${Z}` extends `${infer R extends number}` ? R : never
: never
Solution by milletlovemouse #30987
This should work for all the test values without running into any problems.
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type Tuple<Length extends Digit, Result extends unknown[] = []> = Result["length"] extends Length
? Result
: Tuple<Length, [...Result, unknown]>;
type Carry<N> = N extends number
? `${N}` extends `${infer X extends Digit}${infer Y extends Digit}`
? [X, Y]
: `${N}` extends `${infer X extends Digit}`
? [0, X]
: never
: never;
type AddDigits<N extends Digit, M extends Digit, C extends Digit = 0> = Carry<[...Tuple<N>, ...Tuple<M>, ...Tuple<C>]["length"]>;
type SplitNumber<N extends number | string> = `${N}` extends `${infer X extends Digit}${infer Y}`
? [X, ...SplitNumber<Y>]
: `${N}` extends `${infer X extends Digit}`
? [X]
: [];
type ParseInt<N extends string> = N extends `${infer X extends number}` ? X : never;
type JoinNumberHelper<N> = N extends [infer X extends Digit, ...infer XS extends Digit[]]
? `${X}${JoinNumberHelper<XS>}`
: "";
type JoinNumber<N extends Digit[]> = ParseInt<JoinNumberHelper<N>>;
type PadList<L extends unknown[], N extends number, P = 0, I extends unknown[] = []> = I["length"] extends N
? L
: L[I["length"]] extends undefined
? PadList<[P, ...L], N, P, [unknown, ...I]>
: PadList<L, N, P, [unknown, ...I]>;
type DePadList<L extends unknown[], P = 0> = L extends [P, ...infer XS]
? DePadList<XS, P>
: L;
type AddListsHelper<
A extends number[],
B extends number[],
C extends Digit = 0,
L = PadList<A, B["length"]>,
R = PadList<B, A["length"]>
> = L extends [...infer XS extends number[], infer X extends Digit]
? R extends [...infer YS extends number[], infer Y extends Digit]
? AddDigits<X, Y, C> extends [infer ThisCarry extends Digit, infer ThisDigit extends Digit]
? [...AddListsHelper<XS, YS, ThisCarry>, ThisDigit]
: []
: []
: [];
type AddLists<A extends number[], B extends number[]> = DePadList<AddListsHelper<[0, ...A], [0, ...B]>>;
type AddListXTimes<A extends number[], X extends number, O extends number[] = A, I extends unknown[] = [unknown]> = X extends 0
? [0]
: I["length"] extends X
? A
: AddListXTimes<AddLists<A, O>, X, O, [...I, unknown]>;
type Multiply<N extends number, M extends number> = JoinNumber<AddListXTimes<SplitNumber<N>, M>>;
type Abs<N extends number> = `${N}` extends `-${infer X extends number}` ? X : N;
type Square<N extends number, M extends number = Abs<N>> = Multiply<M, M>;
Solution by oathompsonjones #30300
type Reverse<A extends string | number | bigint, _Result extends string = ''> =
`${ A }` extends `${ infer AH }${ infer AT }`
? Reverse<AT, `${ AH }${ _Result }`>
: _Result
type DigsNext = { '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9' }
type AddOne<A extends string | number> = `${ A }` extends `${ infer AH }${ infer AT }`
? AH extends '9'
? `0${ AddOne<AT> }`
: `${ DigsNext[AH & keyof DigsNext] }${ AT }`
: '1'
type Sum<A extends number | string, B extends number, _Counter extends 0[] = []> =
_Counter['length'] extends B
? A
: Sum<AddOne<A>, B, [ ..._Counter, 0]>
type TinySum<A extends number | string, B extends number> = Reverse<Sum<Reverse<A>, B>>
type RemoveMinus<N extends number> = `${ N }` extends `-${ infer I extends number }` ? I : N
type Square<
N extends number,
_PN extends number = RemoveMinus<N>,
_N extends number = RemoveMinus<N>,
_Counter extends 0[] = [0, 0],
SumN extends number = `${ TinySum<_PN, _N> }` extends `${ infer I extends number }` ? I : never,
> = _PN extends 0 | 1
? _PN
: _Counter['length'] extends _N
? SumN
: Square<0, SumN, _N, [ ..._Counter, 0 ]>
Solution by lvjiaxuan #28354
/*
27133 - Square
-------
by null (@aswinsvijay) #medium #tuple #array #math
### Question
Given a number, your type should return its square.
> View on GitHub: https://tsch.js.org/27133
*/
/* _____________ Your Code Here _____________ */
type Square<N extends number>
= `${N}` extends `-${infer I extends number}`
? Multiply<I, I> extends `${infer R extends number}` ? R : never
: Multiply<N, N> extends `${infer R extends number}` ? R : never
type Multiply<A extends string | number | bigint, B extends string | number | bigint, R extends string = `0`>
= `${A}` extends '0' ? '0'
: `${B}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? Multiply<`${A}0`, L0, R> : L1 extends `${any}` ? Multiply<`${A}0`, L1, Sum<R, A>> :
L2 extends `${any}` ? Multiply<`${A}0`, L2, Sum<R, X2<A>>> : L3 extends `${any}` ? Multiply<`${A}0`, L3, Sum<R, X3<A>>> :
L4 extends `${any}` ? Multiply<`${A}0`, L4, Sum<R, X4<A>>> : L5 extends `${any}` ? Multiply<`${A}0`, L5, Sum<R, X5<A>>> :
L6 extends `${any}` ? Multiply<`${A}0`, L6, Sum<R, X6<A>>> : L7 extends `${any}` ? Multiply<`${A}0`, L7, Sum<R, X7<A>>> :
L8 extends `${any}` ? Multiply<`${A}0`, L8, Sum<R, X8<A>>> : L9 extends `${any}` ? Multiply<`${A}0`, L9, Sum<R, X9<A>>> : never
: R
type X2<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X2<L0, `0${Suffix}`> : L1 extends `${any}` ? X2<L1, `2${Suffix}`> :
L2 extends `${any}` ? X2<L2, `4${Suffix}`> : L3 extends `${any}` ? X2<L3, `6${Suffix}`> :
L4 extends `${any}` ? X2<L4, `8${Suffix}`> : L5 extends `${any}` ? Sum<X2<L5>, 1, `0${Suffix}`> :
L6 extends `${any}` ? Sum<X2<L6>, 1, `2${Suffix}`> : L7 extends `${any}` ? Sum<X2<L7>, 1, `4${Suffix}`> :
L8 extends `${any}` ? Sum<X2<L8>, 1, `6${Suffix}`> : L9 extends `${any}` ? Sum<X2<L9>, 1, `8${Suffix}`> : never
: Suffix
type X3<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X3<L0, `0${Suffix}`> : L1 extends `${any}` ? X3<L1, `3${Suffix}`> :
L2 extends `${any}` ? X3<L2, `6${Suffix}`> : L3 extends `${any}` ? X3<L3, `9${Suffix}`> :
L4 extends `${any}` ? Sum<X3<L4>, 1, `2${Suffix}`> : L5 extends `${any}` ? Sum<X3<L5>, 1, `5${Suffix}`> :
L6 extends `${any}` ? Sum<X3<L6>, 1, `8${Suffix}`> : L7 extends `${any}` ? Sum<X3<L7>, 2, `1${Suffix}`> :
L8 extends `${any}` ? Sum<X3<L8>, 2, `4${Suffix}`> : L9 extends `${any}` ? Sum<X3<L9>, 2, `7${Suffix}`> : never
: Suffix
type X4<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X4<L0, `0${Suffix}`> : L1 extends `${any}` ? X4<L1, `4${Suffix}`> :
L2 extends `${any}` ? X4<L2, `8${Suffix}`> : L3 extends `${any}` ? Sum<X4<L3>, 1, `2${Suffix}`> :
L4 extends `${any}` ? Sum<X4<L4>, 1, `6${Suffix}`> : L5 extends `${any}` ? Sum<X4<L5>, 2, `0${Suffix}`> :
L6 extends `${any}` ? Sum<X4<L6>, 2, `4${Suffix}`> : L7 extends `${any}` ? Sum<X4<L7>, 2, `8${Suffix}`> :
L8 extends `${any}` ? Sum<X4<L8>, 3, `2${Suffix}`> : L9 extends `${any}` ? Sum<X4<L9>, 3, `6${Suffix}`> : never
: Suffix
type X5<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X5<L0, `0${Suffix}`> : L1 extends `${any}` ? X5<L1, `5${Suffix}`> :
L2 extends `${any}` ? Sum<X5<L2>, 1, `0${Suffix}`> : L3 extends `${any}` ? Sum<X5<L3>, 1, `5${Suffix}`> :
L4 extends `${any}` ? Sum<X5<L4>, 2, `0${Suffix}`> : L5 extends `${any}` ? Sum<X5<L5>, 2, `5${Suffix}`> :
L6 extends `${any}` ? Sum<X5<L6>, 3, `0${Suffix}`> : L7 extends `${any}` ? Sum<X5<L7>, 3, `5${Suffix}`> :
L8 extends `${any}` ? Sum<X5<L8>, 4, `0${Suffix}`> : L9 extends `${any}` ? Sum<X5<L9>, 4, `5${Suffix}`> : never
: Suffix
type X6<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X6<L0, `0${Suffix}`> : L1 extends `${any}` ? X6<L1, `6${Suffix}`> :
L2 extends `${any}` ? Sum<X6<L2>, 1, `2${Suffix}`> : L3 extends `${any}` ? Sum<X6<L3>, 1, `8${Suffix}`> :
L4 extends `${any}` ? Sum<X6<L4>, 2, `4${Suffix}`> : L5 extends `${any}` ? Sum<X6<L5>, 3, `0${Suffix}`> :
L6 extends `${any}` ? Sum<X6<L6>, 3, `6${Suffix}`> : L7 extends `${any}` ? Sum<X6<L7>, 4, `2${Suffix}`> :
L8 extends `${any}` ? Sum<X6<L8>, 4, `8${Suffix}`> : L9 extends `${any}` ? Sum<X6<L9>, 5, `4${Suffix}`> : never
: Suffix
type X7<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X7<L0, `0${Suffix}`> : L1 extends `${any}` ? X7<L1, `7${Suffix}`> :
L2 extends `${any}` ? Sum<X7<L2>, 1, `4${Suffix}`> : L3 extends `${any}` ? Sum<X7<L3>, 2, `1${Suffix}`> :
L4 extends `${any}` ? Sum<X7<L4>, 2, `8${Suffix}`> : L5 extends `${any}` ? Sum<X7<L5>, 3, `5${Suffix}`> :
L6 extends `${any}` ? Sum<X7<L6>, 4, `2${Suffix}`> : L7 extends `${any}` ? Sum<X7<L7>, 4, `9${Suffix}`> :
L8 extends `${any}` ? Sum<X7<L8>, 5, `6${Suffix}`> : L9 extends `${any}` ? Sum<X7<L9>, 6, `3${Suffix}`> : never
: Suffix
type X8<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X8<L0, `0${Suffix}`> : L1 extends `${any}` ? X8<L1, `8${Suffix}`> :
L2 extends `${any}` ? Sum<X8<L2>, 1, `6${Suffix}`> : L3 extends `${any}` ? Sum<X8<L3>, 2, `4${Suffix}`> :
L4 extends `${any}` ? Sum<X8<L4>, 3, `2${Suffix}`> : L5 extends `${any}` ? Sum<X8<L5>, 4, `0${Suffix}`> :
L6 extends `${any}` ? Sum<X8<L6>, 4, `8${Suffix}`> : L7 extends `${any}` ? Sum<X8<L7>, 5, `6${Suffix}`> :
L8 extends `${any}` ? Sum<X8<L8>, 6, `4${Suffix}`> : L9 extends `${any}` ? Sum<X8<L9>, 7, `2${Suffix}`> : never
: Suffix
type X9<A extends string | number | bigint, Suffix extends string = ''>
= `${A}` extends `${infer L0}0` | `${infer L1}1` | `${infer L2}2` | `${infer L3}3` | `${infer L4}4` | `${infer L5}5` | `${infer L6}6` | `${infer L7}7` | `${infer L8}8` | `${infer L9}9`
? L0 extends `${any}` ? X9<L0, `0${Suffix}`> : L1 extends `${any}` ? X9<L1, `9${Suffix}`> :
L2 extends `${any}` ? Sum<X9<L2>, 1, `8${Suffix}`> : L3 extends `${any}` ? Sum<X9<L3>, 2, `7${Suffix}`> :
L4 extends `${any}` ? Sum<X9<L4>, 3, `6${Suffix}`> : L5 extends `${any}` ? Sum<X9<L5>, 4, `5${Suffix}`> :
L6 extends `${any}` ? Sum<X9<L6>, 5, `4${Suffix}`> : L7 extends `${any}` ? Sum<X9<L7>, 6, `3${Suffix}`> :
L8 extends `${any}` ? Sum<X9<L8>, 7, `2${Suffix}`> : L9 extends `${any}` ? Sum<X9<L9>, 8, `1${Suffix}`> : never
: Suffix
type Sum<A extends string | number | bigint, B extends string | number | bigint, Suffix extends string = '', P extends string = `${A}+${B}`>
= P extends
Match<'00', infer C00, infer D00> | Match<'19'|'28'|'37'|'46'|'55', infer C10, infer D10> |
Match<'01', infer C01, infer D01> | Match<'29'|'38'|'47'|'56', infer C11, infer D11> |
Match<'02'|'11', infer C02, infer D02> | Match<'39'|'48'|'57'|'66', infer C12, infer D12> |
Match<'03'|'12', infer C03, infer D03> | Match<'49'|'58'|'67', infer C13, infer D13> |
Match<'04'|'13'|'22', infer C04, infer D04> | Match<'59'|'68'|'77', infer C14, infer D14> |
Match<'05'|'14'|'23', infer C05, infer D05> | Match<'69'|'78', infer C15, infer D15> |
Match<'06'|'15'|'24'|'33', infer C06, infer D06> | Match<'79'|'88', infer C16, infer D16> |
Match<'07'|'16'|'25'|'34', infer C07, infer D07> | Match<'89', infer C17, infer D17> |
Match<'08'|'17'|'26'|'35'|'44', infer C08, infer D08> | Match<'99', infer C18, infer D18> |
Match<'09'|'18'|'27'|'36'|'45', infer C09, infer D09>
? C00 extends `${any}` ? Sum<C00, D00, `0${Suffix}`> : C10 extends `${any}` ? Sum<Sum<C10, D10>, 1, `0${Suffix}`> :
C01 extends `${any}` ? Sum<C01, D01, `1${Suffix}`> : C11 extends `${any}` ? Sum<Sum<C11, D11>, 1, `1${Suffix}`> :
C02 extends `${any}` ? Sum<C02, D02, `2${Suffix}`> : C12 extends `${any}` ? Sum<Sum<C12, D12>, 1, `2${Suffix}`> :
C03 extends `${any}` ? Sum<C03, D03, `3${Suffix}`> : C13 extends `${any}` ? Sum<Sum<C13, D13>, 1, `3${Suffix}`> :
C04 extends `${any}` ? Sum<C04, D04, `4${Suffix}`> : C14 extends `${any}` ? Sum<Sum<C14, D14>, 1, `4${Suffix}`> :
C05 extends `${any}` ? Sum<C05, D05, `5${Suffix}`> : C15 extends `${any}` ? Sum<Sum<C15, D15>, 1, `5${Suffix}`> :
C06 extends `${any}` ? Sum<C06, D06, `6${Suffix}`> : C16 extends `${any}` ? Sum<Sum<C16, D16>, 1, `6${Suffix}`> :
C07 extends `${any}` ? Sum<C07, D07, `7${Suffix}`> : C17 extends `${any}` ? Sum<Sum<C17, D17>, 1, `7${Suffix}`> :
C08 extends `${any}` ? Sum<C08, D08, `8${Suffix}`> : C18 extends `${any}` ? Sum<Sum<C18, D18>, 1, `8${Suffix}`> :
C09 extends `${any}` ? Sum<C09, D09, `9${Suffix}`> : never
: `${A}${B}${Suffix}`
type Match<P extends string, C extends string, D extends string> = P extends `${infer X}${infer Y}` ? `${C}${X}+${D}${Y}` | `${C}${Y}+${D}${X}` : never
Solution by teamchong #27822
type MakeArr<N extends number, Acc extends any[] = []> = Acc["length"] extends N
? Acc
: MakeArr<N, [...Acc, any]>;
type Abs<N extends number> = `${N}` extends `-${infer R extends number}`
? R
: N;
type Trim0<
N extends number,
Acc extends number = 0
> = `${N}` extends `${infer R extends number}0`
? [...MakeArr<Acc>, any] extends any[]
? Trim0<R, [...MakeArr<Acc>, any]["length"]>
: never
: [N, Acc]; // N is the number without trailing 0s and Acc is the number of trailing 0s
// Get "000.." string whose length is S
type MakeDouble0Str<
S extends number,
Acc extends string = "",
T extends any[] = [...MakeArr<S>, ...MakeArr<S>]
> = T extends [any, ...infer T]
? MakeDouble0Str<T["length"], `${Acc}0`, T>
: Acc;
type CalcSquare<
N extends number,
S extends number = N,
Acc extends any[] = []
> = S extends 0
? Acc["length"]
: MakeArr<S> extends [any, ...infer R]
? CalcSquare<N, R["length"], [...Acc, ...MakeArr<N>]>
: never;
type Square<
N extends number,
T extends number = Trim0<Abs<N>>["0"],
S extends number = Trim0<Abs<N>>["1"]
> = S extends 0
? CalcSquare<T>
: `${CalcSquare<T>}${MakeDouble0Str<S>}` extends `${infer S extends number}`
? S
: never;
Solution by HiroNonoyama #27631
type Range<N extends number, C extends any[] = []> = C["length"] extends N
? C
: Range<N, [any, ...C]>
type SquareRange<
N extends number,
C extends any[] = [],
R extends any[] = []
> = C["length"] extends N
? R["length"]
: SquareRange<N, [any, ...C], [...Range<N>, ...R]>
type Abs<T extends number> = `${T}` extends `-${infer N extends number}` ? N : T
type TrimZero<T extends number> = `${T}` extends `${infer N extends number}0`
? TrimZero<N>
: T
type DupZero<
T extends number,
R extends string = ""
> = `${T}` extends `${infer N extends number}0` ? DupZero<N, `${R}00`> : R
type AsNumber<T> = T extends infer X extends number ? X : never
type ToNumber<T> = T extends `${infer X extends number}` ? X : never
type Square<N extends number> = ToNumber<`${AsNumber<SquareRange<TrimZero<Abs<N>>>>}${DupZero<N>}`>
This impl can't solve numbers like Square<101>
.
N has to be (-99 ~ 99) * 10^n
Solution by shuji-koike #27516
type MakeCounter<T extends number, _Result extends 1[] = []> = _Result[`length`] extends T | 999 ? _Result : MakeCounter<T, [..._Result, 1]>;
/**扁平化 */
type FlatCounterCounter<T extends any[][], _Result extends any[] = []> = T extends [infer F extends any[], ...infer R extends any[][]] ?
FlatCounterCounter<R, [..._Result, ...F]> :
_Result;
type SimpleMultiply<T extends number, U extends number, _CounterCounter extends 1[][] = []> = T | U extends 100 ? 10000 : _CounterCounter[`length`] extends U ?
FlatCounterCounter<_CounterCounter>[`length`] :
SimpleMultiply<T, U, [..._CounterCounter, MakeCounter<T>]>;
/**100以内 */
type Square<N extends number> = `${N}` extends `-${infer NN extends number}` ? SimpleMultiply<NN, NN> : SimpleMultiply<N, N>;
//---------------------------------- large number version ----------------------------------
// namespace multiply {
// /**0~9 */
// type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
// /**个位 RRRF ==> F */
// type DigitFirst<T extends string | number | bigint> = T extends string ?
// (Number<T> extends Digit ?
// Number<T> :
// (T extends `${number}${infer R}` ? DigitFirst<R> : never)) :
// DigitFirst<`${T}`>;
// /**个位以上 RRRF ==> RRR */
// type DigitRest<T extends string | number | bigint, _Result extends string = ``> = T extends string ?
// (T extends `${infer F}${infer R extends `${any}${any}`}` ?
// DigitRest<R, `${_Result}${F}`> :
// Number<_Result> extends 0/*去0*/ ? `` : _Result) :
// DigitRest<`${T}`>;
// type MakeCounter<T extends number, _Result extends 1[] = []> = _Result[`length`] extends T ? _Result : MakeCounter<T, [..._Result, 1]>;
// /**个位相加 */
// type DigitAdd<X extends Digit, Y extends Digit> = [...MakeCounter<X>, ...MakeCounter<Y>][`length`] extends (infer N extends number) ? N : 0;
// /**Parse Int */
// type Number<T extends string | number | bigint> = T extends `0${infer R}`/*去0*/ ? Number<R> : T extends `${infer N extends number | bigint}` ? N : 0;
// /**+1(进位) */
// type AddOne<T extends number | string, _DigitAdd extends number = DigitAdd<DigitFirst<T>, 1>> = `${_DigitAdd extends Digit ? DigitRest<T> : /*进位*/AddOne<DigitRest<T>>}${DigitFirst<_DigitAdd>}`;
// /**个位乘 */
// type DigitMultiply<T extends string | number | bigint, U extends Digit, _Counter extends 1[] = [], _Result extends string = `0`> = _Counter[`length`] extends U ? _Result : DigitMultiply<T, U, [..._Counter, 1], Sum<_Result, T>>;
// /**x10^n */
// type TenPow<T extends string | number | bigint, N extends number, _Counter extends 1[] = []> = _Counter[`length`] extends N ? T : `${TenPow<T, N, [..._Counter, 1]>}0`;
// /**加法器(自然数) */
// type Sum<A extends string | number | bigint, B extends string | number | bigint, _Result extends string = ``, _DigitAdd extends number = DigitAdd<DigitFirst<A>, DigitFirst<B>>> =
// `${A}${B}` extends `` ? _Result : //return
// Sum<DigitRest<A>, _DigitAdd extends Digit ? DigitRest<B> : /*进位*/AddOne<DigitRest<B>>, `${DigitFirst<_DigitAdd>}${_Result}`>;
// /**乘法器(自然数) */
// export type Multiply<A extends string | number | bigint, B extends string | number | bigint, _CarryCounter extends 1[] = [], _Result extends string = `0`> = B extends `` ? Number<_Result> : //return
// Multiply<A, DigitRest<B>, [..._CarryCounter, 1], Sum<_Result, TenPow<DigitMultiply<A, DigitFirst<B>>, _CarryCounter[`length`]>>>;
// // 123 * 12345 ==> (123 * 5)
// // ==> + (123 * 40)
// // ==> + (123 * 300)
// // ==> + (123 * 2000)
// // ==> + (123 * 10000)
// }
// /**乘法器处理超大数 */
// type Square<N extends number> = `${N}` extends `-${infer NN extends number}` ? multiply.Multiply<NN, NN> : multiply.Multiply<N, N>;
// type test_large_number = Square<3141592662951413>
//---------------------------------- large number version ----------------------------------
Solution by E-uler #27396
type TupLen<T extends number, U extends number[] = []> = T extends 0 ?
[] :
U['length'] extends T ?
U :
TupLen<T, [T, ...U]>;
type Abs<T extends number> = T extends 0 ?
T :
`${T}` extends `-${infer U extends number}` ?
U :
T;
type NRange<T extends number, U extends any[] = []> = U['length'] extends T ? U : NRange<T, [...U, 0]>
type Flatten<T, U extends any[] = []> = T extends []
? U
: T extends [infer F, ...infer R]
? Flatten<R, [...U, ...Flatten<F>]>
: [...U, T]
type TupleSum<T extends number[]> = Flatten<{ [K in keyof T]: NRange<T[K]> }>['length']
type Square<T extends number> = Abs<T> extends 100 ? 10000 : TupleSum<TupLen<Abs<T>>>;
My implementation only works with numbers between -100 and 100
Solution by jjswifty #27391