2021-07-02 02:20:10 +02:00
|
|
|
|
|
|
|
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
|
2021-07-02 02:22:04 +02:00
|
|
|
worst case and if there is no violation of the condition it will be met for
|
2021-07-02 02:20:10 +02:00
|
|
|
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 load_sets():
|
|
|
|
""" Parse sets from file into a list of lists. Each line contains a list of
|
|
|
|
comma separated integers. We sort the integers in each line. """
|
|
|
|
def line_to_set(line):
|
|
|
|
return sorted(map(int, line.strip().split(",")))
|
|
|
|
|
|
|
|
with open("../txt/e105.txt") as f:
|
|
|
|
return list(map(line_to_set, f))
|
|
|
|
|
|
|
|
|
|
|
|
def euler_105():
|
|
|
|
xs = load_sets()
|
|
|
|
s = 0
|
|
|
|
for i, x in enumerate(xs):
|
|
|
|
if is_special_sum_set(x):
|
|
|
|
s += sum(x)
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
solution = euler_105()
|
|
|
|
print("e105.py: " + str(solution))
|
|
|
|
assert(solution == 73702)
|
|
|
|
|