[Typescript] 141. Extreme - Sum

Implement a type `Sum<A, B>` that summing two non-negative integers and returns the sum as a string. Numbers can be specified as a string, number, or bigint.
 
For example,
type T0 = Sum<2, 3> // '5'
type T1 = Sum<'13', '21'> // '34'
type T2 = Sum<'328', 7> // '335'
type T3 = Sum<1_000_000_000_000n, '123'> // '1000000000123'
 
 
/* _____________ Your Code Here _____________ */

type DigitMap = {
  '0': [],
  '1': [1],
  '2': [1, 1],
  '3': [1, 1, 1],
  '4': [1, 1, 1, 1],
  '5': [1, 1, 1, 1, 1],
  '6': [1, 1, 1, 1, 1, 1],
  '7': [1, 1, 1, 1, 1, 1, 1],
  '8': [1, 1, 1, 1, 1, 1, 1, 1],
  '9': [1, 1, 1, 1, 1, 1, 1, 1, 1],
}
type Zero = [];
type One = [1];
type Carry = Zero | One;
type Ten = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
type Digit = keyof DigitMap;

type MinusTen<S extends 1[]> =
  S extends [...Ten, ...infer R] ? `${R['length']}` & Digit : never;

type DigitSum<
  A extends Digit,
  B extends Digit,
  C extends Carry = Zero,
  S extends 1[] = [...DigitMap[A], ...DigitMap[B], ...C]
> =
  `${S['length']}` extends Digit
    ? [Zero, `${S['length']}`]
    : [One, MinusTen<S>];

type SumStr<
  A extends Digit[],
  B extends Digit[],
  R extends [Carry, Digit]
> =
  R extends [infer C extends Carry, infer N extends Digit]
    ? `${SumArr<A, B, C>}${N}`
    : never

type SumArr<
  A extends Digit[],
  B extends Digit[],
  C extends Carry = Zero
> =
  [A, B] extends [
    [infer DA extends Digit, ...infer RA extends Digit[]],
    [infer DB extends Digit, ...infer RB extends Digit[]]
  ]
    ? SumStr<RA, RB, DigitSum<DA, DB, C>>
    : A extends [infer D extends Digit, ...infer R extends Digit[]]
      ? SumStr<R, Zero, DigitSum<D, '0', C>>
      : B extends Zero
        ? C extends Zero ? '' : '1'
        : SumArr<B, Zero, C>;

type DigitArr<S extends string> = S extends `${infer F}${infer R}` ? [...DigitArr<R>, F] : Zero;

type Sum<
  A extends string | number | bigint,
  B extends string | number | bigint
> = SumArr<DigitArr<`${A}`>, DigitArr<`${B}`>>;


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Sum<2, 3>, '5'>>,
  Expect<Equal<Sum<'13', '21'>, '34'>>,
  Expect<Equal<Sum<'328', 7>, '335'>>,
  Expect<Equal<Sum<1_000_000_000_000n, '123'>, '1000000000123'>>,
  Expect<Equal<Sum<9999, 1>, '10000'>>,
  Expect<Equal<Sum<4325234, '39532'>, '4364766'>>,
  Expect<Equal<Sum<728, 0>, '728'>>,
  Expect<Equal<Sum<'0', 213>, '213'>>,
  Expect<Equal<Sum<0, '0'>, '0'>>,
]

 

posted @ 2022-12-21 22:41  Zhentiw  阅读(17)  评论(0编辑  收藏  举报