├── .gitignore ├── README.md ├── build.py ├── package-lock.json ├── package.json ├── source ├── day1.ts └── prelude │ ├── add.ts │ ├── index.ts │ ├── ints.ts │ ├── nat.ts │ ├── parse-int.ts │ └── sub.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cursed AoC 2 | 3 | Advent of Code, but I can only use TypeScript's type system to solve the puzzles. And yes, the inputs are also parsed by the type system :> 4 | 5 | ## Running this 6 | 7 | You'll need: 8 | 9 | 1. A Python3 interpreter --- look for Python files in this repo if you're curious about the **why** of that!; 10 | 2. Node.js; and 11 | 3. Unwavering faith in whatever gods you believe in :> 12 | 13 | Once you've managed to gather all ingredients^W requisites, you can run: 14 | 15 | npm run build 16 | npm run type-check 17 | 18 | If it compiles, then all of the code is correct. If it doesn't? Well, good luck. 19 | 20 | ## Note 21 | 22 | All of the puzzles will only solve the _example input_. Sadly trying to apply this to the real puzzle inputs is just going to make your computer cry. 23 | 24 | --- 25 | 26 |

27 | 29 | CC0 30 | 31 |
32 | To the extent possible under law, 33 | 35 | Q. 36 | has waived all copyright and related or neighboring rights to 37 | this work. 38 |

39 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | from functools import reduce 2 | 3 | def make_binary_table(name, n, op): 4 | output = """export type {0} = {{ 5 | [index: number]: {{ [index: number]: number }}; 6 | """.format(name) 7 | for i in range(0, n): 8 | output += " {0}: {{\n".format(i) 9 | for j in range(0, n): 10 | output += " {0}: {1};\n".format(j, op(i, j)) 11 | output += " };\n" 12 | output += "}[A][B];\n" 13 | return output 14 | 15 | def make_parse_table(n): 16 | output = """export type ParseInt = { 17 | [index: string]: number; 18 | """ 19 | for i in range(0, n): 20 | output += " '{0}': {1};".format(i, i) 21 | output += "}[S];" 22 | return output 23 | 24 | def make_valid_numbers(n): 25 | numbers = reduce(lambda a, b: "{0} | '{1}'".format(a, b), range(1, n), "'0'") 26 | output = "export type ValidNumber = {0};".format(numbers) 27 | return output 28 | 29 | 30 | def store(name, contents): 31 | with open(name, 'w') as f: 32 | f.write(contents) 33 | 34 | store("source/prelude/add.ts", make_binary_table("Add", 300, lambda x, y: x + y)) 35 | store("source/prelude/sub.ts", make_binary_table("Sub", 300, lambda x, y: max(-1, x - y))) 36 | store("source/prelude/parse-int.ts", make_parse_table(300)) 37 | store("source/prelude/ints.ts", make_valid_numbers(300)) 38 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aoc2021-ts", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "typescript": "^4.5.2" 9 | } 10 | }, 11 | "node_modules/typescript": { 12 | "version": "4.5.2", 13 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", 14 | "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", 15 | "bin": { 16 | "tsc": "bin/tsc", 17 | "tsserver": "bin/tsserver" 18 | }, 19 | "engines": { 20 | "node": ">=4.2.0" 21 | } 22 | } 23 | }, 24 | "dependencies": { 25 | "typescript": { 26 | "version": "4.5.2", 27 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", 28 | "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "python3 build.py", 4 | "type-check": "tsc -p ." 5 | }, 6 | "dependencies": { 7 | "typescript": "^4.5.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/day1.ts: -------------------------------------------------------------------------------- 1 | import type { Add, Lt, ParseInts, ParseLines, ToNat } from "./prelude"; 2 | 3 | type input = `199 4 | 200 5 | 208 6 | 210 7 | 200 8 | 207 9 | 240 10 | 269 11 | 260 12 | 263`; 13 | 14 | type parsed_input = ParseInts>; 15 | // [199, 200, 208, 210, 200, 207, 240, 269, 260, 263]; 16 | 17 | type DoSolve = In extends [] 18 | ? R 19 | : In extends [infer B, ...infer Rest] 20 | ? Lt, ToNat> extends true 21 | ? DoSolve, ToNat, Rest> 22 | : DoSolve, Rest> 23 | : never; 24 | 25 | type Solve = In extends [infer A, ...infer Rest] 26 | ? DoSolve<0, ToNat, Rest> 27 | : never; 28 | 29 | const result: Solve = 7; 30 | -------------------------------------------------------------------------------- /source/prelude/index.ts: -------------------------------------------------------------------------------- 1 | import type { Add } from "./add"; 2 | import type { Sub } from "./sub"; 3 | import type { ParseInt } from "./parse-int"; 4 | import type { ValidNumber } from "./ints"; 5 | export { Add, Sub, ParseInt, ValidNumber }; 6 | 7 | export type ParseLines = 8 | Str extends `${infer Line}\n${infer Rest}` 9 | ? [Line, ...ParseLines] 10 | : Str extends "" 11 | ? [] 12 | : Str extends `${infer Line}` 13 | ? [Line] 14 | : never; 15 | 16 | export type ParseInts = Strs extends [infer A, ...infer Rest] 17 | ? [ParseInt>, ...ParseInts] 18 | : Strs extends [] 19 | ? [] 20 | : never; 21 | 22 | const emptyNats: number[] = []; 23 | export type ToStr = A extends string ? A : ""; 24 | export type ToNat = A extends number ? A : -1; 25 | export type ToNats = A extends number[] ? A : typeof emptyNats; 26 | 27 | export type Cmp = Sub extends -1 28 | ? -1 29 | : Sub extends 0 30 | ? 0 31 | : 1; 32 | 33 | export type Lt = Cmp extends -1 34 | ? true 35 | : false; 36 | export type Lte = Cmp extends -1 | 0 37 | ? true 38 | : false; 39 | 40 | export type Eq = Cmp extends 0 41 | ? true 42 | : false; 43 | 44 | export type Gt = Cmp extends 1 45 | ? true 46 | : false; 47 | export type Gte = Cmp extends 1 | 0 48 | ? true 49 | : false; 50 | -------------------------------------------------------------------------------- /source/prelude/ints.ts: -------------------------------------------------------------------------------- 1 | export type ValidNumber = '0' | '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' | '26' | '27' | '28' | '29' | '30' | '31' | '32' | '33' | '34' | '35' | '36' | '37' | '38' | '39' | '40' | '41' | '42' | '43' | '44' | '45' | '46' | '47' | '48' | '49' | '50' | '51' | '52' | '53' | '54' | '55' | '56' | '57' | '58' | '59' | '60' | '61' | '62' | '63' | '64' | '65' | '66' | '67' | '68' | '69' | '70' | '71' | '72' | '73' | '74' | '75' | '76' | '77' | '78' | '79' | '80' | '81' | '82' | '83' | '84' | '85' | '86' | '87' | '88' | '89' | '90' | '91' | '92' | '93' | '94' | '95' | '96' | '97' | '98' | '99' | '100' | '101' | '102' | '103' | '104' | '105' | '106' | '107' | '108' | '109' | '110' | '111' | '112' | '113' | '114' | '115' | '116' | '117' | '118' | '119' | '120' | '121' | '122' | '123' | '124' | '125' | '126' | '127' | '128' | '129' | '130' | '131' | '132' | '133' | '134' | '135' | '136' | '137' | '138' | '139' | '140' | '141' | '142' | '143' | '144' | '145' | '146' | '147' | '148' | '149' | '150' | '151' | '152' | '153' | '154' | '155' | '156' | '157' | '158' | '159' | '160' | '161' | '162' | '163' | '164' | '165' | '166' | '167' | '168' | '169' | '170' | '171' | '172' | '173' | '174' | '175' | '176' | '177' | '178' | '179' | '180' | '181' | '182' | '183' | '184' | '185' | '186' | '187' | '188' | '189' | '190' | '191' | '192' | '193' | '194' | '195' | '196' | '197' | '198' | '199' | '200' | '201' | '202' | '203' | '204' | '205' | '206' | '207' | '208' | '209' | '210' | '211' | '212' | '213' | '214' | '215' | '216' | '217' | '218' | '219' | '220' | '221' | '222' | '223' | '224' | '225' | '226' | '227' | '228' | '229' | '230' | '231' | '232' | '233' | '234' | '235' | '236' | '237' | '238' | '239' | '240' | '241' | '242' | '243' | '244' | '245' | '246' | '247' | '248' | '249' | '250' | '251' | '252' | '253' | '254' | '255' | '256' | '257' | '258' | '259' | '260' | '261' | '262' | '263' | '264' | '265' | '266' | '267' | '268' | '269' | '270' | '271' | '272' | '273' | '274' | '275' | '276' | '277' | '278' | '279' | '280' | '281' | '282' | '283' | '284' | '285' | '286' | '287' | '288' | '289' | '290' | '291' | '292' | '293' | '294' | '295' | '296' | '297' | '298' | '299'; -------------------------------------------------------------------------------- /source/prelude/parse-int.ts: -------------------------------------------------------------------------------- 1 | export type ParseInt = { 2 | [index: string]: number; 3 | '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; '21': 21; '22': 22; '23': 23; '24': 24; '25': 25; '26': 26; '27': 27; '28': 28; '29': 29; '30': 30; '31': 31; '32': 32; '33': 33; '34': 34; '35': 35; '36': 36; '37': 37; '38': 38; '39': 39; '40': 40; '41': 41; '42': 42; '43': 43; '44': 44; '45': 45; '46': 46; '47': 47; '48': 48; '49': 49; '50': 50; '51': 51; '52': 52; '53': 53; '54': 54; '55': 55; '56': 56; '57': 57; '58': 58; '59': 59; '60': 60; '61': 61; '62': 62; '63': 63; '64': 64; '65': 65; '66': 66; '67': 67; '68': 68; '69': 69; '70': 70; '71': 71; '72': 72; '73': 73; '74': 74; '75': 75; '76': 76; '77': 77; '78': 78; '79': 79; '80': 80; '81': 81; '82': 82; '83': 83; '84': 84; '85': 85; '86': 86; '87': 87; '88': 88; '89': 89; '90': 90; '91': 91; '92': 92; '93': 93; '94': 94; '95': 95; '96': 96; '97': 97; '98': 98; '99': 99; '100': 100; '101': 101; '102': 102; '103': 103; '104': 104; '105': 105; '106': 106; '107': 107; '108': 108; '109': 109; '110': 110; '111': 111; '112': 112; '113': 113; '114': 114; '115': 115; '116': 116; '117': 117; '118': 118; '119': 119; '120': 120; '121': 121; '122': 122; '123': 123; '124': 124; '125': 125; '126': 126; '127': 127; '128': 128; '129': 129; '130': 130; '131': 131; '132': 132; '133': 133; '134': 134; '135': 135; '136': 136; '137': 137; '138': 138; '139': 139; '140': 140; '141': 141; '142': 142; '143': 143; '144': 144; '145': 145; '146': 146; '147': 147; '148': 148; '149': 149; '150': 150; '151': 151; '152': 152; '153': 153; '154': 154; '155': 155; '156': 156; '157': 157; '158': 158; '159': 159; '160': 160; '161': 161; '162': 162; '163': 163; '164': 164; '165': 165; '166': 166; '167': 167; '168': 168; '169': 169; '170': 170; '171': 171; '172': 172; '173': 173; '174': 174; '175': 175; '176': 176; '177': 177; '178': 178; '179': 179; '180': 180; '181': 181; '182': 182; '183': 183; '184': 184; '185': 185; '186': 186; '187': 187; '188': 188; '189': 189; '190': 190; '191': 191; '192': 192; '193': 193; '194': 194; '195': 195; '196': 196; '197': 197; '198': 198; '199': 199; '200': 200; '201': 201; '202': 202; '203': 203; '204': 204; '205': 205; '206': 206; '207': 207; '208': 208; '209': 209; '210': 210; '211': 211; '212': 212; '213': 213; '214': 214; '215': 215; '216': 216; '217': 217; '218': 218; '219': 219; '220': 220; '221': 221; '222': 222; '223': 223; '224': 224; '225': 225; '226': 226; '227': 227; '228': 228; '229': 229; '230': 230; '231': 231; '232': 232; '233': 233; '234': 234; '235': 235; '236': 236; '237': 237; '238': 238; '239': 239; '240': 240; '241': 241; '242': 242; '243': 243; '244': 244; '245': 245; '246': 246; '247': 247; '248': 248; '249': 249; '250': 250; '251': 251; '252': 252; '253': 253; '254': 254; '255': 255; '256': 256; '257': 257; '258': 258; '259': 259; '260': 260; '261': 261; '262': 262; '263': 263; '264': 264; '265': 265; '266': 266; '267': 267; '268': 268; '269': 269; '270': 270; '271': 271; '272': 272; '273': 273; '274': 274; '275': 275; '276': 276; '277': 277; '278': 278; '279': 279; '280': 280; '281': 281; '282': 282; '283': 283; '284': 284; '285': 285; '286': 286; '287': 287; '288': 288; '289': 289; '290': 290; '291': 291; '292': 292; '293': 293; '294': 294; '295': 295; '296': 296; '297': 297; '298': 298; '299': 299;}[S]; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "rootDir": "source", 5 | "outDir": "build", 6 | "module": "commonjs", 7 | "target": "ES2020", 8 | "lib": ["ESNext", "DOM", "ESNext.Intl"], 9 | "experimentalDecorators": true, 10 | "declaration": true, 11 | "incremental": true, 12 | "sourceMap": true 13 | }, 14 | "include": ["./source"] 15 | } 16 | --------------------------------------------------------------------------------