Solve problem 149.

main
felixm 2024-05-05 11:38:36 -04:00
parent a07f34075b
commit cd2e933afe
1 changed files with 105 additions and 0 deletions

105
python/e149.py Normal file
View File

@ -0,0 +1,105 @@
def gen_numbers():
numbers = []
for k in range(1, 56):
n = (100_003 - 200_003*k + 300_007*k**3) % 1_000_000 - 500_000
numbers.append(n)
for k in range(56, 2000 * 2000 + 1):
n = (numbers[k-24-1] + numbers[k-55-1] + 1_000_000) % 1_000_000 - 500_000
numbers.append(n)
return numbers
def split(xs, n):
return [xs[i:i + n] for i in range(0, len(xs), n)]
def diags(rows):
n = len(rows)
diags = []
for col_i in range(-n + 1, n):
d = []
for row_i in range(n):
if col_i >= 0 and col_i < n:
d.append(rows[row_i][col_i])
col_i += 1
diags.append(d)
return diags
def anti_diags(rows):
n = len(rows)
diags = []
for col_i in range(-n + 1, n):
d = []
for row_i in range(n - 1, -1, -1):
if col_i >= 0 and col_i < n:
d.append(rows[row_i][col_i])
col_i += 1
diags.append(d)
return diags
def shorten(xs):
r = []
i = 0
while i < len(xs):
r.append(0)
if xs[i] < 0:
while i < len(xs) and xs[i] < 0:
r[-1] += xs[i]
i += 1
else:
while i < len(xs) and xs[i] >= 0:
r[-1] += xs[i]
i += 1
if r[0] <= 0:
r = r[1:]
if r and r[-1] <= 0:
r = r[:-1]
return r
def max_subarray(numbers):
"""Find the largest sum of any contiguous subarray.
https://en.wikipedia.org/wiki/Maximum_subarray_problem
Emberassing that I didn't come up with that myself...
"""
best_sum = -10**12
current_sum = 0
for x in numbers:
current_sum = max(x, current_sum + x)
best_sum = max(best_sum, current_sum)
return best_sum
def max_subarray_naiv(xs):
""" Naiv implementation in O(n^3) or something. """
r = 0
xs = shorten(xs)
for width in range(1, len(xs) + 1, 2):
for i in range(len(xs)):
r = max(r, sum(xs[i:i+width]))
return r
def euler_149():
ns = gen_numbers()
assert ns[10-1] == -393027
assert ns[100-1] == 86613
rows = split(ns, 2000)
cols = list(map(list, zip(*rows)))
r = 0
for elems in [rows, cols, diags(rows), anti_diags(rows)]:
for xs in elems:
r = max(max_subarray(xs), r)
return r
if __name__ == "__main__":
solution = euler_149()
print("e149.py: " + str(solution))
assert solution == 52852124