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"