Skip to content

Instantly share code, notes, and snippets.

@gtkatakura
Forked from Grubba27/fizzbuzz.ts
Created October 6, 2022 04:21
Show Gist options
  • Select an option

  • Save gtkatakura/90280d96e986c48cf4553aeccabeb94c to your computer and use it in GitHub Desktop.

Select an option

Save gtkatakura/90280d96e986c48cf4553aeccabeb94c to your computer and use it in GitHub Desktop.

Revisions

  1. @Grubba27 Grubba27 revised this gist Apr 20, 2022. No changes.
  2. @Grubba27 Grubba27 created this gist Apr 20, 2022.
    110 changes: 110 additions & 0 deletions fizzbuzz.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,110 @@



    type Reverse<A> =
    `${A}` extends `${infer AH}${infer AT}`
    ? `${Reverse<AT>}${AH}` : A

    type Digs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    type DigsNext<I = Digs, R = {}> =
    I extends [infer Head, infer Next, ...infer Tail]
    ? DigsNext<[Next, ...Tail], R & Record<Head, Next>>
    : { [K in keyof R]: R[K] }
    type DigsPrev = { [K in keyof DigsNext as DigsNext[K]]: K }

    type AddOne<A> =
    A extends `${infer AH}${infer AT}`
    ? AH extends '9' ? `0${AddOne<AT>}` : `${DigsNext[AH]}${AT}`
    : `1`
    type SubOne<A> =
    A extends `${infer AH}${infer AT}`
    ? AH extends '0' ? `9${SubOne<AT>}` : `${DigsPrev[AH]}${AT}`
    : never
    type Add<A, B> =
    A extends `${infer AH}${infer AT}` ?
    B extends `${infer BH}${infer BT}`
    ? BH extends '0' ? `${AH}${Add<AT, BT>}` : Add<AddOne<A>, SubOne<B>>
    : A : B
    type Mul<A, B, R = '0'> =
    A extends '0' ? R :
    B extends '0' ? R :
    A extends `${infer AH}${infer AT}`
    ? AH extends '0' ? Mul<AT, `0${B}`, R> : Mul<SubOne<A>, B, Add<R, B>>
    : R
    type Multiply<A extends string | number | bigint, B extends string | number | bigint> =
    Reverse<Mul<Reverse<A>, Reverse<B>>>


    type Division<
    W extends number,
    D extends number,
    Error extends any = never,
    Q extends string = '0'
    > =
    W extends 0
    ? Q extends never ? Error : Q
    : W extends never ? Error : Division<Subtract<W, D>, D, Error, AddOne<Q>>

    type ConstructTuple<
    L extends number,
    R extends unknown[] = []
    > = R["length"] extends L
    ? R
    : ConstructTuple<L, [...R, unknown]>

    type Subtract<
    M extends number,
    S extends number
    > = ConstructTuple<M> extends [...subtrahend: ConstructTuple<S>, ...rest: infer Rest]
    ? Rest["length"]
    : never
    const div: Division<9, 3> = "3"
    const div: Division<15, 3> = "5"

    type FizzBuzzValidator<
    V extends number
    > =
    Division<V, 3> extends never
    ? never
    : Division<V, 5> extends never
    ? never
    : 'FizzBuzz'

    type BuzzValidator<
    V extends number
    > =
    Division<V, 3> extends never
    ? never
    : 'Buzz'

    type FizzValidator<
    V extends number
    > =
    Division<V, 5> extends never
    ? never
    : 'Fizz'

    type FizzBuzz
    <V extends number> =
    FizzBuzzValidator<V> extends never
    ? FizzValidator<V> extends never
    ? BuzzValidator<V> extends never
    ? V
    :'Buzz'
    :'Fizz'
    :'FizzBuzz'

    const res: FizzBuzz<2> // 2
    const buzz: FizzBuzz<3> // Buzz
    const fizz: FizzBuzz<5> // Fizz
    const fizzBuzz: FizzBuzz<15> // FizzBuzz

    type FizzBuzzArr<
    V extends Array<number>,
    A extends Array<any> = []
    > =
    V extends [infer E, ...infer D]
    ? FizzBuzzArr<D, [...A, ...[FizzBuzz<E>]]>
    : A

    const FIZZBUZZZZ: FizzBuzzArr<[1,2,3,4,5,6,7,8,9, 15]> // [1, 2, "Buzz", 4, "Fizz", "Buzz", 7, 8, "Buzz", "FizzBuzz"]