输出基本证明


21

背景

在某些可能的将来,世界会将其数字系统从十进制(以10 b10为基数或)转换为其他基数(二进制b2,八进制b8,十六进制b16甚至一元b1,在这种情况下,我们很费力!)。因此,为应对这一可能改变世界的事件,您决定对所有程序进行基础验证。这可以通过仅将0s和1s与运算符结合使用以替换现有的数字常量来完成。

但是,只有一个问题:您需要更改大量程序,而将每个数字手动转换为表达式将需要数周!因此,您决定编写一个程序(或函数)来为您确定应替换每个数字的表达式。

输入项

输入将为正整数。您的代码必须能够处理最多1000个整数。

(如果您的代码支持小数和/或负输入,请参阅下面的评分。)

输出量

您的代码必须以至少一种语言输出计算结果为表达式的表达式。这可以是任何语言;它不一定要与您编写的程序或函数相同。此外,此表达式也不必是完整的程序或函数。

为了清楚起见,输出可能包含以下任何操作:

  • 递增/递减
  • 加/加
  • 减去/取反
  • 乘/双(仅在不直接涉及数字的情况下2!)
  • 除法/取模
  • 指数/对数
  • 平方/平方(再次,仅当这些不直接涉及数字时2!)
  • 按位运算(bOR,bAND,bNOT,bXOR,移位)
  • 设置/获取变量
  • 堆栈操作

你可能使用eval()或输出的任何类似的功能。您也可能在输出中不使用执行上述功能以外的任何功能的功能。

哦,还有另一件事:由于我们希望输出在尽可能多的底数内有效,因此它可能包含的唯一数字常量是0and 110除非(ten)这样的数字是不允许的,除非该语言将其解释为a 1和a 0。也不允许使用字符串包含数字,就像使用CJam的A- K(代表10- 20)这样的字符一样,也是不允许的。

测试用例

(所有输出均使用JavaScript,但可以使用其他语言。)

输入1:

2

可能的输出1:

1+1

输入2:

13

可能的输出2:

(a=1+1+1)*a+a+1

输入3:

60

可能的输出3:

(b=(a=1+1+1+1)*a)*a-a

输入4:

777

可能的输出4:

(c=(b=((a=1+1+1+1)*a-a+1)*a)*a+b)+c+c-a+1

输入5:

1000

可能的输出5:

Math.pow((a=1+1+1)*a+1,a)

计分

这项挑战的目标是尽可能缩短代码的输出。您的分数将通过以下方式计算:

  • 基本分数: 1到1000之间的整数的所有输出的平均字节数。

  • 十进制分数:如果您的代码至少支持3个小数位,则这是从开始到0.001结束的数字序列所有输出的平均字节数,每次1000增加1.0010.001, 1.002, 2.003...998.999, 1000.000然后从该分数中扣除50%。

  • 负分数:如果您的代码支持负数和零,则这是从-1000到的所有整数的输出的平均字节数0。然后从该分数中扣除10%。

(最简单的计算方法可能是在程序/函数内部循环。)

您的最终分数是上述任何一个公式的平均值。

如果输出是不确定的(即有些随机;具有相同输入的多次运行会产生多个唯一输出),则每个输入的分数取决于我CPU上十次运行中的最大输出。

另外,由于您不知道将来的计算机数据将多么宝贵,因此生成器代码的字节数必须小于512字节。

宣布两周内(9月30日)最低分的获胜者。祝贺您的获胜者 @ThomasKwa


排行榜

为确保您的答案正确显示,请从以下标题开始:

# Language name/Other language name, X points

X您的答案分数在哪里。例:

# CJam/Pyth, 25.38 points

如果您有任何疑问或建议,请告诉我。祝好运!


我可以使用保留变量0还是1默认变量?
丹尼斯2015年

@Dennis我认为没有任何问题,所以继续吧!
ETHproductions 2015年

我假设我无法在以2为基数和默认基数之间进行基本转换。
蓝色

@muddyfish不,在输出中不允许进行基本转换。
ETHproductions 2015年

我猜我们也不允许使用类似的东西Integer.parseInt("1000", 1+1+1+1+1+1+1+1+1+1)?我敢肯定,parseInt只使用允许的操作;-)
圣保罗Ebermann

Answers:


10

Python / Zilog Z80机器代码,11.653 11.488

import math,numpy as np
def R(n):
    if n==0:return []
    if n<0:return -R(-n)
    e=int(math.log(n,2))
    if n >= 5/3 * 2**e:
        return np.append(2**(e+1),-R(2**(e+1)-n))
    return np.append(2**e,R(n-2**e))

def strR(n):
    b = R(n)
    s = ""
    if n==0:return s
    e=max(abs(b))
    while e:
        if e in b:s+="#"
        elif -e in b:s+="+"
        s+=")"
        e//=2
    return s[:-1]

奖励:负数。

假定hl寄存器对最初为0,并在中返回结果hl

仅使用以下三个指令:

ASCII   Hex    Instruction
--------------------------
#       23     inc hl
)       29     add hl,hl
+       2B     dec hl

我们对最小权重平衡二进制表示形式BBR2进行了少量修改。由于BBR2最小化了权重(非零数字的数量),但是我们要最小化权重加上移位数,因此我们将算法中的常数从更改3/25/3

要计算分数并进行验证,请使用以下代码:

def verify(n):
v = 0
for c in strR(n):
    if c=="#":v += 1
    elif c=="+":v -= 1
    else: v *= 2
return v==n

print(0.5*(sum([len(strR(n)) for n in range(1,1001)])/1000 + \
           sum([len(strR(n)) for n in range(-1000,1)])/1001 * 0.9))

print(all([verify(n) for n in range(-1000,1001)]))

输出示例:

strR(486)
         '#)))))+)+))+)'

或在组装中:

inc hl \ add hl,hl \ add hl,hl \ add hl,hl \ add hl,hl \ add hl,hl \ dec hl \ add hl,hl \ dec hl \ add hl,hl \ add hl,hl \ dec hl \ add hl,hl

更多示例程序:

-256  +))))))))
-255  +))))))))#
-254  +)))))))#)
-253  +)))))))#)#
-252  +))))))#))
-251  +))))))#))#
-250  +))))))#)#)
-249  +)))))#)))+
-248  +)))))#)))
-247  +)))))#)))#
-246  +)))))#))#)
-245  +)))))#))#)#
-244  +)))))#)#))
-243  +)))))#)#))#
-242  +))))#)))+)
-241  +))))#))))+

  -5  +))+
  -4  +))
  -3  +)+
  -2  +)
  -1  +
   0  
   1  #
   2  #)
   3  #)#
   4  #))
   5  #))#

可能的优化:OP规则规定直接更改的高字节的inc hdec h指令hl是非法的,但是允许sla h未记录的sl1 h(分别h在a 0和a的移位处左移1 1)。sla hsl1 h每个为两个字节,但有时会缩短输出。


非常好,到目前为止是最低的!我猜这是纯机器代码派上用场的一个实例。;)
ETHproductions 2015年

2
+1这可能是无与伦比的。同样对于使用机器代码的天才(在具有8位指令集和16位寄存器的cpu上)
Level River St

+转换为太奇怪了dec。我一直读错误的负面例子。
ETHproductions 2015年

9

CJam / CJam,143.263 42.713 28.899 23.901 21.903 20.468

ri
[
    ['X\2b1>e`{~{"1)*)"*}{_({(')*1\"m<"}{"1)*"*}?}?}/]s
    "X1)*"/"1)"*
    "1)1)*"/"1)))"*
    "X1)m<"/"1)))"*
    _"1)"/("1):Y"+\'Y*+
]
{,}$0=

没有奖金适用。

在线尝试:样品运行 | 分数计算器 | 验证

运行示例

   1 X
   2 1)
   3 1))
   4 1)))
   5 1))))
   6 1))1)*
   7 1))1)*)
   8 X1))m<
   9 1)))1)*)
  10 1))))1)*
  11 1))))1)*)
  12 1))1)m<
  13 1))1)*1)*)
  14 1))1)*)1)*
  15 1))1)*)1)*)
  16 X1)))m<
  17 X1))m<1)*)
  18 1)))1)*)1)*
  19 1)))1)*)1)*)
  20 1))))1)m<
 981 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*Y*)
 982 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*)Y*
 983 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*)Y*)
 984 1):Y)Y*)Y*)Y*Y*)Y*)Y)m<
 985 1):Y)Y*)Y*)Y*Y*)Y*)Ym<Y*)
 986 1):Y)Y*)Y*)Y*Y*)Y*)Y*Y*)Y*
 987 1):Y)Y*)Y*)Y*Y*)Y*)Y*Y*)Y*)
 988 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Ym<
 989 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*Y*)
 990 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*)Y*
 991 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*)Y*)
 992 1):Y)Y*)Y*)Y*)Y)))m<
 993 1):Y)Y*)Y*)Y*)Y))m<Y*)
 994 1):Y)Y*)Y*)Y*)Y)m<Y*)Y*
 995 1):Y)Y*)Y*)Y*)Y)m<Y*)Y*)
 996 1):Y)Y*)Y*)Y*)Ym<Y*)Ym<
 997 1):Y)Y*)Y*)Y*)Ym<Y*)Y*Y*)
 998 1):Y)Y*)Y*)Y*)Ym<Y*)Y*)Y*
 999 1):Y)Y*)Y*)Y*)Ym<Y*)Y*)Y*)
1000 1):Y)Y*)Y*)Y*)Y*Y*)Y)m<

我的话,那太快了!但是,这些链接在Firefox中不起作用。
ETHproductions 2015年

由于这不是代码高尔夫球,因此我将每个%表达式替换为更长的表达式。链接现在应该可以工作了。
丹尼斯2015年

输入34给出1。在哪个输入上效果更好
Kishan Kumar

2
@KishanKumar 验证将测试所有1000个可能的输入。输出1表示比较成功。
丹尼斯

您能否添加一些示例输出?
圣保罗Ebermann

3

ß /BrainFuck,34.201分

ß来源(194B):

E='++[------>+<]>++'°\c[1]<0°{E&='.'µA=ß"-ß°°c[1]),'')µE&='+++'°/B=1°(A[0]°\A[B]='.'°{µE&='--.++'°]E&=ß~A'+',A[B])&'.'&ß~A'-',A[B])°}°)°'ß"&E,'+-')+ß"&E,'-+')>0µE=ß"'ß"'E,'-+',''),'+-','')°!€E)

如果有人感兴趣,我会加一个说明。BF输出已经非常优化,但是我想我可以使用剩余的318Bß代码来实现

  • 循环嵌套优化,
  • 更多的8位溢出快捷方式,
  • 操作人员碰撞消除

样品:

在Windows中运行:

$ sharps encode.ss 42
++[------>+<]>+++++++++.--.--

$ sharps encode.ss -42
++[------>+<]>++.+++++++.--.--

$ sharps encode.ss 1.427
++[------>+<]>++++++.---.++++++.--.+++++.-------

$ sharps encode.ss -946.427
++[------>+<]>++.++++++++++++.-----.++.--------.++++++.--.+++++.-------

在linux中运行:

$ WINEDEBUG=-all wine sharps source.ss -4.72
++[------>+<]>++.+++++++.------.+++++++++.-----.--

在线BF解释器中进行验证。

分数:

  1. 基本平均值= 37.495
  2. 十进制平均值= 60.959 * 0.5 = ~30.48
  3. 负平均值 = 38.4765234765235 * 0.9 = ~34.629
  4. 平均值以上,最终得分= (37.495 + 30.48 + 34.629)/3 = 34.201

1
我总是喜欢看到人们创造的新语言。:)感谢您的分数细目!我想在小数部分增加奖金,因此我将抵扣额从40%更改为50%。
ETHproductions 2015年

@ETHproductions是的,我将尝试为此设置在线解释器。大约有435个高度抽象的运算符,可以定义另外的9,9k ;-)。我已经纠正了计算(希望如此)。
mınxomaτ

3

Ruby / Ruby,29.77885

31.873 * 0.9(负)30.872(正)。

基本策略是对称的基数3表示形式(“平衡三进制”),即当用数字-1,0,1代替0,1,2

#function
f=->n{m=n  
  a='0' 
  7.times{|i|
    r=m%3;r-=r/2*3
    m=(m-r)/3
    #produce expression: replace 0 with (0*x+-1)
    #only add 0*x if there are higher base 3 digits to follow.
    #only add (..+-1) if the current base 3 digit is nonzero. 
    a.sub!('0',['','(','('][r]+(m.abs>0?'0*x':'')+['','+1)','-1)'][r])
  }
  #tidy up expression
  a.sub!('(-1)*','-')          #remove internal (-1)*
  a.sub!('(+1)*','')           #remove internal (+1)*
  a[-1]==')' && a=a[1..-2]     #remove unnecessary global brackets
  a.sub!('x','(x=1+1+1)')      #find the first x and define it as 1+1+1=3
  #special cases for small numbers 
  n.abs<8 && a=n==0?'0':['','1'+'+1'*(n-1).abs,'-1'*n.abs][n<=>0] 
  a 
}

#call like this
(1..1000).each{|p|
b=f.call(p)
puts b

这是清理之前从0到40的输出

(+1)
((+1)*x-1)
(+1)*x
((+1)*x+1)
(((+1)*x-1)*x-1)
((+1)*x-1)*x
(((+1)*x-1)*x+1)
((+1)*x*x-1)
(+1)*x*x
((+1)*x*x+1)
(((+1)*x+1)*x-1)
((+1)*x+1)*x
(((+1)*x+1)*x+1)
((((+1)*x-1)*x-1)*x-1)
(((+1)*x-1)*x-1)*x
((((+1)*x-1)*x-1)*x+1)
(((+1)*x-1)*x*x-1)
((+1)*x-1)*x*x
(((+1)*x-1)*x*x+1)
((((+1)*x-1)*x+1)*x-1)
(((+1)*x-1)*x+1)*x
((((+1)*x-1)*x+1)*x+1)
(((+1)*x*x-1)*x-1)
((+1)*x*x-1)*x
(((+1)*x*x-1)*x+1)
((+1)*x*x*x-1)
(+1)*x*x*x
((+1)*x*x*x+1)
(((+1)*x*x+1)*x-1)
((+1)*x*x+1)*x
(((+1)*x*x+1)*x+1)
((((+1)*x+1)*x-1)*x-1)
(((+1)*x+1)*x-1)*x
((((+1)*x+1)*x-1)*x+1)
(((+1)*x+1)*x*x-1)
((+1)*x+1)*x*x
(((+1)*x+1)*x*x+1)
((((+1)*x+1)*x+1)*x-1)
(((+1)*x+1)*x+1)*x
((((+1)*x+1)*x+1)*x+1)

并在清理之后

0
1
1+1
1+1+1
1+1+1+1
1+1+1+1+1
1+1+1+1+1+1
1+1+1+1+1+1+1
(x=1+1+1)*x-1
(x=1+1+1)*x
(x=1+1+1)*x+1
((x=1+1+1)+1)*x-1
((x=1+1+1)+1)*x
((x=1+1+1)+1)*x+1
(((x=1+1+1)-1)*x-1)*x-1
(((x=1+1+1)-1)*x-1)*x
(((x=1+1+1)-1)*x-1)*x+1
((x=1+1+1)-1)*x*x-1
((x=1+1+1)-1)*x*x
((x=1+1+1)-1)*x*x+1
(((x=1+1+1)-1)*x+1)*x-1
(((x=1+1+1)-1)*x+1)*x
(((x=1+1+1)-1)*x+1)*x+1
((x=1+1+1)*x-1)*x-1
((x=1+1+1)*x-1)*x
((x=1+1+1)*x-1)*x+1
(x=1+1+1)*x*x-1
(x=1+1+1)*x*x
(x=1+1+1)*x*x+1
((x=1+1+1)*x+1)*x-1
((x=1+1+1)*x+1)*x
((x=1+1+1)*x+1)*x+1
(((x=1+1+1)+1)*x-1)*x-1
(((x=1+1+1)+1)*x-1)*x
(((x=1+1+1)+1)*x-1)*x+1
((x=1+1+1)+1)*x*x-1
((x=1+1+1)+1)*x*x
((x=1+1+1)+1)*x*x+1
(((x=1+1+1)+1)*x+1)*x-1
(((x=1+1+1)+1)*x+1)*x
(((x=1+1+1)+1)*x+1)*x+1

我相信它被称为“平衡三元”。
lirtosiast

@ThomasKwa编辑,谢谢
Level River St

3

锡兰/锡兰,49.86 40.95点

第三个版本使用Ceylon 1.2生成器和509字节的代码:

import ceylon.language{S=String,I=Integer,e=expand}S q(I n)=>n==0then"0"else(n<0then"-"+p(-n,"-")else p(n,"+"));variable Map<[I,S],S>c=map{};S p(I n,S s){S v=c[[n,s]]else(n<8then s.join([1].repeat(n)))else(let(a="+-".replace(s,""))e(e{for(x in 2..8)let(l=(n^(1.0/x)).integer){for(r in l:2)if(r>1)let(w=r^x){if(w-n<n)"("+p(r,"+")+")^("+p(x,"+")+")"+(w<n then s+p(n-w,s)else(n<w then a+p(w-n,a)else""))}}}).reduce<S>((x,y)=>x.size<y.size then x else y))else"";c=[n,s]in c then c else map{[n,s]->v,*c};return v;}

它下降到35.22点,但是我不会将其放在标题行中,因为Celyon 1.2仅在10月29日发布。我认为我无法以这种大小在Ceylon 1.1中实现此算法。)此处有更多详细信息,在这里我将介绍第二个版本。(历史上可以看到第一个版本–它仅支持正数,但确实可以容纳256个字节。)

第二版

现在是第二个版本,它支持负整数(和0),并且通常通过使用extra创建一个短一些的输出-。(此版本实际上使用了允许的长度,第一个尝试保持在256个字节以下,而不是512个字节以下。)

String proof(Integer n) {
    if (n == 0) { return "0"; }
    if (n < 0) { return "-" + p(-n, "-"); }
    return p(n, "+");
}
String p(Integer n, String sign) {
    if (n < 9) {
        return sign.join([1].repeat(n));
    }
    value anti = (sign == "+") then "-" else "+";
    value root = ((n^0.5) + 0.5).integer;
    return "(" + p(root, "+") + ")^(1+1)" +
       ( (root^2 < n) then sign + p(n - root^2, sign) else
         ((n < root^2) then anti + p(root^2 - n, anti) else ""));
}

代码的长度为487,因此以后仍有一些空间可以进行更多优化。(还有许多保留形式,包括空格和长变量名。)

得分:

Total positive: 42652
Average positive:42.652
Total negative: 43653
Average negative: 43.60939060939061
With bonus:39.24845154845155
Overall score: 40.95022577422577

一些样本输出:

   27:  21: (1+1+1+1+1)^(1+1)+1+1
   28:  23: (1+1+1+1+1)^(1+1)+1+1+1
   29:  25: (1+1+1+1+1)^(1+1)+1+1+1+1
   30:  27: (1+1+1+1+1)^(1+1)+1+1+1+1+1
   31:  29: (1+1+1+1+1+1)^(1+1)-1-1-1-1-1
   32:  27: (1+1+1+1+1+1)^(1+1)-1-1-1-1
   33:  25: (1+1+1+1+1+1)^(1+1)-1-1-1
   34:  23: (1+1+1+1+1+1)^(1+1)-1-1

  -27:  22: -(1+1+1+1+1)^(1+1)-1-1
  -28:  24: -(1+1+1+1+1)^(1+1)-1-1-1
  -29:  26: -(1+1+1+1+1)^(1+1)-1-1-1-1
  -30:  28: -(1+1+1+1+1)^(1+1)-1-1-1-1-1
  -31:  30: -(1+1+1+1+1+1)^(1+1)+1+1+1+1+1
  -32:  28: -(1+1+1+1+1+1)^(1+1)+1+1+1+1
  -33:  26: -(1+1+1+1+1+1)^(1+1)+1+1+1
  -34:  24: -(1+1+1+1+1+1)^(1+1)+1+1


  993:  65: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1+1)^(1+1)+1+1+1+1+1
  994:  63: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1-1-1
  995:  61: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1-1
  996:  59: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1
  997:  57: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1
  998:  55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1
  999:  53: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)
 1000:  55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)+1

 -993:  66: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1+1)^(1+1)-1-1-1-1-1
 -994:  64: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1+1+1
 -995:  62: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1+1
 -996:  60: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1
 -997:  58: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1
 -998:  56: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1
 -999:  54: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)
-1000:  56: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)-1

    1:   1: 1
    2:   3: 1+1
    3:   5: 1+1+1
    4:   7: 1+1+1+1
    5:   9: 1+1+1+1+1
    6:  11: 1+1+1+1+1+1
    7:  13: 1+1+1+1+1+1+1
    8:  15: 1+1+1+1+1+1+1+1
    9:  13: (1+1+1)^(1+1)
   10:  15: (1+1+1)^(1+1)+1

    0:   1: 0
   -1:   2: -1
   -2:   4: -1-1
   -3:   6: -1-1-1
   -4:   8: -1-1-1-1
   -5:  10: -1-1-1-1-1
   -6:  12: -1-1-1-1-1-1
   -7:  14: -1-1-1-1-1-1-1
   -8:  16: -1-1-1-1-1-1-1-1
   -9:  14: -(1+1+1)^(1+1)
  -10:  16: -(1+1+1)^(1+1)-1

如您所见,负数始终-比对应的正数长1个字节(前导)。

基本思路与之前的程序相同:在目标编号附近找到一个正方形,并递归地表示其根和余数。但是现在我们允许平方也比目标数大一些,这会使余数变为负数。(+0.5可以将其更改为其他常数来调整算法,但是似乎我已经达到了最佳值– 0.4和0.6都给出较差的结果。)

为了使负值sign变为负值(否则与正值具有相同的结构,我们将运算符传递给递归函数p- "+""-"。在平凡的情况下(即n <9),我们也可以将其用于联接器)如果是正数则表示余数,如果是负数则使用相反的符号。

proof函数处理初始符号(特殊情况为0),p并通过递归进行实际工作。

第三版,适用于锡兰1.2

import ceylon.language { S=String, I=Integer,e=expand }

// output a base-proof Ceylon expression for an integer
// (i.e. using only 0 and 1 as digits).
//
// Question: http://codegolf.stackexchange.com/q/58084/2338
// My Answer:  http://codegolf.stackexchange.com/a/58122/2338
//
// The goal is to produce an expression as short as possible, with
// the code staying under 512 bytes in length.
//
// This approach is to represent a positive integer as a square
// of a positive integer plus some remainder (where the remainder
// can be negative), and for negative integers replace the + on the
// outer level by -.

S q(I n) =>
        n == 0 then "0"
        else (n < 0 then "-" + p(-n, "-")
            else p(n, "+"));

// cache for values of p
variable Map<[I, S],S> c = map { };

// Transforms a positive number into a base-proof term, using
// the given sign for the summation on the outer level.
S p(I n, S s) {
    S v =
    // look into the cache
            c[[n, s]] else (
        // hard-code small numbers
        n < 8 then s.join([1].repeat(n)))
            else
    // do the complicated stuff
    (let (a = "+-".replace(s,""))
            e(e {
                    for (x in 2..8) // try these exponents
                        let (l = (n ^ (1.0 / x)).integer) // \[ sqrt[exp]{n} \] in LaTeX
                            { for (r in l:2) // lowerRoot, lowerRoot + 1
                                    if (r > 1)
                                        let (w = r ^ x)
                                            { if (w-n < n) // avoid recursion to larger or same number
                                                    // format the string as  r^x + (n-w)
                                                    "(" + p(r, "+") + ")^(" + p(x, "+") + ")" +
                                                            (w < n then s + p(n - w, s)
                                                                else (n < w then a + p(w - n, a)
                                                                    else ""))
                                            } } })
            // and now find the shortest formatted string
                .reduce<S>((x, y) => x.size < y.size then x else y))
    // this should never happen, but we can't tell the compiler
    // that at least some of the iterables are non-empty due to the if clause.
            else "";

    // this builds a new cache in each step – quite wasteful,
    // as this also happens when the value was found in the cache,
    // but we don't have more characters remaining.
    //// c = map { [n, s] -> v, *c };
    ///better way:
     c = [n,s] in c then c else map{[n,s]->v, *c}; 
    return v;
}

高尔夫版本(即注释和空格已删除)张贴在顶部,恰好是509字节的代码。

这使用了与第二个版本相同的基本原理,但是它不仅使用正方形,还尝试使用更高的数字幂(尝试将指数从2扩展到8),并使用最短的结果。它还缓存结果,否则,对于具有许多递归调用的较大数量的数据,这将是令人无法接受的缓慢。

得分:

Total positive: 36622
Average positive: 36.622
Total negative: 37623
Average negative: 37.58541458541458
With bonus:33.826873126873124
Overall score: 35.22443656343656

中间最大的缩进构造是三个嵌套的可迭代理解,内部两个是let表达式。然后使用expand函数将它们取消嵌套两次,然后该reduce函数查找这些字符串中最短的字符串。

我已经提出了一项功能要求,以便能够一次完成该任务。

在理解内,我们从根r,指数x和余数(n-ww-n)构建一个字符串。

let表达和map功能在锡兰1.2是新的。map可能已被替换为HashMap(这将需要更多字符进行导入,尽管可能会更快,因为我不会为每个新条目构建新的地图)。let像这样的表达式let (w = r ^ x)可以通过使用if类似的子句来替换if(exists w = true then r ^ x)(然后我也不需要两个expand调用),但是这仍然会更长一些,无法容纳511个允许的字节。

在这里,与上面选择的输出相对应的样本输出,除了非常小的数字之外,所有其他输出均较短:

   27:  15: (1+1+1)^(1+1+1)
   28:  17: (1+1+1)^(1+1+1)+1
   29:  19: (1+1+1)^(1+1+1)+1+1
   30:  21: (1+1)^(1+1+1+1+1)-1-1
   31:  19: (1+1)^(1+1+1+1+1)-1
   32:  17: (1+1)^(1+1+1+1+1)
   33:  19: (1+1)^(1+1+1+1+1)+1
   34:  21: (1+1)^(1+1+1+1+1)+1+1

  -27:  16: -(1+1+1)^(1+1+1)
  -28:  18: -(1+1+1)^(1+1+1)-1
  -29:  20: -(1+1+1)^(1+1+1)-1-1
  -30:  22: -(1+1)^(1+1+1+1+1)+1+1
  -31:  20: -(1+1)^(1+1+1+1+1)+1
  -32:  18: -(1+1)^(1+1+1+1+1)
  -33:  20: -(1+1)^(1+1+1+1+1)-1
  -34:  22: -(1+1)^(1+1+1+1+1)-1-1

  993:  39: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1-1
  994:  37: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1
  995:  35: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1
  996:  33: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1
  997:  31: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1
  998:  29: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1
  999:  27: ((1+1+1)^(1+1)+1)^(1+1+1)-1
 1000:  25: ((1+1+1)^(1+1)+1)^(1+1+1)

 -993:  40: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1+1
 -994:  38: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1
 -995:  36: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1
 -996:  34: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1
 -997:  32: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1
 -998:  30: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1
 -999:  28: -((1+1+1)^(1+1)+1)^(1+1+1)+1
-1000:  26: -((1+1+1)^(1+1)+1)^(1+1+1)

    1:   1: 1
    2:   3: 1+1
    3:   5: 1+1+1
    4:   7: 1+1+1+1
    5:   9: 1+1+1+1+1
    6:  11: 1+1+1+1+1+1
    7:  13: 1+1+1+1+1+1+1
    8:  13: (1+1)^(1+1+1)
    9:  13: (1+1+1)^(1+1)
   10:  15: (1+1+1)^(1+1)+1

    0:   1: 0
   -1:   2: -1
   -2:   4: -1-1
   -3:   6: -1-1-1
   -4:   8: -1-1-1-1
   -5:  10: -1-1-1-1-1
   -6:  12: -1-1-1-1-1-1
   -7:  14: -1-1-1-1-1-1-1
   -8:  14: -(1+1)^(1+1+1)
   -9:  14: -(1+1+1)^(1+1)
  -10:  16: -(1+1+1)^(1+1)-1

例如,现在我们有1000 =(3 ^ 2 + 1)^ 3,而不是1000 =(6 ^ 2-4)^ 2-5 ^ 2 + 1。


我错误地记得程序限制为256个字节...在512个字节中可以完成更多工作。稍后再试。
圣保罗Ebermann

不,它说less than 512。这样您就可以使用 511个字节;)
mınxomaτ15年

我怎么从未听说过这种语言?!:O但认真的说,很好的解释!我喜欢理解他人在答案中使用的技术。+1
ETHproductions 2015年

@ETHproductions我也只在两周前在网站上读过它,并开始喜欢它。因此,为了更好地了解它,我尝试使用锡兰在这里回答问题。
圣保罗Ebermann

2

Ruby / dc, 20.296 18.414 16.968

动态编程!定义一个函数列表,给定一个dc指令,该函数列表将返回一个新表达式和该表达式的数值。然后,从1prefined 开始,它会构建一个包含直至和包括所需值的所有可到达值的列表。

编辑:

n-1添加了一个函数,并使其多次运行该算法。似乎需要7次通过才能稳定下来。必须将一些变量名缩短为512字节以内。

编辑2:

当我在时,为n(n-1)n(n + 1)n ^ 3添加了函数。将代码缩短一些,精确到512字节。

N = gets.to_i

fns = [
  ->(n,s){[n-1,   s+'1-']},
  ->(n,s){[n+1,   s+'1+']},
  ->(n,s){[n*2,   s+'d+']},
  ->(n,s){[n*3,   s+'dd++']},
  ->(n,s){[n*~-n, s+'d1-*']},
  ->(n,s){[n*n,   s+'d*']},
  ->(n,s){[n*-~n, s+'d1+*']},
  ->(n,s){[n*n*n, s+'dd**']},
]

lst = []*(N+1)
lst[0..2] = %w[0 1 1d+]

loop do
  prev = lst.dup

  (1..N).each do |n|
    fns.each do |f|
      m,s = f[n, lst[n]]
      lst[m] = s if m <= N && (lst[m].nil? || lst[m].size > s.size)
    end
  end

  break if lst == prev
end

puts lst[N]

生成的数字:

输出完全由五个不同的字符组成:1将值1压入堆栈;将值1压入堆栈。d复制堆栈的顶部;+,,-* 弹出两个最高值,并分别推送它们的和,差和乘积。执行后,每个生成的表达式仅将一个值添加到堆栈中。

   1: 1
   2: 1d+
   3: 1dd++
   4: 1d+d+
   5: 1d+d+1+
   6: 1d+dd++
   7: 1d+dd++1+
   8: 1d+dd**
   9: 1dd++d*
  10: 1d+d+1+d+
  11: 1d+d+1+d+1+
  12: 1dd++d1+*
  13: 1dd++d1+*1+
  14: 1d+dd++1+d+
  15: 1d+d+d*1-
  16: 1d+d+d*
  17: 1d+d+d*1+
  18: 1dd++d*d+
  19: 1dd++d*d+1+
  20: 1d+d+d1+*
  21: 1d+d+d1+*1+
  22: 1d+d+1+d+1+d+
  23: 1d+dd**dd++1-
  24: 1d+dd**dd++
  25: 1d+d+1+d*

...

 989: 1d+d+d*d+d1-*1-1-1-
 990: 1d+d+d*d+d1-*1-1-
 991: 1d+d+d*d+d1-*1-
 992: 1d+d+d*d+d1-*
 993: 1d+d+d*d+d1-*1+
 994: 1d+d+d*d+d1-*1+1+
 995: 1d+d+d*d+d1-*1+1+1+
 996: 1d+d+1+dd**d+1-d+d+
 997: 1d+d+1+d+dd**1-1-1-
 998: 1d+d+1+d+dd**1-1-
 999: 1d+d+1+d+dd**1-
1000: 1d+d+1+d+dd**

1
很好,到目前为止击败了除z80机器代码以外的所有东西(甚至包括Dennis的CJam!)。您是否认为可以-在不超过字节数的情况下添加运算符?
ETHproductions 2015年

@ETHproductions怎么样?;)现在也不难添加负数。
daniero

0

Python 2.6中,78.069 - 66.265分

提交我想知道的价值的答案(在这种情况下不是很多……但是清楚地表明,对于这个挑战,仅考虑将输出构成为位移值的总和是不够的;当考虑到没有数字时) 0或1之外的值可能会出现在输出中)。稍后我可能会以另一种方式生成输出。

代码本身不太长(176个字符):

def f(a):return'+'.join(('(1<<%s)'%['0','+'.join('1'*x)][x>0]).replace('(1<<0)','1')for x in[i for i,e in enumerate(bin(a)[::-1][:-2])if int(e)])
print"".join(f(int(input())))

它生成正确但冗长的输出:

17
1+(1<<1+1+1+1)

800
(1<<1+1+1+1+1)+(1<<1+1+1+1+1+1+1+1)+(1<<1+1+1+1+1+1+1+1+1)

计算分数的代码段:

def f(a):return'+'.join(('(1<<%s)'%['0','+'.join('1'*x)][x>0]).replace('(1<<0)','1')for x in[i for i,e in enumerate(bin(a)[::-1][:-2])if int(e)])
print sum(len("".join(f(i)))for i in range(1000))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.