Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

27133 - Square #33227

Open
DevilTea opened this issue May 14, 2024 · 0 comments
Open

27133 - Square #33227

DevilTea opened this issue May 14, 2024 · 0 comments
Labels
27133 answer Share answers/solutions to a question en in English

Comments

@DevilTea
Copy link

DevilTea commented May 14, 2024

// 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>>
@DevilTea DevilTea added answer Share answers/solutions to a question en in English labels May 14, 2024
@github-actions github-actions bot added the 27133 label May 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
27133 answer Share answers/solutions to a question en in English
Projects
None yet
Development

No branches or pull requests

1 participant