Solutions for Advent of Code 2023 using the TypeScript type system
My solutions for Advent of Code 2023 using the TypeScript type system.
Yes! TypeScript has a really powerful type system that lets you do all kinds of fun stuff! For example, this parses a string with a list of numbers separated by space into an array:
type ParseNumbers<TInput extends string> =
TInput extends `${infer INumber extends number} ${infer Rest}`
? [INumber, ...ParseNumbers<Rest>]
: TInput extends `${infer INumber extends number}`
? [INumber]
: [];
declare const input: ParseNumbers<'1 57 12 4'>; // [1, 57, 12, 4]
While the type system doesn't directly support arithmetic operations, they can be implemented in other ways. For example, this is a naive implementation of addition:
// Create a tuple of N items by recursively adding one item at a time until the length is N
type MakeCounter<N extends number, TResult extends any[] = []> = TResult['length'] extends N
? TResult
: MakeCounter<N, [...TResult, any]>;
type Add<A extends number, B extends number> = [...MakeCounter<A>, ...MakeCounter<B>]['length'];
declare const result: Add<2, 3>; // 5
A fun challenge! Please don't use any of this in production :)
This project uses Yarn as a package manager so you'll need to have that installed.
To install dependencies, run:
yarn install
This installs a patched version of TypeScript where type instantiation recursion limits have been raised a bit :). Be sure to point your editor to this local version of TypeScript if you want type hints.
As requested by the AoC organizers, the input files are not included in this
repository. Inputs should be placed in the input/
directory with
the name <NN>.ts
, where NN
is the 0-padded day number. For example, the
input for day 1 should be placed in input/01.ts
.
Each input file should contain a single Input
type export as follows:
export type Input = `<input>
`;
The <input>
is the raw input string as provided by AoC with newlines intact.
There should not be a leading newline, and there should always be a
trailing newline.
For example, the example input for day 1 would look like this:
export type Input = `1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
`;
To print the output of a solution, run:
yarn run print <day>
For example, yarn run print 4
prints the output of day 4.
Day | Stars |
---|---|
1 | ⭐️ ⭐️ |
2 | ⭐️ ⭐️ |
3 | ⭐️ ⭐️ |
4 | ⭐️ ⭐️ |
5 | ⭐️ ⭐️ |
6 | ⭐️ ⭐️ |
7 | ⭐️ ⭐️ |
8 | ⭐️ ⭐️ |
9 | ⭐️ ⭐️ |
10 | ⭐️ ⭐️ |
11 | ⭐️ ⭐️ |
12 | ⭐️ ⭐️ |
13 | ⭐️ ⭐️ |
14 | ⭐️ ⭐️ |
15 | ⭐️ ⭐️ |
16 | ⭐️ ⭐️ |
17 | ⭐️ ⭐️ |
18 | ⭐️ ⭐️ |
19 | ⭐️ ⭐️ |
20 | ⭐️ ⭐️ |
21 | ⭐️ ⭐️ |
22 | ⭐️ ⭐️ |
23 | ⭐️ ⭐️ |
24 | ⭐️ ⭐️ |
25 | ⭐️ ⭐️ |
There are many properties of TypeScript compiler that makes it significantly more difficult to solve these challenges:
2^24
instances of any type since this is the maximum number of entries a JavaScript Map
can hold. In particular you can't have too many different template literals (strings). For some of the more complex problems this means that you need to make sure you use a mix of different data structures in the solution, relying too much on any particular structure might cause you to hit this limit.These are a few things that I learned about how to best use the TypeScript type system to solve these challenges: