Skip to content

Instantly share code, notes, and snippets.

@mochaaP
Created December 3, 2023 09:41
Show Gist options
  • Save mochaaP/d1b936b47355638209e2734eb3ea5f74 to your computer and use it in GitHub Desktop.
Save mochaaP/d1b936b47355638209e2734eb3ea5f74 to your computer and use it in GitHub Desktop.
advent of code 2023 done wrong
module AoC2023.Day01 where
import Data.Char (isDigit)
main :: IO ()
main = do
res <- readFile "input/1.txt"
let i = lines res
-- part one
print
$ ( sum
. map
( \line ->
let n = filter isDigit line
in read [head n, last n] :: Int
)
)
i
-- part two
print
$ ( sum
. map
asNum
)
i
asNum :: String -> Int
asNum x = read [numl "" x, numr "" x] :: Int
numl :: String -> String -> Char
numl "" (x : xs)
| isDigit x = x
| otherwise = numl [x] xs
numl acc (x : xs)
| acc == "one" = '1'
| acc == "two" = '2'
| acc == "three" = '3'
| acc == "four" = '4'
| acc == "five" = '5'
| acc == "six" = '6'
| acc == "seven" = '7'
| acc == "eight" = '8'
| acc == "nine" = '9'
| isDigit x = x
| otherwise = numl (acc ++ [x]) xs
numr :: String -> String -> Char
numr "" x
| isDigit $ last x = last x
| otherwise = numr [last x] $ init x
numr acc x
| acc == "one" = '1'
| acc == "two" = '2'
| acc == "three" = '3'
| acc == "four" = '4'
| acc == "five" = '5'
| acc == "six" = '6'
| acc == "seven" = '7'
| acc == "eight" = '8'
| acc == "nine" = '9'
| isDigit $ last x = last x
| otherwise = numr (last x : acc) (init x)
namespace Multiply {
type Reverse<A extends string | number | bigint> =
`${A}` extends `${infer AH}${infer AT}` ? `${Reverse<AT>}${AH}` : "";
type DigsNext = {
"0": "1";
"1": "2";
"2": "3";
"3": "4";
"4": "5";
"5": "6";
"6": "7";
"7": "8";
"8": "9";
};
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 & keyof DigsNext]}${AT}`
: "1";
type SubOne<A> = A extends `${infer AH}${infer AT}`
? AH extends "0"
? `9${SubOne<AT>}`
: `${DigsPrev[AH & keyof DigsPrev]}${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 extends string, B extends string, 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;
export type Multiply<
A extends string | number | bigint,
B extends string | number | bigint,
> = Reverse<Mul<Reverse<A>, Reverse<B>>>;
}
namespace Sum {
type Or<left extends boolean, right extends boolean> = left extends true
? true
: right extends true
? true
: false;
type CoalesceToString<n extends string | number | bigint> = n extends string
? n
: `${n}`;
type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type SubOneFromDigit<digit extends Digit> = digit extends "1"
? "0"
: digit extends "2"
? "1"
: digit extends "3"
? "2"
: digit extends "4"
? "3"
: digit extends "5"
? "4"
: digit extends "6"
? "5"
: digit extends "7"
? "6"
: digit extends "8"
? "7"
: digit extends "9"
? "8"
: digit extends "10"
? "9"
: never;
type AddOneToDigit<digit extends Digit> = digit extends "0"
? { result: "1"; carry: false }
: digit extends "1"
? { result: "2"; carry: false }
: digit extends "2"
? { result: "3"; carry: false }
: digit extends "3"
? { result: "4"; carry: false }
: digit extends "4"
? { result: "5"; carry: false }
: digit extends "5"
? { result: "6"; carry: false }
: digit extends "6"
? { result: "7"; carry: false }
: digit extends "7"
? { result: "8"; carry: false }
: digit extends "8"
? { result: "9"; carry: false }
: digit extends "9"
? { result: "0"; carry: true }
: never;
type SingleDigitSumResult<result extends Digit, carry extends boolean> = {
result: result;
carry: carry;
};
type SumSingleDigits<
left extends Digit,
right extends Digit,
carryIn extends boolean = false,
carryOut extends boolean = false,
> = carryIn extends true
? AddOneToDigit<left> extends SingleDigitSumResult<
infer leftIncremented,
infer carryOutFromIncrement
>
? SumSingleDigits<leftIncremented, right, false, carryOutFromIncrement>
: never
: right extends "0"
? { result: left; carry: carryOut }
: AddOneToDigit<left> extends SingleDigitSumResult<
infer leftIncremented,
infer carryOutFromIncrement
>
? SumSingleDigits<
leftIncremented,
SubOneFromDigit<right>,
false,
Or<carryOut, carryOutFromIncrement>
>
: never;
type RightMostDigitResult<rest extends string, digit extends Digit> = {
rest: rest;
digit: digit;
};
type RightMostDigit<s extends string> = s extends `${infer rest}${Digit}`
? s extends `${rest}${infer digit}`
? { rest: rest; digit: digit }
: never
: never;
type SumStrings<
left extends string,
right extends string,
accumulatedResultDigits extends string = "",
carry extends boolean = false,
> = "" extends left
? // Left is empty
"" extends right
? // Right is empty
carry extends true
? `1${accumulatedResultDigits}`
: accumulatedResultDigits
: // Right has value
RightMostDigit<right> extends RightMostDigitResult<
infer remainingRight,
infer rightDigit
>
? SumSingleDigits<"0", rightDigit, carry> extends SingleDigitSumResult<
infer resultDigit,
infer resultCarry
>
? SumStrings<
"",
remainingRight,
`${resultDigit}${accumulatedResultDigits}`,
resultCarry
>
: never
: never
: // Left has value
"" extends right
? // Right has no value
RightMostDigit<left> extends RightMostDigitResult<
infer remainingLeft,
infer leftDigit
>
? SumSingleDigits<"0", leftDigit, carry> extends SingleDigitSumResult<
infer resultDigit,
infer resultCarry
>
? SumStrings<
remainingLeft,
"",
`${resultDigit}${accumulatedResultDigits}`,
resultCarry
>
: never
: never
: // Right has value
RightMostDigit<left> extends RightMostDigitResult<
infer remainingLeft,
infer leftDigit
>
? RightMostDigit<right> extends RightMostDigitResult<
infer remainingRight,
infer rightDigit
>
? SumSingleDigits<
leftDigit,
rightDigit,
carry
> extends SingleDigitSumResult<infer resultDigit, infer resultCarry>
? SumStrings<
remainingLeft,
remainingRight,
`${resultDigit}${accumulatedResultDigits}`,
resultCarry
>
: never
: never
: never;
export type Sum<
left extends string | number | bigint,
right extends string | number | bigint,
> = SumStrings<CoalesceToString<left>, CoalesceToString<right>>;
}
namespace Comparison {
export type Lower = -1;
export type Equal = 0;
export type Greater = 1;
export type Comparator<
A extends number | string,
B extends number | string,
> = ComparePositives<`${A}`, `${B}`>;
// Compares two positive long numbers
type ComparePositives<
A extends string,
B extends string,
ByLength = CompareByLength<A, B>,
> = ByLength extends Comparison.Equal ? CompareByDigits<A, B> : ByLength;
// Compares two strings by length
type CompareByLength<
A extends string,
B extends string,
> = A extends `${infer _}${infer AR}`
? B extends `${infer _}${infer BR}`
? CompareByLength<AR, BR>
: Comparison.Greater
: B extends `${infer _}${infer __}`
? Comparison.Lower
: Comparison.Equal;
// Compares two positive long numbers of the same length
type CompareByDigits<
A extends string,
B extends string,
> = `${A}|${B}` extends `${infer AF}${infer AR}|${infer BF}${infer BR}`
? CompareDigits<AF, BF> extends Comparison.Equal
? CompareByDigits<AR, BR>
: CompareDigits<AF, BF>
: Comparison.Equal;
// Compares two digits
type CompareDigits<A extends string, B extends string> = A extends B
? Comparison.Equal
: "0123456789" extends `${string}${A}${string}${B}${string}`
? Comparison.Lower
: Comparison.Greater;
}
import Input from "./input/2.ts";
type Color = "red" | "green" | "blue";
type AllTrySatisfied<T extends Try[]> = T extends [infer A extends Try]
? Satisfies<A>
: T extends [infer A extends Try, ...infer Rest extends Try[]]
? Satisfies<A> & AllTrySatisfied<Rest>
: never;
type Attempt<T extends string> = T extends `${infer A}; ${infer Rest}`
? [Count<A>, ...Attempt<Rest>]
: T extends `${infer A}`
? [Count<A>]
: never;
type Count<T extends string> =
T extends `${infer N extends number} ${infer K extends Color}, ${infer Rest}`
? { [_ in K]: N } & { [R in keyof Count<Rest>]: Count<Rest>[R] }
: T extends `${infer N extends number} ${infer K extends Color}`
? { [_ in K]: N }
: never;
type MergedGame<T extends string> = T extends `${number}: ${infer F}`
? MergeAttempt<Attempt<F>> extends {
red: infer R extends number;
green: infer G extends number;
blue: infer B extends number;
}
? Multiply.Multiply<
Multiply.Multiply<R, G>,
B
> extends `${infer N extends number}`
? N
: never
: 0
: never;
type GameSatisfied<T extends string> =
T extends `${infer I extends number}: ${infer F}`
? AllTrySatisfied<Attempt<F>> extends never
? 0
: I
: never;
type Satisfies<T extends Try> = (T["red"] extends number
? Comparison.Comparator<T["red"], 12> extends
| Comparison.Equal
| Comparison.Lower
? true
: false
: true) &
(T["green"] extends number
? Comparison.Comparator<T["green"], 13> extends
| Comparison.Equal
| Comparison.Lower
? true
: false
: true) &
(T["blue"] extends number
? Comparison.Comparator<T["blue"], 14> extends
| Comparison.Equal
| Comparison.Lower
? true
: false
: true);
type MergeAttempt<T extends Try[]> = T extends [infer x extends Try]
? x
: T extends [infer x extends Try, ...infer xs extends Try[]]
? MergeTry<x, MergeAttempt<xs>>
: never;
type MergeTry<L extends Try, R extends Try> = {
red: L["red"] extends number
? R["red"] extends number
? Comparison.Comparator<L["red"], R["red"]> extends
| Comparison.Equal
| Comparison.Greater
? L["red"]
: R["red"]
: L["red"]
: R["red"];
green: L["green"] extends number
? R["green"] extends number
? Comparison.Comparator<L["green"], R["green"]> extends
| Comparison.Equal
| Comparison.Greater
? L["green"]
: R["green"]
: L["green"]
: R["green"];
blue: L["blue"] extends number
? R["blue"] extends number
? Comparison.Comparator<L["blue"], R["blue"]> extends
| Comparison.Equal
| Comparison.Greater
? L["blue"]
: R["blue"]
: L["blue"]
: R["blue"];
};
type Try = { [_ in Color]?: number };
type MergedTry<Line extends string> =
Line extends `Game ${infer G}\nGame ${infer G_}\nGame ${infer G__}\n${infer More}`
? [MergedGame<G>, MergedGame<G_>, MergedGame<G__>, ...MergedTry<More>]
: Line extends `Game ${infer G}\nGame ${infer G_}\n${infer More}`
? [MergedGame<G>, MergedGame<G_>, ...MergedTry<More>]
: Line extends `Game ${infer G}\n${infer More}`
? [MergedGame<G>, ...MergedTry<More>]
: Line extends `Game ${infer G}`
? [MergedGame<G>]
: never;
type Satisfied<Line extends string> =
Line extends `Game ${infer G}\nGame ${infer G_}\nGame ${infer G__}\n${infer More}`
? [
GameSatisfied<G>,
GameSatisfied<G_>,
GameSatisfied<G__>,
...Satisfied<More>,
]
: Line extends `Game ${infer G}\nGame ${infer G_}\n${infer More}`
? [GameSatisfied<G>, GameSatisfied<G_>, ...Satisfied<More>]
: Line extends `Game ${infer G}\n${infer More}`
? [GameSatisfied<G>, ...Satisfied<More>]
: Line extends `Game ${infer G}`
? [GameSatisfied<G>]
: never;
type Trys = MergedTry<typeof Input>;
type Sums = Satisfied<typeof Input>;
type CalcSum<T extends number[]> = T extends [infer Con extends number]
? Con
: T extends [infer Con extends number, ...infer Rest extends number[]]
? Sum.Sum<Con, CalcSum<Rest>> extends `${infer N extends number}`
? N
: never
: T extends [
infer Con extends number,
infer Cons extends number,
...infer Rest extends number[],
]
? Sum.Sum<
Sum.Sum<Con, Cons>,
CalcSum<Rest>
> extends `${infer N extends number}`
? N
: never
: never;
type Chunk<
T extends unknown[],
N extends number,
Swap extends unknown[] = [],
> = Swap["length"] extends N
? [Swap, ...Chunk<T, N>]
: T extends [infer K, ...infer L]
? Chunk<L, N, [...Swap, K]>
: Swap extends []
? Swap
: [Swap];
type ChunkedCalcSum<T extends number[][]> = T extends [
infer Con extends number[],
]
? CalcSum<Con>
: T extends [infer Con extends number[], ...infer Rest extends number[][]]
? Sum.Sum<
CalcSum<Con>,
ChunkedCalcSum<Rest>
> extends `${infer N extends number}`
? N
: never
: never;
type ChunkedSum = Chunk<Sums, 10>;
type ChunkedTrys = Chunk<Trys, 10>;
export type Solution1 = ChunkedCalcSum<ChunkedSum>;
export type Solution2 = ChunkedCalcSum<ChunkedTrys>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment