Last active
February 4, 2022 00:04
-
-
Save zachhardesty7/2bc7327353adb13e7b443f8c85113ba0 to your computer and use it in GitHub Desktop.
AOC16 Typescript Types
This file contains 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
// copyright 2022 Zach Hardesty | |
// want to check this out in the TypeScript playground? | |
// visit the following link to automatically see the latest version! | |
// https://www.typescriptlang.org/play?jsx=0#gist/2bc7327353adb13e7b443f8c85113ba0 | |
// eventually a solution to day 16 of Advent of Code 2021 using only the compile-time | |
// type system of TypeScript. | |
// https://adventofcode.com/2021/day/16 | |
// TODO: implement proper subpacket parsing | |
// TODO: implement solution for non binary inputs for operations | |
// TODO: | |
// test out using `& {}` to brand a primitive | |
// i.e. prevent subtype reduction | |
// e.g. prevent eating nevers | |
// TODO: | |
// test out using `{} &` to force TS to expand out recursive types | |
// DEBUGGING HELP | |
// https://blog.andrewbran.ch/debugging-the-type-script-codebase/ | |
// https://www.typescriptlang.org/docs/handbook/compiler-options.html | |
// https://medium.com/jspoint/typescript-compilation-the-typescript-compiler-4cb15f7244bc | |
// https://servingniches.org/posts/2019-05-28___debugging_serverside_typescript_with_webstorm/ | |
// https://github.com/microsoft/TypeScript/pull/45711 // recursive tail call optimization PR | |
// DEBUGGING AST - maybe helpful, untested if it even works | |
// https://mihailik.github.io/teapo/ | |
// https://astexplorer.net/ | |
type INPUT_0 = "D" | |
type INPUT_1 = "D2FE28" | |
type INPUT_2 = "NOT_HEX" | |
type binaryMap = { | |
"0": "0000" | |
"1": "0001" | |
"2": "0010" | |
"3": "0011" | |
"4": "0100" | |
"5": "0101" | |
"6": "0110" | |
"7": "0111" | |
"8": "1000" | |
"9": "1001" | |
A: "1010" | |
B: "1011" | |
C: "1100" | |
D: "1101" | |
E: "1110" | |
F: "1111" | |
} | |
/** | |
* v1 convert string literal of hex chars to binary string literal | |
* | |
* technically doesn't fail if last char isn't hex | |
* | |
* max length - 999 hex chars | |
*/ | |
// type hexToBin< | |
// S extends string, | |
// Out extends string = "" | |
// > = S extends `${infer S0}${infer Rest}` | |
// ? S0 extends keyof binaryMap | |
// ? hexToBin<Rest, `${Out}${binaryMap[S0]}`> | |
// : never | |
// : Out | |
/** v2 also checks last char is hex, thought this would give 1 extra max char but no difference */ | |
// type hexToBin< | |
// S extends string, | |
// Out extends string = "" | |
// > = S extends `${infer S0}${infer Rest}` | |
// ? S0 extends keyof binaryMap | |
// ? Rest extends "" | |
// ? `${Out}${binaryMap[S0]}` | |
// : hexToBin<Rest, `${Out}${binaryMap[S0]}`> | |
// : never | |
// : never | |
/** | |
* v3 process 2 chars at the same time, half as much recursion | |
* | |
* max length - 1999 hex chars | |
*/ | |
type hexToBin< | |
S extends string, | |
Out extends string = "", | |
> = S extends `${infer S0}${infer S1}${infer Rest}` | |
? S0 extends keyof binaryMap | |
? S1 extends keyof binaryMap | |
? hexToBin<Rest, `${Out}${binaryMap[S0]}${binaryMap[S1]}`> | |
: never | |
: never | |
: S extends keyof binaryMap // only 0 or 1 chars left in input string | |
? `${Out}${binaryMap[S]}` | |
: Out | |
type INPUT_0_bin = Expect<hexToBin<INPUT_0>, "1101"> | |
type INPUT_1_bin = Expect<hexToBin<INPUT_1>, "110100101111111000101000"> | |
type INPUT_2_bin = Expect<hexToBin<INPUT_2>, never> | |
// | |
// #region - packet parsing | |
// | |
type Zero = "0" | |
type One = "1" | |
type Bit = Zero | One | |
type Nibble = `${Bit}${Bit}${Bit}${Bit}` | |
type Version = `${Bit}${Bit}${Bit}` | |
type PacketTypeAny = `${Bit}${Bit}${Bit}` | |
/** @version 1 */ | |
// type parseLitPacketBodyDebug< | |
// V extends string, | |
// Out extends string = "" | |
// > = V extends `${infer More}${infer N0}${infer N1}${infer N2}${infer N3}${infer Rest}` | |
// ? More extends Zero | |
// ? [`${Out}${N0}${N1}${N2}${N3}`, Rest] | |
// : More extends One | |
// ? parseLitPacketBodyDebug<Rest, `${Out}${N0}${N1}${N2}${N3}`> | |
// : never | |
// : never | |
/** @version 2 - use `Nibble`, maybe double infer at once is bad, but lazy match works here */ | |
// type parseLitPacketBodyDebug< | |
// V extends string, | |
// Out extends string = "" | |
// > = V extends `${Bit}${Nibble}${infer Rest}` | |
// ? V extends `${infer More}${infer N}${Rest}` | |
// ? More extends Zero | |
// ? [`${Out}${N}`, Rest] | |
// : More extends One | |
// ? parseLitPacketBodyDebug<Rest, `${Out}${N}`> | |
// : never | |
// : never | |
// : never | |
/** @version 3 - no `More`, nests better but 1 more `infer` */ | |
// type parseLitPacketBodyDebug< | |
// V extends string, | |
// Out extends string = "", | |
// > = V extends `0${Nibble}${infer Rest}` | |
// ? V extends `0${infer N}${Rest}` | |
// ? [`${Out}${N}`, Rest] | |
// : never | |
// : V extends `1${Nibble}${infer Rest}` | |
// ? V extends `1${infer N}${Rest}` | |
// ? parseLitPacketBodyDebug<Rest, `${Out}${N}`> | |
// : never | |
// : never | |
/** @version 4 - back to long infer list */ | |
type parseLitPacketBodyDebug< | |
V extends string, | |
Out extends string = "", | |
> = V extends `0${infer N0}${infer N1}${infer N2}${infer N3}${infer Rest}` | |
? [`${Out}${N0}${N1}${N2}${N3}`, Rest] | |
: V extends `1${infer N0}${infer N1}${infer N2}${infer N3}${infer Rest}` | |
? parseLitPacketBodyDebug<Rest, `${Out}${N0}${N1}${N2}${N3}`> | |
: never | |
type parseLitPacketDebug<B extends string> = B extends `${Version}100${infer Rest}` | |
? parseLitPacketBodyDebug<Rest> | |
: never | |
type INPUT_1_literal = Expect<parseLitPacketDebug<INPUT_1_bin>[0], "011111100101"> | |
type FourBit = `${Bit}${Bit}${Bit}${Bit}` | |
/** NOTE: DON'T USE, forces subtype expansion of union of 35k str literals, 15 bits, follows a `0` */ | |
type LengthTypeTotal = `${FourBit}${FourBit}${FourBit}${Bit}${Bit}${Bit}` | |
// might be some merit to some other approach like making a giant tuple or even a temporary one | |
// to simplify having to see `Bit` so many times | |
// type LengthTypeTotal2 = [Bit,Bit,Bit,Bit,Bit,Bit,Bit,Bit]; | |
// type LengthTypeTotal3 = [string, string, string]; | |
// type Test = "11100101" extends LengthTypeTotal2 ? "yes" : "no" | |
// type Tester2<Bin> = Bin extends [...LengthTypeTotal3, ...infer U] ? "yes" : "no" | |
// type Test2 = Tester2<["1","1","1","0","0","1","0","1"]> | |
// type Tester3<Bin> = Bin extends [...LengthTypeTotal3, ...infer U] ? "yes" : "no" | |
// type Test3 = Tester2<["1","1","1","0","0","1","0","1"]> | |
/** NOTE: DON'T USE, forces subtype expansion of union of 35k str literals, 11 bits, follows a `1` */ | |
type LengthTypeChildren = `${FourBit}${FourBit}${Bit}${Bit}${Bit}` | |
/** v1 */ | |
// type parseOpPacketBodyDebug< | |
// Val extends string | |
// // Out extends string = "" | |
// > = Val extends `${infer LT}${infer Rest}` | |
// ? // > = Val extends `${infer LT}${L1 | L2}${infer Rest}` | |
// // ? L1 extends LengthTypeTotal | |
// LT extends Zero | |
// ? Rest extends `${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer B11}${infer B12}${infer B13}${infer B14}${infer RestRest}` | |
// ? [ | |
// `${B0}${B1}${B2}${B3}${B4}${B5}${B6}${B7}${B8}${B9}${B10}${B11}${B12}${B13}${B14}`, | |
// RestRest | |
// ] | |
// : LT extends One | |
// ? Rest extends `${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer RestRest}` | |
// ? [ | |
// `${B0}${B1}${B2}${B3}${B4}${B5}${B6}${B7}${B8}${B9}${B10}`, | |
// RestRest | |
// ] | |
// : never | |
// : never | |
// : never | |
// : never | |
/** | |
* v2 upgrade readability - using double extend trick to | |
* minimize long template literal `infer` | |
* UPDATE: bad idea, forces TS to expand the subtype union of 35k string literals | |
*/ | |
// type parseOpPacketBodyDebug< | |
// Val extends string | |
// > = Val extends `${infer LT}${infer Rest}` | |
// ? LT extends Zero | |
// ? Rest extends `${LengthTypeTotal}${infer RestRest}` | |
// ? Rest extends `${infer B}${RestRest}` | |
// ? [B, RestRest] | |
// : never | |
// : never | |
// : LT extends One | |
// ? Rest extends `${LengthTypeChildren}${infer RestRest}` | |
// ? Rest extends `${infer B}${RestRest}` | |
// ? [B, RestRest] | |
// : never | |
// : never | |
// : never | |
// : never | |
/** v3 upgrade readability - eliminate extra `Rest`, inline and don't return single bit check */ | |
// type parseOpPacketBodyDebug<Val extends string> = | |
// Val extends `0${LengthTypeTotal}${infer Rest}` | |
// ? Val extends `0${infer Len}${Rest}` | |
// ? [Len, Rest] | |
// : never | |
// : Val extends `1${LengthTypeChildren}${infer Rest}` | |
// ? Val extends `1${infer Len}${Rest}` | |
// ? [Len, Rest] | |
// : never | |
// : never | |
/** v4 back to long bit infer to prevent expansion of subtype into 35k str literals */ | |
type parseOpPacketBodyDebug<Val extends string> = | |
Val extends `0${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer B11}${infer B12}${infer B13}${infer B14}${infer Rest}` | |
? [ | |
`${B0}${B1}${B2}${B3}${B4}${B5}${B6}${B7}${B8}${B9}${B10}${B11}${B12}${B13}${B14}`, | |
Rest, | |
] | |
: Val extends `1${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer Rest}` | |
? [`${B0}${B1}${B2}${B3}${B4}${B5}${B6}${B7}${B8}${B9}${B10}`, Rest] | |
: never | |
/** v1 */ | |
// type parseFirstPacketDebug< | |
// Bin extends string | |
// > = Bin extends `${infer V0}${infer V1}${infer V2}${infer T0}${infer T1}${infer T2}${infer Rest}` | |
// ? `${T0}${T1}${T2}` extends "100" | |
// ? [`${V0}${V1}${V2}`, `${T0}${T1}${T2}`, ...parseLitPacketBodyDebug<Rest>] | |
// : `${T0}${T1}${T2}` extends PacketTypeAny | |
// ? [`${V0}${V1}${V2}`, `${T0}${T1}${T2}`, ...parseOpPacketBodyDebug<Rest>] | |
// : never | |
// : never | |
/** v2 removes long `infer` template in favor of extra levels of nesting. good? bad? */ | |
// type parseFirstPacketDebug< | |
// Bin extends string | |
// > = Bin extends `${Version}${infer Rest1}` | |
// ? Bin extends `${infer V}${Rest1}` | |
// ? Rest1 extends `${PacketTypeAny}${infer Rest2}` | |
// ? Rest1 extends `${infer T}${Rest2}` | |
// ? T extends "100" | |
// ? [V, T, ...parseLitPacketBodyDebug<Rest2>] | |
// : T extends PacketTypeAny | |
// ? [V, T, ...parseOpPacketBodyDebug<Rest2>] | |
// : never | |
// : never | |
// : never | |
// : never | |
// : never | |
/** v3 drops 1 level of nesting for potentially less recursion depth or maybe much slower */ | |
type parseFirstPacketDebug<Bin extends string> = | |
Bin extends `${infer V0}${infer V1}${infer V2}${infer T0}${infer T1}${infer T2}${infer Rest}` | |
? `${T0}${T1}${T2}` extends "100" | |
? [`${V0}${V1}${V2}`, `${T0}${T1}${T2}`, ...parseLitPacketBodyDebug<Rest>] | |
: `${T0}${T1}${T2}` extends PacketTypeAny | |
? [`${V0}${V1}${V2}`, `${T0}${T1}${T2}`, ...parseOpPacketBodyDebug<Rest>] | |
: never | |
: never | |
/** optimize */ | |
type INPUT_1_debug_first_packet = Expect< | |
parseFirstPacketDebug<INPUT_1_bin>, | |
["110", "100", "011111100101", "000"] | |
> | |
type INPUT_3 = "38006F45291200" | |
type INPUT_3_bin = Expect< | |
hexToBin<INPUT_3>, | |
"00111000000000000110111101000101001010010001001000000000" | |
> | |
type INPUT_3_debug_first_packet = Expect< | |
parseFirstPacketDebug<INPUT_3_bin>, | |
["001", "110", /* "0", */ "000000000011011", "1101000101001010010001001000000000"] | |
> | |
type INPUT_3_debug_first_packet2 = Expect< | |
parseFirstPacketDebug<INPUT_3_debug_first_packet[3]>, | |
["110", "100", "1010", "01010010001001000000000"] | |
> | |
type INPUT_3_debug_first_packet3 = Expect< | |
parseFirstPacketDebug<INPUT_3_debug_first_packet2[3]>, | |
["010", "100", "00010100", "0000000"] | |
> | |
type INPUT_3_debug_first_packet4 = Expect< | |
parseFirstPacketDebug<INPUT_3_debug_first_packet3[3]>, | |
never | |
> | |
/** only useful for small inputs, TS doesn't print the full output */ | |
type parseAllPacketsDebug<Bin extends string> = Bin extends never | |
? [] | |
: [...parseFirstPacketDebug<Bin>, parseAllPacketsDebug<parseFirstPacketDebug<Bin>[3]>] | |
type INPUT_3_debug = parseAllPacketsDebug<INPUT_3_bin> | |
// | |
// #region - MATH - started this since version numbers need to be added together for part 1 | |
// | |
type AddBit<Bit1 extends string, Bit2 extends string> = Bit1 | Bit2 extends Zero | |
? Zero | |
: Bit1 | Bit2 extends One | |
? "?" | |
: One | |
type AddBinary<Bin1 extends string, Bin2 extends string, Out extends string = ""> = | |
| Bin1 | |
| Bin2 extends "" | |
? Out | |
: Bin1 extends `${infer Rest1}${Bit}` | |
? Bin1 extends `${Rest1}${infer B1}` | |
? Bin2 extends `${infer Rest2}${Bit}` | |
? Bin2 extends `${Rest2}${infer B2}` | |
? AddBinary<Rest1, Rest2, `${AddBit<B1, B2>}${Out}`> | |
: never | |
: never | |
: never | |
: never | |
type TEST_ADD_00 = Expect<AddBinary<"001", "010">, "011"> | |
/** carry not implemented */ | |
// @ts-expect-error | |
type TEST_ADD_01 = Expect<AddBinary<"100", "100">, "1000"> | |
/** | |
* lots of `Zero` & `One` use here. undecided if I like it. this way makes it quicker | |
* to write, but maybe a bit harder to read | |
*/ | |
type AddBitCarry< | |
Bit1 extends string, | |
Bit2 extends string, | |
Carry extends string = Zero, | |
> = Bit1 | Bit2 | Carry extends Zero // all Zero | |
? [Zero, Zero] | |
: Bit1 | Bit2 | Carry extends One // all One | |
? [One, One] | |
: (Bit1 | Bit2) & (Bit1 | Carry) & (Bit2 | Carry) extends One // One in any 2 out of the 3 positions | |
? [Zero, One] | |
: [One, Zero] | |
/** v1 does hiding the internal accumulators really matter? */ | |
// type _AddBinaryCarry< | |
// Bin1 extends string, | |
// Bin2 extends string, | |
// // internal | |
// Out extends string = "", | |
// Carry extends string = "0" | |
// > = Bin1 | Bin2 extends "" // base case, both are empty, terminate recursion and return | |
// ? Carry extends "1" | |
// ? `1${Out}` | |
// : Out | |
// : Bin1 extends `${infer Rest1}${Bit}` // pick off the last bit of each binary string | |
// ? Bin1 extends `${Rest1}${infer B1}` | |
// ? Bin2 extends `${infer Rest2}${Bit}` | |
// ? Bin2 extends `${Rest2}${infer B2}` | |
// ? _AddBinaryCarry< | |
// Rest1, | |
// Rest2, | |
// `${AddBitCarry<B1, B2, Carry>[0]}${Out}`, | |
// AddBitCarry<B1, B2, Carry>[1] | |
// > | |
// : never | |
// : never | |
// : never | |
// : never | |
// /** v2 handle sparse bit patterns */ | |
// type _AddBinaryCarry< | |
// Bin1 extends string, | |
// Bin2 extends string, | |
// // internal | |
// Out extends string = "", | |
// Carry extends string = "0" | |
// > = Bin1 | Bin2 extends "" // base case, both are empty, terminate recursion and return | |
// ? Carry extends "1" | |
// ? `1${Out}` | |
// : Out | |
// : Bin1 extends `${infer Rest1}${Bit}` // pick off the last bit of each binary string | |
// ? Bin1 extends `${Rest1}${infer B1}` | |
// ? Bin2 extends `${infer Rest2}${Bit}` | |
// ? Bin2 extends `${Rest2}${infer B2}` | |
// ? _AddBinaryCarry< | |
// Rest1, | |
// Rest2, | |
// `${AddBitCarry<B1, B2, Carry>[0]}${Out}`, | |
// AddBitCarry<B1, B2, Carry>[1] | |
// > | |
// : never | |
// : _AddBinaryCarry< | |
// Rest1, | |
// Bin2, | |
// `${AddBitCarry<B1, "0", Carry>[0]}${Out}`, | |
// AddBitCarry<B1, "0", Carry>[1] | |
// > | |
// : never | |
// : Bin2 extends `${infer Rest2}${Bit}` | |
// ? Bin2 extends `${Rest2}${infer B2}` | |
// ? _AddBinaryCarry< | |
// Bin1, | |
// Rest2, | |
// `${AddBitCarry<Zero, B2, Carry>[0]}${Out}`, | |
// AddBitCarry<Zero, B2, Carry>[1] | |
// > | |
// : never | |
// : never | |
type Bitify<Bit extends string> = Bit extends "" ? Zero : Bit | |
/** v3 */ | |
/** | |
* recursive depth might be pretty limited but fine for now. `Add2Bit` inline would double depth | |
* | |
* mismatched binary length inputs are invalid, but could be left padded with zero | |
* | |
* @todo optimization | |
* | |
* @version 3 handle sparse bit patterns better | |
*/ | |
type AddBinaryCarry< | |
Bin1 extends string, | |
Bin2 extends string, | |
// internal | |
Out extends string = "", | |
Carry extends string = "0", | |
> = Bin1 | Bin2 extends "" // base case, both are empty, terminate recursion and return | |
? Carry extends "1" | |
? `1${Out}` | |
: Out | |
: Bitify<Bin1> extends `${infer Rest1}${Bit}` // pick off the last bit of each binary string | |
? Bitify<Bin1> extends `${Rest1}${infer B1}` | |
? Bitify<Bin2> extends `${infer Rest2}${Bit}` | |
? Bitify<Bin2> extends `${Rest2}${infer B2}` | |
? AddBinaryCarry< | |
Rest1, | |
Rest2, | |
`${AddBitCarry<B1, B2, Carry>[0]}${Out}`, | |
AddBitCarry<B1, B2, Carry>[1] | |
> | |
: never | |
: never | |
: never | |
: never | |
type A = Zero | |
// type A = One | |
type B = Zero | |
// type B = One | |
// type C = Zero | |
type C = One | |
// logic used for carry bit. true if any 2 of 3 inputs are both One | |
type TEST_ADD_1 = (A | B) & (A | C) & (B | C) extends One ? true : false | |
type TEST_ADD_20 = Expect<AddBinaryCarry<"001", "010">, "011"> | |
type TEST_ADD_21 = Expect<AddBinaryCarry<"001", "001">, "010"> | |
type TEST_ADD_22 = Expect<AddBinaryCarry<"001", "011">, "100"> | |
type TEST_ADD_23 = Expect<AddBinaryCarry<"011", "011">, "110"> | |
type TEST_ADD_24 = Expect<AddBinaryCarry<"100", "100">, "1000"> | |
type TEST_ADD_25 = Expect<AddBinaryCarry<"111", "111">, "1110"> | |
type TEST_ADD_26 = Expect< | |
AddBinaryCarry<"01010101010101010101", "10101010101010101010">, | |
"11111111111111111111" | |
> | |
type TEST_ADD_27 = Expect< | |
AddBinaryCarry<"11000000000000000001", "10000000000000000000">, | |
"101000000000000000001" | |
> | |
type TEST_ADD_30 = Expect<AddBinaryCarry<"1", "0000">, "0001"> | |
type TEST_ADD_31 = Expect<AddBinaryCarry<"0000", "1">, "0001"> | |
type TEST_ADD_32 = Expect<AddBinaryCarry<"", "1">, "1"> | |
type TEST_ADD_33 = Expect<AddBinaryCarry<"1", "">, "1"> | |
type TEST_ADD_34 = Expect<AddBinaryCarry<"", "">, ""> | |
// #region - meta helpers | |
/** | |
* passes thru passing test input, errors with inputs that are not equal | |
* | |
* can be used in the middle of an expression and composed to check each step | |
* | |
* @todo check for perf issues with recursion | |
*/ | |
type Expect< | |
Input extends Intersect, | |
Expected extends Intersect, | |
Intersect = Expected & Input, | |
> = Input | |
// const RENDER_TESTER2 = "RENDER_TESTER" | |
// @ts-expect-error | |
type expect_chain_test_0 = Expect<42, Expect<number, 42> | 0> | |
// @ts-expect-error | |
type expect_chain_test_1 = Expect<Expect<number, 42> | 0, 42> | |
type expect_chain_test_2 = Expect<Expect<42 | number, number> | 0, number> | |
type expect_chain_test_3 = Expect<number, Expect<number, 42 | number> | 0> | |
// | |
// #region - VERSION OPTIMIZED FINAL | |
// | |
type parseAllPacketsVersionsDebug< | |
Bin extends string, | |
Out extends Array<any> = [], | |
> = Bin extends never | |
? Out | |
: parseFirstPacketDebug<Bin> extends never | |
? Out | |
: parseAllPacketsVersionsDebug< | |
parseFirstPacketDebug<Bin>[3], | |
[...Out, parseFirstPacketDebug<Bin>[0]] | |
> | |
/** v1 */ | |
// type parseLitPacketBodyVersions<Body extends string> = | |
// Body extends `0${Nibble}${infer RestD}` | |
// ? RestD | |
// : Body extends `1${Nibble}${infer RestE}` | |
// ? parseLitPacketBodyVersions<RestE> | |
// : never | |
/** @version 2 - eliminate `Nibble` as it causes excessive subtype expansion */ | |
type parseLitPacketBodyVersions<Body extends string> = | |
Body extends `0${infer B0}${infer B1}${infer B2}${infer B3}${infer RestD}` | |
? RestD | |
: Body extends `1${infer B0}${infer B1}${infer B2}${infer B3}${infer RestE}` | |
? parseLitPacketBodyVersions<RestE> | |
: never | |
type parseOpPacketBodyVersions<Body extends string> = | |
Body extends `0${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer B11}${infer B12}${infer B13}${infer B14}${infer RestB}` | |
? [RestB] | |
: Body extends `1${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer RestC}` | |
? [RestC] | |
: never | |
/** @version 1 */ | |
// type parseFirstPacketVersions<BinPacket extends string> = | |
// BinPacket extends `${Version}${PacketTypeAny}${infer RestA}` | |
// ? BinPacket extends `${infer V}${PacketTypeAny}${RestA}` | |
// ? BinPacket extends `${Version}${infer T}${RestA}` | |
// ? T extends "100" | |
// ? [V, ...[parseLitPacketBodyVersions<RestA>]] | |
// : [V, ...parseOpPacketBodyVersions<RestA>] | |
// : never | |
// : never | |
// : never | |
/** | |
* @version 2 - sigh, back to goofy bit pattern, slightly faster | |
*/ | |
type parseFirstPacketVersions<BinPacket extends string> = | |
BinPacket extends `${Version}${PacketTypeAny}${infer RestA}` | |
? BinPacket extends `${infer V}${PacketTypeAny}${RestA}` | |
? BinPacket extends `${Version}${infer T}${RestA}` | |
? T extends "100" | |
? [V, ...[parseLitPacketBodyVersions<RestA>]] | |
: [V, ...parseOpPacketBodyVersions<RestA>] | |
: never | |
: never | |
: never | |
/** v1 perf: supports ~270 hex chars, or 9 repeats of A0016C880162017C3686B18A3D4780 */ | |
// type parseAllPacketsVersionsSum< | |
// Bin extends string, | |
// Sum extends string = "" | |
// > = Bin extends never | |
// ? Sum | |
// : parseFirstPacketVersions<Bin> extends never | |
// ? Sum | |
// : parseAllPacketsVersionsSum< | |
// parseFirstPacketVersions<Bin>[1], | |
// AddBinaryCarry<parseFirstPacketVersions<Bin>[0], Sum> | |
// > | |
/** | |
* @version 2 - same recursion, but faster | |
*/ | |
type _parseAllPacketsVersionsSum< | |
Packet extends [string, string], | |
Sum extends string, | |
> = Packet[1] extends "" | |
? Sum | |
: _parseAllPacketsVersionsSum< | |
parseFirstPacketVersions<Packet[1]>, | |
AddBinaryCarry<Packet[0], Sum> | |
> | |
/** | |
* kick off recursion | |
* perf: supports ~270 hex chars, or 9 repeats of A0016C880162017C3686B18A3D4780 | |
* @version 2 | |
*/ | |
type parseAllPacketsVersionsSum<Bin extends string> = _parseAllPacketsVersionsSum< | |
parseFirstPacketVersions<Bin>, | |
"" | |
> | |
type INPUT_3_versions = Expect< | |
parseAllPacketsVersionsDebug<INPUT_3_bin>, | |
["001", "110", "010"] | |
> | |
type INPUT_3_versions_sum = Expect<parseAllPacketsVersionsSum<INPUT_3_bin>, "1001"> | |
type INPUT_4 = "EE00D40C823060" | |
type INPUT_4_bin = Expect< | |
hexToBin<INPUT_4>, | |
"11101110000000001101010000001100100000100011000001100000" | |
> | |
// type INPUT_4_debug = parseAllPacketsDebug<INPUT_4_bin> | |
type INPUT_4_versions = Expect< | |
parseAllPacketsVersionsDebug<INPUT_4_bin>, | |
["111", "010", "100", "001"] | |
> | |
type INPUT_4_versions_sum = Expect<parseAllPacketsVersionsSum<INPUT_4_bin>, "1110"> | |
type INPUT_5 = "8A004A801A8002F478" | |
type INPUT_5_bin = hexToBin<INPUT_5> | |
// type INPUT_5_versions = parseAllPacketsVersionsDebug<INPUT_5_bin> | |
type INPUT_5_versions_sum = Expect<parseAllPacketsVersionsSum<INPUT_5_bin>, "10000"> | |
type INPUT_6 = "620080001611562C8802118E34" | |
type INPUT_6_bin = hexToBin<INPUT_6> | |
// type INPUT_6_versions = parseAllPacketsVersionsDebug<INPUT_6_bin> | |
type INPUT_6_versions_sum = Expect<parseAllPacketsVersionsSum<INPUT_6_bin>, "1100"> | |
type INPUT_7 = "C0015000016115A2E0802F182340" | |
type INPUT_7_bin = hexToBin<INPUT_7> | |
// type INPUT_7_versions = parseAllPacketsVersionsDebug<INPUT_7_bin> | |
type INPUT_7_versions_sum = Expect<parseAllPacketsVersionsSum<INPUT_7_bin>, "10111"> | |
type INPUT_8 = "A0016C880162017C3686B18A3D4780" | |
type INPUT_8_bin = hexToBin<INPUT_8> | |
// type INPUT_8_versions = parseAllPacketsVersionsDebug<INPUT_8_bin> | |
type INPUT_8_versions_sum = Expect<parseAllPacketsVersionsSum<INPUT_8_bin>, "11111"> | |
type INPUT_FINAL = | |
"420D74C3088043390499ED709E6EB49A5CC4A3A3898B7E0F44011C4CC48AC0119D049B0C500265EB8F615900180910C88129B2F0007C61C4B7F74ED7396B20020A44A4C014D005E5A72E274B4E5C4B96CC3793410078C01D82F1DA08180351661AC1920042A3CC578BA6008F802138D93352B9CFCEF61D3009A7D2268D254925569C02A92D62BF108D52C1B3E4B257B57FAE5C54400A84840267880311D23245F1007A35C79848200C4288FF0E8C01194A4E625E00A4EFEF5F5996486C400C5002800BFA402D3D00A9C4027B98093D602231C00F001D38C009500258057E601324C00D3003D400C7003DC00A20053A6F1DBDE2D4600A6802B37C4B9E872B0E44CA5FF0BFB116C3004740119895E6F7312BCDE25EF077700725B9F2B8F131F333005740169A7F92EFEB3BC8A21998027400D2CDF30F927880B4C62D6CDFFD88EB0068D2BF019A8DAAF3245B39C9CFA1D2DF9C3DB9D3E50A0164BE2A3339436993894EC41A0D10020B329334C62016C8E7A5F27C97D0663982D8EB23C5282529CDD271E8F100AE1401AA80021119E3A4511006E1E47689323585F3AEBF900AEB2B6942BD91EE8028000874238AB0C00010B8D913220A004A73D789C4D54E24816301802538E940198880371AE15C1D1007638C43856C00954C25CD595A471FE9D90056D60094CEA61933A9854E9F3801F2BBC6131001F792F6796ACB40D036605C80348C005F64F5AC374888CA42FD99A98025319EB950025713656F202200B767AB6A30E802D278F81CBA89004CD286360094FC03A7E01640245CED5A3C010100660FC578B60008641C8B105CC017F004E597E596E633BA5AB78B9C8F840C029917C9E389B439179927A3004F003511006610C658A200084C2989D0AE67BD07000606154B70E66DC0C01E99649545950B8AB34C8401A5CDA050043D319F31CB7EBCEE14" | |
type INPUT_FINAL_bin = hexToBin<INPUT_FINAL> | |
// type INPUT_FINAL_versions = parseAllPacketsVersions<INPUT_FINAL_bin> | |
/** gotta manually convert to decimal unfortunately (`895`) */ | |
type INPUT_FINAL_versions_sum = Expect< | |
parseAllPacketsVersionsSum<INPUT_FINAL_bin>, | |
"1101111111" | |
> | |
/************************** | |
* #region - START PART 2 | |
**************************/ | |
type Trim<Bin> = Bin extends "" | |
? "0" | |
: Bin extends `${infer B0}${infer Rest}` | |
? B0 extends "0" | |
? Trim<Rest> | |
: Bin | |
: Bin | |
type _MultBin< | |
Bin1 extends string, | |
Bin2 extends string, | |
// internal | |
Count extends string = "1", | |
Orig extends string = Bin1, | |
> = Trim<Bin2> extends Count | |
? Bin1 | |
: _MultBin<AddBinaryCarry<Bin1, Orig>, Bin2, AddBinaryCarry<Count, "1">, Orig> | |
type MultBin<Bin1 extends string, Bin2 extends string> = "0" extends | |
| Trim<Bin1> | |
| Trim<Bin2> | |
? "0" | |
: _MultBin<Bin1, Bin2> | |
type TEST_MULT_00 = Expect<MultBin<"001", "010">, "010"> | |
type TEST_MULT_01 = Expect<MultBin<"001", "001">, "001"> | |
type TEST_MULT_02 = Expect<MultBin<"001", "011">, "011"> | |
type TEST_MULT_03 = Expect<MultBin<"011", "011">, "1001"> | |
type TEST_MULT_04 = Expect<MultBin<"100", "100">, "10000"> | |
type TEST_MULT_05 = Expect<MultBin<"111", "111">, "110001"> | |
type TEST_MULT_06 = Expect<MultBin<"011", "010">, "110"> | |
type TEST_MULT_07 = Expect<MultBin<"010", "011">, "110"> | |
type TEST_MULT_20 = Expect<MultBin<"1", "0000">, "0"> | |
type TEST_MULT_21 = Expect<MultBin<"0000", "1">, "0"> | |
type TEST_MULT_22 = Expect<MultBin<"", "1">, "0"> | |
type TEST_MULT_23 = Expect<MultBin<"1", "">, "0"> | |
type TEST_MULT_24 = Expect<MultBin<"", "">, "0"> | |
type Equal<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false | |
type MinBin< | |
Bin1 extends string, | |
Bin2 extends string, | |
Orig1 extends string = Bin1, | |
Orig2 extends string = Bin2, | |
> = Equal<Trim<Bin1>, Trim<Bin2>> extends true | |
? Bin1 | |
: Bin1 extends `${infer B1}${infer Rest1}` | |
? Bin2 extends `${infer B2}${infer Rest2}` | |
? Equal<B1, B2> extends true | |
? MinBin<Rest1, Rest2, Orig1, Orig2> | |
: B1 extends "0" | |
? Orig1 | |
: B2 extends "0" | |
? Orig2 | |
: never | |
: never | |
: never | |
type TEST_MIN_00 = Expect<MinBin<"001", "010">, "001"> | |
type TEST_MIN_01 = Expect<MinBin<"001", "001">, "001"> | |
type TEST_MIN_02 = Expect<MinBin<"001", "011">, "001"> | |
type TEST_MIN_03 = Expect<MinBin<"011", "011">, "011"> | |
type TEST_MIN_06 = Expect<MinBin<"011", "010">, "010"> | |
type TEST_MIN_07 = Expect<MinBin<"010", "011">, "010"> | |
type TEST_MIN_20 = Expect<MinBin<"1", "0000">, "0000"> | |
type TEST_MIN_21 = Expect<MinBin<"0000", "1">, "0000"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_MIN_22 = Expect<MinBin<"", "1">, "0"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_MIN_23 = Expect<MinBin<"1", "">, "0"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_MIN_24 = Expect<MinBin<"", "">, "0"> | |
type MaxBin< | |
Bin1 extends string, | |
Bin2 extends string, | |
Orig1 extends string = Bin1, | |
Orig2 extends string = Bin2, | |
> = Equal<Trim<Bin1>, Trim<Bin2>> extends true | |
? Bin1 | |
: Bin1 extends `${infer B1}${infer Rest1}` | |
? Bin2 extends `${infer B2}${infer Rest2}` | |
? Equal<B1, B2> extends true | |
? MaxBin<Rest1, Rest2, Orig1, Orig2> | |
: B1 extends "1" | |
? Orig1 | |
: B2 extends "1" | |
? Orig2 | |
: never | |
: never | |
: never | |
type TEST_MAX_00 = Expect<MaxBin<"001", "010">, "010"> | |
type TEST_MAX_01 = Expect<MaxBin<"001", "001">, "001"> | |
type TEST_MAX_02 = Expect<MaxBin<"001", "011">, "011"> | |
type TEST_MAX_03 = Expect<MaxBin<"011", "011">, "011"> | |
type TEST_MAX_06 = Expect<MaxBin<"011", "010">, "011"> | |
type TEST_MAX_07 = Expect<MaxBin<"010", "011">, "011"> | |
type TEST_MAX_20 = Expect<MaxBin<"1", "0000">, "1"> | |
type TEST_MAX_21 = Expect<MaxBin<"0000", "1">, "1"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_MAX_22 = Expect<MaxBin<"", "1">, "1"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_MAX_23 = Expect<MaxBin<"1", "">, "1"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_MAX_24 = Expect<MaxBin<"", "">, "??"> | |
type GTBin< | |
Bin1 extends string, | |
Bin2 extends string, | |
Orig1 extends string = Bin1, | |
Orig2 extends string = Bin2, | |
> = Equal<Trim<Bin1>, Trim<Bin2>> extends true | |
? Zero | |
: Bin1 extends `${infer B1}${infer Rest1}` | |
? Bin2 extends `${infer B2}${infer Rest2}` | |
? Equal<B1, B2> extends true | |
? GTBin<Rest1, Rest2, Orig1, Orig2> | |
: B1 extends "1" | |
? One | |
: Zero | |
: never | |
: never | |
type TEST_GT_00 = Expect<GTBin<"001", "010">, "0"> | |
type TEST_GT_01 = Expect<GTBin<"001", "001">, "0"> | |
type TEST_GT_06 = Expect<GTBin<"011", "010">, "1"> | |
type TEST_GT_07 = Expect<GTBin<"010", "011">, "0"> | |
type TEST_GT_20 = Expect<GTBin<"1", "0000">, "1"> | |
type TEST_GT_21 = Expect<GTBin<"0000", "1">, "0"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_GT_22 = Expect<GTBin<"", "1">, "1"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_GT_23 = Expect<GTBin<"1", "">, "1"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_GT_24 = Expect<GTBin<"", "">, "??"> | |
type LTBin< | |
Bin1 extends string, | |
Bin2 extends string, | |
Orig1 extends string = Bin1, | |
Orig2 extends string = Bin2, | |
> = Equal<Trim<Bin1>, Trim<Bin2>> extends true | |
? Zero | |
: Bin1 extends `${infer B1}${infer Rest1}` | |
? Bin2 extends `${infer B2}${infer Rest2}` | |
? Equal<B1, B2> extends true | |
? LTBin<Rest1, Rest2, Orig1, Orig2> | |
: B1 extends "0" | |
? One | |
: Zero | |
: never | |
: never | |
type TEST_LT_00 = Expect<LTBin<"001", "010">, "1"> | |
type TEST_LT_01 = Expect<LTBin<"001", "001">, "0"> | |
type TEST_LT_06 = Expect<LTBin<"011", "010">, "0"> | |
type TEST_LT_07 = Expect<LTBin<"010", "011">, "1"> | |
type TEST_LT_20 = Expect<LTBin<"1", "0000">, "0"> | |
type TEST_LT_21 = Expect<LTBin<"0000", "1">, "1"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_LT_22 = Expect<LTBin<"", "1">, "1"> | |
// @ts-expect-error - empty string not implemented | |
type TEST_LT_23 = Expect<LTBin<"1", "">, "0"> | |
type TEST_LT_24 = Expect<LTBin<"", "">, "0"> | |
type EQBin<Bin1 extends string, Bin2 extends string> = Equal< | |
Trim<Bin1>, | |
Trim<Bin2> | |
> extends true | |
? One | |
: Zero | |
type TEST_EQ_00 = Expect<EQBin<"001", "010">, "0"> | |
type TEST_EQ_01 = Expect<EQBin<"001", "001">, "1"> | |
type TEST_EQ_06 = Expect<EQBin<"011", "010">, "0"> | |
type TEST_EQ_07 = Expect<EQBin<"010", "011">, "0"> | |
type TEST_EQ_08 = Expect<EQBin<"00001", "1">, "1"> | |
type TEST_EQ_20 = Expect<EQBin<"1", "0000">, "0"> | |
type TEST_EQ_21 = Expect<EQBin<"0000", "1">, "0"> | |
type TEST_EQ_22 = Expect<EQBin<"", "1">, "0"> | |
type TEST_EQ_23 = Expect<EQBin<"1", "">, "0"> | |
type TEST_EQ_24 = Expect<EQBin<"", "">, "1"> | |
/***************** | |
* PART II FINAL | |
*****************/ | |
type IPacketTypeId = { | |
sum: "000" | |
product: "001" | |
min: "010" | |
max: "011" | |
literal: "100" | |
gt: "101" | |
lt: "110" | |
eq: "111" | |
} | |
type IPacketTypeName = { | |
[K in keyof IPacketTypeId as IPacketTypeId[K]]: K | |
} | |
namespace PacketTypeId { | |
export type sum = "000" | |
export type product = "001" | |
export type min = "010" | |
export type max = "011" | |
export type literal = "100" | |
export type gt = "101" | |
export type lt = "110" | |
export type eq = "111" | |
} | |
/** @version 1 */ | |
type parseLitPacketBodyOut< | |
Body extends string, | |
Out extends string = "", | |
> = Body extends `0${infer B0}${infer B1}${infer B2}${infer B3}${infer RestD}` | |
? [`${Out}${B0}${B1}${B2}${B3}`, RestD] | |
: Body extends `1${infer B0}${infer B1}${infer B2}${infer B3}${infer RestE}` | |
? parseLitPacketBodyOut<RestE, `${Out}${B0}${B1}${B2}${B3}`> | |
: never | |
/** @version 1 */ | |
type parseOpPacketLengthOut<Bin extends string> = | |
Bin extends `0${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer B11}${infer B12}${infer B13}${infer B14}${infer RestB}` | |
? [ | |
`${B0}${B1}${B2}${B3}${B4}${B5}${B6}${B7}${B8}${B9}${B10}${B11}${B12}${B13}${B14}`, | |
RestB, | |
] | |
: Bin extends `1${infer B0}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer B10}${infer RestC}` | |
? [`${B0}${B1}${B2}${B3}${B4}${B5}${B6}${B7}${B8}${B9}${B10}`, RestC] | |
: never | |
/** @todo support unary and n-ary inputs */ | |
type parseSumPacketBodyOut<Body extends string> = [ | |
AddBinaryCarry< | |
parseFirstPacketOut<Body>[0], | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[0] | |
>, | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[1], | |
] | |
/** @todo support unary and n-ary inputs */ | |
type parseMultPacketBodyOut<Body extends string> = [ | |
MultBin< | |
parseFirstPacketOut<Body>[0], | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[0] | |
>, | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[1], | |
] | |
/** @todo support unary and n-ary inputs */ | |
type parseMinPacketBodyOut<Body extends string> = [ | |
MinBin< | |
parseFirstPacketOut<Body>[0], | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[0] | |
>, | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[1], | |
] | |
/** @todo support unary and n-ary inputs */ | |
type parseMaxPacketBodyOut<Body extends string> = [ | |
MaxBin< | |
parseFirstPacketOut<Body>[0], | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[0] | |
>, | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[1], | |
] | |
type parseLTPacketBodyOut<Body extends string> = [ | |
LTBin< | |
parseFirstPacketOut<Body>[0], | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[0] | |
>, | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[1], | |
] | |
type parseGTPacketBodyOut<Body extends string> = [ | |
GTBin< | |
parseFirstPacketOut<Body>[0], | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[0] | |
>, | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[1], | |
] | |
type parseEQPacketBodyOut<Body extends string> = [ | |
EQBin< | |
parseFirstPacketOut<Body>[0], | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[0] | |
>, | |
parseFirstPacketOut<parseFirstPacketOut<Body>[1]>[1], | |
] | |
/** switch statement for picking operation */ | |
type parseOpPacketOut< | |
Type extends string, | |
Length extends string, | |
Body extends string, | |
> = Type extends PacketTypeId.lt | |
? parseLTPacketBodyOut<Body> | |
: Type extends PacketTypeId.gt | |
? parseGTPacketBodyOut<Body> | |
: Type extends PacketTypeId.eq | |
? parseEQPacketBodyOut<Body> | |
: Type extends PacketTypeId.sum | |
? parseSumPacketBodyOut<Body> | |
: Type extends PacketTypeId.product | |
? parseMultPacketBodyOut<Body> | |
: Type extends PacketTypeId.min | |
? parseMinPacketBodyOut<Body> | |
: Type extends PacketTypeId.max | |
? parseMaxPacketBodyOut<Body> | |
: never | |
/** | |
* @version 1 | |
*/ | |
type parseFirstPacketOut<BinPacket extends string> = | |
BinPacket extends `${infer V0}${infer V1}${infer V2}${infer T0}${infer T1}${infer T2}${infer RestA}` | |
? `${T0}${T1}${T2}` extends PacketTypeId.literal | |
? parseLitPacketBodyOut<RestA> | |
: Trim< | |
parseOpPacketOut< | |
`${T0}${T1}${T2}`, | |
parseOpPacketLengthOut<RestA>[0], | |
parseOpPacketLengthOut<RestA>[1] | |
>[0] | |
> | |
: never | |
/** | |
* @version 1 | |
*/ | |
type _parseAllPacketsOut< | |
Packet extends [string, string], | |
Res extends string, | |
> = Packet[1] extends "" | |
? Packet[0] | |
: _parseAllPacketsOut< | |
parseFirstPacketOut<Packet[1]>[1], | |
parseFirstPacketOut<Packet[1]>[0] | |
> | |
/** | |
* kick off recursion | |
* @version 1 | |
*/ | |
type parseAllPacketsOut<Bin extends string> = _parseAllPacketsOut< | |
parseFirstPacketOut<Bin>, | |
"" | |
> | |
// #region printers | |
type printOPPacketBodyOut<Body extends string> = [ | |
[printFirstPacketOut<Body>, printFirstPacketOut<printFirstPacketOut<Body>[2]>], | |
printFirstPacketOut<printFirstPacketOut<Body>[2]>[2], | |
] | |
type printOpPacketOut< | |
Type extends string, | |
Body extends string, | |
> = Type extends keyof IPacketTypeName | |
? [IPacketTypeName[Type], ...printOPPacketBodyOut<Body>] | |
: never | |
/** | |
* @version 1 | |
*/ | |
type printFirstPacketOut<BinPacket extends string> = | |
BinPacket extends `${infer V0}${infer V1}${infer V2}${infer T0}${infer T1}${infer T2}${infer RestA}` | |
? `${T0}${T1}${T2}` extends PacketTypeId.literal | |
? ["lit", ...parseLitPacketBodyOut<RestA>] | |
: printOpPacketOut<`${T0}${T1}${T2}`, parseOpPacketLengthOut<RestA>[1]> | |
: never | |
/** sum */ | |
type INPUT_20 = hexToBin<"C200B40A82"> | |
type INPUT_20_DEBUG = printFirstPacketOut<INPUT_20> | |
type INPUT_20_OUT = Expect<parseFirstPacketOut<INPUT_20>, "11"> | |
/** product */ | |
type INPUT_21 = hexToBin<"04005AC33890"> | |
type INPUT_21_DEBUG = printFirstPacketOut<INPUT_21> | |
type INPUT_21_OUT = Expect<parseFirstPacketOut<INPUT_21>, "110110"> | |
/** min */ | |
type INPUT_22 = hexToBin<"880086C3E88112"> | |
type INPUT_22_DEBUG = printFirstPacketOut<INPUT_22> | |
// type INPUT_22_OUT = Expect<parseAllPacketsOut<INPUT_22>, "111"> | |
/** max */ | |
type INPUT_23 = hexToBin<"CE00C43D881120"> | |
type INPUT_23_DEBUG = printFirstPacketOut<INPUT_23> | |
// type INPUT_23_OUT = Expect<parseAllPacketsOut<INPUT_23>, "1001"> | |
/** lt */ | |
type INPUT_24 = hexToBin<"D8005AC2A8F0"> | |
type INPUT_24_DEBUG = printFirstPacketOut<INPUT_24> | |
type INPUT_24_OUT = Expect<parseFirstPacketOut<INPUT_24>, "1"> | |
/** gt */ | |
type INPUT_25 = hexToBin<"F600BC2D8F"> | |
type INPUT_25_DEBUG = printFirstPacketOut<INPUT_25> | |
type INPUT_25_OUT = Expect<parseFirstPacketOut<INPUT_25>, "0"> | |
/** eq */ | |
type INPUT_26 = hexToBin<"9C005AC2F8F0"> | |
type INPUT_26_DEBUG = printFirstPacketOut<INPUT_26> | |
type INPUT_26_OUT = Expect<parseFirstPacketOut<INPUT_26>, "0"> | |
/** combo */ | |
type INPUT_27 = hexToBin<"9C0141080250320F1802104A08"> | |
type INPUT_27_DEBUG = printFirstPacketOut<INPUT_27> | |
// type INPUT_27_OUT = Expect<parseFirstPacketOut<INPUT_27>, "1"> | |
/** toggle comment on me to see how long it takes to render */ | |
const RENDER_TESTER = "RENDER_TESTER" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment