Solve problem 149.
parent
a07f34075b
commit
cd2e933afe
|
@ -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
|
Loading…
Reference in New Issue