solving yelp ratings at the type level
i swear im going to actually do a writeup on this in 2 days (remind me)
problem: https://programmingpuzzles.com/puzzles/012-the-perfect-menu
type TupleN<N extends number, Acc extends any[] = []> =
Acc["length"] extends N ? Acc : TupleN<N, [...Acc, 0]>;
declare namespace Parsing {
type Num<S> =
S extends `${infer N extends number}` ? N : never;
type CommaSep<S extends string> =
S extends `${infer A},${infer Rest}` ?
[A, ...CommaSep<Rest>]
: S extends "" ? []
: [S];
type ParseLines<S> =
S extends `${infer X}\n${infer XS}` ?
[X, ...ParseLines<XS>]
: [];
type ParseLine<Line extends string> =
CommaSep<Line> extends (
[...infer Dishes extends string[], infer N]
) ?
[
Dishes,
[
...TupleN<Num<N>>,
...TupleN<Num<N>>,
...TupleN<Num<N>>,
],
]
: never;
type ParseDishes<
Str extends string,
Lines extends string[] = ParseLines<Str>,
> = {
[K in keyof Lines]: CommaSep<Lines[K]> extends (
[...infer Rest, any]
) ?
Rest
: never;
};
}
declare namespace Comb {
type Tup = 0[];
type PossibleValue = 1 | 2 | 3 | 4 | 5;
type Triple = [Tup, Tup, Tup];
type ChooseA<N extends Tup, A extends Tup> =
A["length"] extends PossibleValue ?
[...ChooseB<N, A, [0]>, ...ChooseA<N, [...A, 0]>]
: [];
type ChooseB<
N extends Tup,
A extends Tup,
B extends Tup,
> =
B["length"] extends PossibleValue ?
ChooseB<N, A, [...B, 0]> extends (
infer Rest extends any[]
) ?
N extends [...A, ...B, ...infer C extends Tup] ?
C["length"] extends PossibleValue ?
[
[A["length"], B["length"], C["length"]],
...Rest,
]
: Rest
: Rest
: never
: [];
export type Splits3<N extends Tup> = ChooseA<N, [0]>;
}
type Clean<X> = {
[K in keyof X]: X[K];
} & {};
declare namespace Dict {
type MakeDict<
Dishes extends string[],
Values extends any[],
> = Clean<
{
[K in Dishes[0]]: Values[0];
} & {
[K in Dishes[1]]: Values[1];
} & {
[K in Dishes[2]]: Values[2];
}
>;
type DictCombinations<
Dishes extends string[],
Values extends any[],
Combinations extends any[] = Comb.Splits3<Values>,
> = {
[K in keyof Combinations]: MakeDict<
Dishes,
Combinations[K]
>;
};
}
type Search<Lists extends any[][], Choice = unknown> =
Lists["length"] extends 0 ? Choice
: Lists extends (
[
infer First extends any[],
...infer Rest extends any[][],
]
) ?
TryEach<First, Rest, Choice>
: never;
type TryEach<
List extends any[],
RestLists extends any[][],
Choice extends any,
> =
List["length"] extends 0 ? never
: List extends (
[infer X extends object, ...infer Xs extends object[]]
) ?
Search<RestLists, Choice & X> extends infer R ?
[R] extends [never] ?
TryEach<Xs, RestLists, Choice>
: R
: never
: never;
type Solution<
Input,
Lines extends any[] = Parsing.ParseLines<Input>,
ReviewLines extends any[] = {
[K in keyof Lines]: Parsing.ParseLine<
Lines[K]
> extends (
[
infer Dishes extends any[],
infer Value extends any[],
]
) ?
Dict.DictCombinations<Dishes, Value>
: never;
},
> = Clean<Search<ReviewLines>>;
type Res = Solution<`Gazpaco,Ragu,Tiramisu,3
Gazpaco,Trippa alla Romana,Panettone,1
Gazpaco,Ragu,Panettone,2
Caprese,Trippa alla Romana,Panettone,2
`>;