diff --git a/python/e103.py b/python/e103.py new file mode 100644 index 0000000..fd0f20e --- /dev/null +++ b/python/e103.py @@ -0,0 +1,83 @@ + +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) +