2015 day 24.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Mikaël Capelle 2024-12-14 15:20:07 +01:00
parent 8969ea895f
commit 323f810fcd
3 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,88 @@
from typing import Any, Iterator, TypeAlias
from ..base import BaseSolver
TupleOfInts: TypeAlias = tuple[int, ...]
def check_n_groups(
target: int, groups: tuple[TupleOfInts, ...], numbers: TupleOfInts
) -> bool:
n_groups = len(groups)
groups_s = tuple(sum(group) for group in groups)
if all(target == group_s for group_s in groups_s):
return not numbers
if not numbers:
return False
head, *tail_l = numbers
tail, tail_s = tuple(tail_l), sum(tail_l)
return any(
groups_s[i] + head <= target
and sum(groups_s[j] for j in range(len(groups)) if i != j) + tail_s
>= (n_groups - 1) * target
and check_n_groups(
target, groups[:i] + ((groups[i] + (head,)),) + groups[i + 1 :], tail
)
for i in range(len(groups))
)
def enumerate_single_subset(
target: int, numbers: TupleOfInts
) -> Iterator[tuple[int, TupleOfInts, TupleOfInts]]:
"""
Enumerate subset of numbers whose sum equals target.
Subset are enumerated in increasing order of length, then product (quantum value).
Args:
target: Target for the sum of the subset.
numbers: Tuple of integers to find the subset from.
Returns:
A generator (quantum, subset, remaining) where subset if the subset of numbers
whose sum equals target, quantum the product of the subset, and remaining the
remaining numbers.
"""
groups: list[tuple[int, TupleOfInts, TupleOfInts]] = [(1, (), numbers)]
for _ in range(len(numbers)):
new_groups: list[tuple[int, TupleOfInts, TupleOfInts]] = []
for g_quantum, group, remaining in groups:
sg = sum(group)
for i in range(len(remaining)):
if group and remaining[i] <= group[-1]:
continue
uv = remaining[:i] + remaining[i + 1 :]
kv = g_quantum * remaining[i], group + (remaining[i],), uv
if sg + remaining[i] == target:
yield kv
elif sg + remaining[i] < target:
new_groups.append(kv)
groups = new_groups
def find_min_quantum(numbers: tuple[int, ...], n_groups: int):
return next(
g_quantum
for g_quantum, group_1v2, group_234v2 in enumerate_single_subset(
sum(numbers) // n_groups, numbers
)
if check_n_groups(sum(group_1v2), ((),) * (n_groups - 1), group_234v2)
)
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
numbers = tuple(map(int, input.split()))
yield find_min_quantum(numbers, 3)
yield find_min_quantum(numbers, 4)

View File

@ -0,0 +1,28 @@
1
3
5
11
13
17
19
23
29
31
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
113

View File

@ -0,0 +1,10 @@
1
2
3
4
5
7
8
9
10
11