Created
January 31, 2019 09:25
-
-
Save minajevs/cd1657462bec5baf57789d9dbf9228bf to your computer and use it in GitHub Desktop.
fizzbuzz types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type StringBool = "true" | "false"; | |
interface AnyNumber { prev?: any, isZero: StringBool }; | |
interface PositiveNumber { prev: any, isZero: "false" }; | |
type IsZero<TNumber extends AnyNumber> = TNumber["isZero"]; | |
type Next<TNumber extends AnyNumber> = { prev: TNumber, isZero: "false" }; | |
type Prev<TNumber extends PositiveNumber> = TNumber["prev"]; | |
type Add<T1 extends AnyNumber, T2> = { "true": T2, "false": Next<Add<Prev<T1>, T2>> }[IsZero<T1>]; | |
// Computes T1 * T2 | |
type Mult<T1 extends AnyNumber, T2 extends AnyNumber> = MultAcc<T1, T2, _0>; | |
type MultAcc<T1 extends AnyNumber, T2, TAcc extends AnyNumber> = | |
{ "true": TAcc, "false": MultAcc<Prev<T1>, T2, Add<TAcc, T2>> }[IsZero<T1>]; | |
// Computes max(T1 - T2, 0). | |
type Subt<T1 extends AnyNumber, T2 extends AnyNumber> = | |
{ "true": T1, "false": Subt<Prev<T1>, Prev<T2>> }[IsZero<T2>]; | |
interface SubtResult<TIsOverflow extends StringBool, TResult extends AnyNumber> { | |
isOverflowing: TIsOverflow; | |
result: TResult; | |
} | |
// Returns a SubtResult that has the result of max(T1 - T2, 0) and indicates whether there was an overflow (T2 > T1). | |
type SafeSubt<T1 extends AnyNumber, T2 extends AnyNumber> = | |
{ | |
"true": SubtResult<"false", T1>, | |
"false": { | |
"true": SubtResult<"true", T1>, | |
"false": SafeSubt<Prev<T1>, Prev<T2>> | |
}[IsZero<T1>] | |
}[IsZero<T2>]; | |
type _0 = { isZero: "true" }; | |
type _1 = Next<_0>; | |
type _2 = Next<_1>; | |
type _3 = Next<_2>; | |
type _4 = Next<_3>; | |
type _5 = Next<_4>; | |
type _6 = Next<_5>; | |
type _7 = Next<_6>; | |
type _8 = Next<_7>; | |
type _9 = Next<_8>; | |
type _10 = Next<_9>; | |
type _11 = Next<_10>; | |
type _12 = Next<_11>; | |
type _13 = Next<_12>; | |
type _14 = Next<_13>; | |
type _15 = Next<_14>; | |
type _16 = Next<_15>; | |
type _17 = Next<_16>; | |
type _18 = Next<_17>; | |
type _19 = Next<_18>; | |
type _20 = Next<_19>; | |
type Digits = { 0: _0, 1: _1, 2: _2, 3: _3, 4: _4, 5: _5, 6: _6, 7: _7, 8: _8, 9: _9, 10: _10, 11: _11, 12: _12, 13: _13, 14: _14, 15: _15, 16: _16, 17: _17, 18: _18, 19: _19, 20: _20 }; | |
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; | |
type NumberToType<TNumber extends Digit> = Digits[TNumber]; | |
type _100 = Mult<_10, _10>; | |
type Dec2<T2 extends Digit, T1 extends Digit> | |
= Add<Mult<_10, NumberToType<T2>>, NumberToType<T1>>; | |
type Mod<TNumber extends AnyNumber, TModNumber extends AnyNumber> = | |
{ | |
"true": _0, | |
"false": Mod2<TNumber, TModNumber, SafeSubt<TNumber, TModNumber>> | |
}[IsZero<TNumber>]; | |
type Mod2<TNumber extends AnyNumber, TModNumber extends AnyNumber, TSubtResult extends SubtResult<any, any>> = | |
{ | |
"true": TNumber, | |
"false": Mod<TSubtResult["result"], TModNumber> | |
}[TSubtResult["isOverflowing"]]; | |
type Equals<TNumber1 extends AnyNumber, TNumber2 extends AnyNumber> | |
= Equals2<TNumber1, TNumber2, SafeSubt<TNumber1, TNumber2>>; | |
type Equals2<TNumber1 extends AnyNumber, TNumber2 extends AnyNumber, TSubtResult extends SubtResult<any, any>> = | |
{ | |
"true": "false", | |
"false": IsZero<TSubtResult["result"]> | |
}[TSubtResult["isOverflowing"]]; | |
// DIV | |
type Divisable<TNum extends Digit, TBase extends Digit> = | |
DivisableNumb<NumberToType<TNum>, NumberToType<TBase>> | |
type DivisableNumb<TNum extends AnyNumber, TBase extends AnyNumber> = | |
Equals<Mod<TNum, TBase>, _0> | |
type FizzBuzz<TNum extends Digit> = | |
Divisable<TNum, 15> extends "true" ? "FizzBuzz" : | |
Divisable<TNum, 3> extends "true" ? "Fizz" : | |
Divisable<TNum, 5> extends "true" ? "Buzz" : | |
TNum | |
// TEST | |
let fb1: FizzBuzz<1> | |
let fb2: FizzBuzz<2> | |
let fb3: FizzBuzz<3> | |
let fb4: FizzBuzz<4> | |
let fb5: FizzBuzz<5> | |
let fb6: FizzBuzz<6> | |
let fb7: FizzBuzz<7> | |
let fb8: FizzBuzz<8> | |
let fb9: FizzBuzz<9> | |
let fb10: FizzBuzz<10> | |
let fb11: FizzBuzz<11> | |
let fb12: FizzBuzz<12> | |
let fb13: FizzBuzz<13> | |
let fb14: FizzBuzz<14> | |
let fb15: FizzBuzz<15> | |
let fb16: FizzBuzz<16> | |
let fb17: FizzBuzz<17> | |
let fb18: FizzBuzz<18> | |
let fb19: FizzBuzz<19> | |
let fb20: FizzBuzz<20> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment