Skip to content

Instantly share code, notes, and snippets.

@oparisblue
Created July 12, 2022 08:29
Show Gist options
  • Save oparisblue/41a57166a76b744c3c3b9ddefdaa7001 to your computer and use it in GitHub Desktop.
Save oparisblue/41a57166a76b744c3c3b9ddefdaa7001 to your computer and use it in GitHub Desktop.
Computing Movement along X/Y axies using TypeScript types
type Direction = "N" | "E" | "S" | "W";
type MovementAlongAxis<Path extends string, PosAxis extends Direction, NegAxis extends Direction, PosPart extends string = "", NegPart extends string = ""> =
Uppercase<Path> extends `${infer Movement extends Direction}${infer RemainingPath}` ? (
// If we're adding to the axis's value
Movement extends PosAxis ? (
NegPart extends "" ? (
// No negatives => add one to the positive part
MovementAlongAxis<RemainingPath, PosAxis, NegAxis, `0${PosPart}`, NegPart>
) : (
// Negatives => remove one from the negative part
NegPart extends `${infer _}${infer RemainingNegative}` ?
MovementAlongAxis<RemainingPath, PosAxis, NegAxis, PosPart, RemainingNegative> :
MovementAlongAxis<RemainingPath, PosAxis, NegAxis, PosPart, "">
)
) :
// If we're removing from the axis's value
Movement extends NegAxis ? (
PosPart extends "" ? (
// No positives => add one to the negative part
MovementAlongAxis<RemainingPath, PosAxis, NegAxis, PosPart, `0${NegPart}`>
) : (
// Positives => remove one from the positive part
PosPart extends `${infer _}${infer RemainingPositive}` ?
MovementAlongAxis<RemainingPath, PosAxis, NegAxis, RemainingPositive, NegPart> :
MovementAlongAxis<RemainingPath, PosAxis, NegAxis, "", NegPart>
)
) :
// Movement in some other axis, skip
MovementAlongAxis<RemainingPath, PosAxis, NegAxis, PosPart, NegPart>
) : {"+": PosPart, "-": NegPart};
type TallyToNumber<Tally extends string, Result extends 0[] = []> =
Tally extends `${infer _}${infer Tail}` ?
TallyToNumber<Tail, [...Result, 0]> :
Result["length"];
type FormatNumber<Parts extends {"+": string, "-": string}> =
Parts["-"] extends "" ?
`${TallyToNumber<Parts["+"]>}` :
`-${TallyToNumber<Parts["-"]>}`;
type FindDestination<Path extends string> =
`X: ${FormatNumber<MovementAlongAxis<Path, "E", "W">>}, Y: ${FormatNumber<MovementAlongAxis<Path, "N", "S">>}`;
type Test = FindDestination<"NNNEEESSSWSSSS">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment