68 lines
1.6 KiB
Python
68 lines
1.6 KiB
Python
from itertools import permutations
|
|
from string import ascii_uppercase
|
|
from functools import cache
|
|
|
|
|
|
@cache
|
|
def count(xst: tuple) -> int:
|
|
expected = 0
|
|
for i in range(len(xst)):
|
|
if xst[i] == expected:
|
|
expected += 1
|
|
else:
|
|
# Carriage i is not the correct one
|
|
break
|
|
else:
|
|
# Train is fully sorted
|
|
return 0
|
|
|
|
# Find out where Simple Simon would split next; there are two cases.
|
|
xs = list(xst)
|
|
|
|
# If the next expected carriage is at the end of the list, Simon can just
|
|
# reverse from where we currently are.
|
|
if xs[-1] == expected:
|
|
xs[i:] = xs[i:][::-1]
|
|
return 1 + count(tuple(xs))
|
|
|
|
for j in range(i + 1, len(xst)):
|
|
if xst[j] == expected:
|
|
xs[j:] = xs[j:][::-1]
|
|
return 1 + count(tuple(xs))
|
|
|
|
assert False, "should not get here"
|
|
|
|
|
|
def get_maximix_arrangements(n: int) -> list:
|
|
x = [i for i in range(n)]
|
|
xs = permutations(x)
|
|
max_xs = []
|
|
max_xs_count = 0
|
|
for x in xs:
|
|
if x[0] == 0 or x[-1] == 0:
|
|
continue
|
|
c = count(x)
|
|
if c == max_xs_count:
|
|
max_xs.append(x)
|
|
elif c > max_xs_count:
|
|
max_xs = [x]
|
|
max_xs_count = c
|
|
return sorted(map(to_ascii, max_xs))
|
|
|
|
|
|
def to_ascii(x) -> str:
|
|
return "".join([ascii_uppercase[d] for d in x])
|
|
|
|
|
|
def euler_336():
|
|
xs = get_maximix_arrangements(6)
|
|
assert len(xs) == 24
|
|
assert xs[10 - 1] == "DFAECB"
|
|
return get_maximix_arrangements(11)[2011 - 1]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
solution = euler_336()
|
|
print(f"e336.py: {solution}")
|
|
assert solution == "CAGBIHEFJDK"
|