euler/python/e103.py

84 lines
2.8 KiB
Python

def build_sets(sets, numbers):
""" Sets is a list of two tuples. Each field represents the sum of the two
sets. For each new number, we can add the number to set one, add the
number to set two, or don't add the number to any sets. If there are no
more numbers we return the list so that we can check if there are tuples
that have the same sum. """
if not numbers:
return sets
current_number, numbers = numbers[0], numbers[1:]
new_sets = []
for t in sets:
new_sets.append(t)
new_sets.append((t[0] + current_number, t[1]))
new_sets.append((t[0], t[1] + current_number))
return build_sets(new_sets, numbers)
def is_condition_one_met(s):
tuples = build_sets([(0, 0)], s)
for a, b in tuples:
if a != 0 and b != 0 and a == b:
return False
return True
def is_condition_two_met(s):
""" The second condition says that if |B| > |C| then sum(B) > sum(C). Since
each line is sorted we take the two smallest integers and compare it to the
biggest. Then we take the three smallest integers and compare it to the two
biggest, and so on. Comparing the smallest with the biggest integers is the
worst case and if there is no violation of the condition it will be met for
all other subset pairs. """
half_len = (len(s) - 1) // 2
for i in range(1, half_len + 1):
if not sum(s[:i + 1]) > sum(s[-i:]):
# print(f"{s[:i + 1]=} < {s[-i:]=}")
return False
return True
def is_special_sum_set(s):
""" Check for the two conditions and return True if they are both met. """
if not is_condition_two_met(s):
return False
if not is_condition_one_met(s):
return False
return True
def next_set_heuristic(xs):
""" Calculate the estimated next optimum based on the formul given in the
question. """
b = xs[(len(xs) - 1) // 2]
next_set = [b]
for a in xs:
next_set.append(a + b)
return next_set
def euler_103():
e_max = 50
min_set = None
for a in range(1, e_max):
for b in range(a + 1, e_max):
for c in range(b + 1, e_max):
for d in range(c + 1, e_max):
for e in range(d + 1, e_max):
for f in range(e + 1, e_max):
for g in range(e + 1, e_max):
s = [a, b, c, d, e, f, g,]
if is_special_sum_set(s):
s_sum = sum(s)
if min_set is None or s_sum < sum(min_set):
min_set = s
return int("".join(map(str, min_set)))
if __name__ == "__main__":
solution = euler_103()
print("e103.py: " + str(solution))
assert(solution == 20313839404245)