def generate_triangle(): t = 0 ts = [[]] i_in_row, max_in_row = 0, 1 for _ in range(1, 500_500 + 1): t = (615_949 * t + 797_807) % 2**20 s = t - 2**19 ts[-1].append(s) i_in_row += 1 if i_in_row == max_in_row: i_in_row = 0 max_in_row += 1 ts.append([]) ts.pop() # remove empty list return ts def array_to_prefix_sum_array(xs): ys = [] current_sum = 0 for x in xs: current_sum += x ys.append(current_sum) return ys def range_sum(prefix_sum, i, j): if i == 0: return prefix_sum[j] else: return prefix_sum[j] - prefix_sum[i - 1] def find_min_triangle(row_i, col_i, sum_triangle): current_sum, min_sum = 0, float("inf") left_i, right_i = col_i, col_i while row_i < len(sum_triangle): current_sum += range_sum(sum_triangle[row_i], left_i, right_i) row_i += 1 right_i += 1 min_sum = min(current_sum, min_sum) return min_sum def euler_150(): triangle = generate_triangle() # triangle = [[15], [-14, -7], [20, -13, -5], [-3, 8, 23, -26], [1, -4 , -5, -18, 5], [-16, 31, 2, 9, 28, 3]] sum_triangle = [array_to_prefix_sum_array(xs) for xs in triangle] min_triangle = float("inf") for row_i in range(len(triangle)): for col_i in range(len(triangle[row_i])): potential_min = find_min_triangle(row_i, col_i, sum_triangle) min_triangle = min(min_triangle, potential_min) return min_triangle if __name__ == "__main__": solution = euler_150() print("e150.py: " + str(solution)) assert solution == -271248680