euler/python/e105.py

75 lines
2.3 KiB
Python
Raw Normal View History

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
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)