N times program for the N-th number
Perl 5 -p
, generates Perl 5 -p
, overhead 19 17 13
-1 thanks to @Dom Hastings
The score for one input will be length of the input + 13
. Can obviously be improved by generating self-decompressing programs for larger inputs, but I won't bother.
Give the input array separated by commas on one line on STDIN.
#!/usr/bin/perl -p
chomp;$_="}{\$_=($_)[\$%++]"
Try it online!
Run the output concatenated n
times with no input (e.g. redirect from /dev/null)
Sample way to run it for input 2,6,4,7
and the resulting program repeated 4 times:
perl -p '}{$_=(3,6,4,7)[$%++]}{$_=(3,6,4,7)[$%++]}{$_=(3,6,4,7)[$%++]}{$_=(3,6,4,7)[$%++]' < /dev/null
Try it online!
If you don't like the resulting program trying to read from STDIN use this version with overhead 17:
#!/usr/bin/perl -p
chomp;$_="1/!say+($_)[\$-++],"
Try it online!
Sample way to run it for input 2,6,4,7
and the resulting program repeated 4 times:
perl -E '1/!say+(2,6,4,7)[$-++],1/!say+(2,6,4,7)[$-++],1/!say+(2,6,4,7)[$-++],1/!say+(2,6,4,7)[$-++],'
Try it online!
This version crashes after printing the required output
Python 3, generates Stax
This uses a variety of strategies. Most strategies only apply under certain conditions, but there's one fallback strategy that is always usable. At the end, the smallest candidate program is selected.
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)
Try it online!
Update: Validation It will be time consuming to execute each multiplicity of each program separately. It's possible to run them all at the same time. In order to do this, a small piece of code must be used. It's responsible for a few things.
Do implicit output if any. Normally, at the end of a stax program, the top of stack is printed if there has been no other output. When running multiple programs in the same source file, this must be done explicitly.
Clear both stacks.
Reset registers. For these programs only the x register is used.
This boilerplate should be applied after every individual program to be executed.
|d{P}{zP}?0XLd
For example, the input [5,2,7,3]
produces the stax program 3527E|X@
. All four multiplicities can be tested at once.
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
Try it online!
In this way, it's possible to test all the multiplicities of all the program in the same run, assuming nothing breaks. It would probably be the largest stax program ever executed if all 500 are done.
05AB1E, generates 05AB1E
¸»“"ÿ"#.g<“ƵƒçJ
Try it online!
The generated program for the input [5,17,7,13,2]
is "5 17 7 13 2"#.g<è
.
Test suite for [5,17,7,13,2]
The length of the generated program is len(input) + 5