Skip to content

Instantly share code, notes, and snippets.

@Grubba27
Last active April 13, 2022 00:19
Show Gist options
  • Save Grubba27/8ac60e88868df7767ce3ac8d2bf62940 to your computer and use it in GitHub Desktop.
Save Grubba27/8ac60e88868df7767ce3ac8d2bf62940 to your computer and use it in GitHub Desktop.
Log
// Multiplication comes from this issue: https://github.com/type-challenges/type-challenges/issues/5814
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 Power<
V extends string,
P extends string,
A extends string = V> =
P extends '1'
? A
: P extends '0'
? '1'
: Power<V, SubOne<P>, Multiply<V, A>>
const $: Power<'2', '4'> = "16";
const _: Power<'2', '3'> = "8";
type ToNumber<
S extends string,
L extends number[] = []>
= `${L['length']}` extends S
? L['length']
: ToNumber<S, [...L, 0]>
type GreaterThan<
T extends number,
U extends number,
C extends unknown[] = []
> =
T extends U
? false
: C['length'] extends T
? false
: C['length'] extends U
? true
: GreaterThan<T, U, [...C, 1]>;
// Log<10, 100> = 2
type Log<
B extends string,
L extends string,
I extends string = "0",
PA extends string = "0"> =
L extends "1"
? "0"
: L extends PA
? I
: GreaterThan<ToNumber<PA>,ToNumber<L>> extends true
? never
: Log<B, L, AddOne<I>, Power<B, AddOne<I>>>;
let p: Log<"3", "81"> = "4"
let k: Log<"10", "100"> = "2"
let a: Log<"5", "5"> = "1"
let z: Log<"8", "1"> = "0"
let s: Log<"2", "256"> = "8"
let test: Log<"2", "10"> = "a"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment