project-euler/103_special_subset_sums_opt...

47 lines
1.4 KiB
Python

#!/usr/bin/env python3
def test(n, setsums):
newsums = [s+n for s in setsums] + setsums + [n]
if len(newsums) != len(set(newsums)):
return False
return newsums
def search(left, right, length, best, setsums, lor, w): #left to right
if len(left + right) >= length:
if sum(left + right) < best:
#print left+right, sum(left+right)
for i, n in enumerate(left+right):
w[i] = n
return sum(left + right)
return best
hole = length - len(left + right) - 1
minsum = sum(left + right) + (hole*(hole+1))//2 + left[-1]*hole
if lor:
n = max(left[-1]+1, sum(right)-sum(left) + 1)
bound = right[0] - hole
else:
n = left[-1] + hole + 1
bound = best - minsum
if len(right) > 0 and right[0] < bound:
bound = right[0]
while n < bound and n < best - minsum - (n-left[-1])*hole*lor:
newsums = test(n, setsums)
if newsums:
best = search(left + [n]*lor,
[n]*(not lor) + right,
length, best, newsums, not lor, w)
n += 1
return best
def base(length, best):
x = length//2 + length % 2
n = (x + 1 - length%2) * (x-1) + 1
n = 20
w = [0]*length
while n < best - (length-1)*length - n*(length-1):
best = search([n], [], length, best, [n], False, w)
n += 1
return "".join(map(str, w)), best
print(base(7, 500)[0])