这使用了多种策略。大多数策略仅在特定条件下适用,但是有一种后备策略始终可用。最后,选择最小的候选程序。
from functools import reduce
from math import sqrt
symbols = " !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}"
def uncycle(arr):
for size in range(1, len(arr)):
if all(e == arr[i % size] for (i, e) in enumerate(arr)):
return arr[:size]
return arr
def constant(val):
return "A" if val == 10 else str(val)
def shift(val):
if not val: return ""
return constant(abs(val)) + "+-"[val < 0]
def encode(a, offsetMode):
result = "";
if offsetMode:
for i in range(len(a) - 1, 0, -1):
a[i] -= a[i - 1]
for i in range(len(a)):
parts = []
signBit = (a[i] < 0) * 2
continuing = (offsetMode and i == len(a) - 1) * 1
remain = abs(a[i])
while remain > 22:
parts.insert(0, remain % 46 * 2 + continuing);
remain //= 46
continuing = 1
parts.insert(0, remain * 4 + signBit + continuing)
result += "".join(symbols[p] for p in parts)
return result
def cram(arr):
flat = encode(arr, False)
offset = encode(arr, True)
return offset if len(offset) < len(flat) else flat;
def issquare(num):
root = int(sqrt(num))
return root * root == num
def isgeometric(arr):
r = arr[0]
return all(r ** (i + 1) == e for (i,e) in enumerate(arr))
def generateProgram(arr):
candidates = []
rotated = uncycle(arr)
rotated = rotated[-1:] + rotated[:-1]
deltas = [b - a for a,b in zip(arr, arr[1:])]
# single constant strategy
if len(arr) == 1:
candidates.append(constant(arr[0]))
# repeated constant
elif len(set(arr)) == 1:
num = arr[0]
if num == 10: candidates.append("A")
if num % 2 == 0: candidates.append(constant(num // 2) + "H")
if issquare(num): candidates.append(str(int(sqrt(num))) + "J")
candidates.append(constant(num - 1) + "^")
# repdigit
if len(arr) == 2 and 10 < arr[1] == arr[0] * 11 < 100:
candidates.append(str(arr[0]) + "p")
# single digits
if max(arr) < 10:
candidates.append("".join(map(str, rotated)) + "E|X@")
# max 10
if max(arr) == 10 and rotated[0] != 1:
candidates.append("".join(str(e - 1) for e in rotated) + "E|X@^")
fns = [
("", lambda x: x),
("H", lambda x: 2 * x),
("^", lambda x: x + 1),
("J", lambda x: x * x),
("Hv", lambda x: 2 * x - 1),
("H^", lambda x: 2 * x + 1),
("^H", lambda x: 2 * x + 2),
("HJ", lambda x: 4 * x * x),
("JH", lambda x: 2 * x * x),
(":T", lambda x: x * (x + 1) / 2),
("|F", lambda x: reduce(lambda a, b: a*b, range(1, x+1))),
("J^", lambda x: x * x + 1),
("^J", lambda x: x * x + 2 * x + 1),
]
for (stax, fn) in fns:
if all(fn(i + 1) == e for (i,e) in enumerate(arr)):
candidates.append("|X" + stax)
# fixed delta
if len(set(deltas)) == 1:
delta = deltas[0]
start = arr[0] - delta
if start == 0:
candidates.append(shift(delta))
if delta == 1:
candidates.append("|X" + shift(start))
elif delta == -1:
candidates.append("|x" + shift(start))
elif delta > 1:
candidates.append("|X" + constant(delta) + "*" + shift(start))
elif delta < -1:
candidates.append("|x" + constant(-delta) + "*" + shift(start))
# geometric series
if isgeometric(arr):
candidates.append(constant(arr[0]) + "*")
# prefix
if len(arr) == 2 and arr[1] // 10 == arr[0] < 10:
candidates.append("." + str(arr[1]) + "|X(")
# suffix
if len(arr) == 2 and arr[0] % 10 == arr[1] < 10:
candidates.append("." + "".join(map(str, arr)) + "|X)")
# uncycled cram
candidates.append('"' + cram(rotated) + '"!|X@')
candidates.sort(key=len)
return candidates[0]
while True:
arr = eval(input())
prog = generateProgram(arr)
print(prog)
在线尝试!
更新:验证 分别执行每个程序的每个多重性将很耗时。可以同时运行它们。为此,必须使用一小段代码。它负责一些事情。
进行隐式输出(如果有)。通常,在stax程序的末尾,如果没有其他输出,则打印堆栈的顶部。在同一个源文件中运行多个程序时,必须明确地执行此操作。
清除两个堆栈。
重置寄存器。对于这些程序,仅使用x寄存器。
该样板应该在每个要执行的程序之后应用。
|d{P}{zP}?0XLd
例如,输入[5,2,7,3]
产生stax program 3527E|X@
。可以同时测试所有四个多重性。
3527E|X@
|d{P}{zP}?0XLd
3527E|X@3527E|X@
|d{P}{zP}?0XLd
3527E|X@3527E|X@3527E|X@
|d{P}{zP}?0XLd
3527E|X@3527E|X@3527E|X@3527E|X@
|d{P}{zP}?0XLd
在线尝试!
这样,假设没有任何中断,就可以在同一运行中测试所有程序的所有多重性。如果全部完成500个,它可能是有史以来执行的最大的stax程序。