ベースプルーフ式の出力


21

バックグラウンド

いくつかの可能な未来では、世界は彼らの数値システムを10進数(基数10またはb10)から他の基数(2 b2進数b8、8進数、16進数b16、さらには単項b1に変換します。したがって、この世界を変える可能性のあるイベントに備えて、すべてのプログラムをベースプルーフすることにします。これは、単数0のsと1s のみを演算子と組み合わせて使用​​して、既存の数値定数を置き換えることで実行できます。

ただし、問題が1つだけあります。変更するプログラムが大量にあり、各数値を手動で式に変換するには数週間かかります。したがって、プログラム(または関数)を作成して、各式を置き換える式を決定します。

入力

入力は正の整数になります。コード 1000までの整数を処理できる必要あります。

(コードが小数および/または負の入力をサポートしている場合は、以下のスコアリングを参照してください。)

出力

コードは、少なくとも1つの言語で入力に評価される式を出力する必要があります。これはどの言語でもかまいません。プログラムまたは関数が記述されているものと同じである必要はありません。また、この式は完全なプログラムまたは関数である必要はありません。

明確にするために、出力には次の操作のいずれかが含まれる場合があります。

  • インクリメント/デクリメント
  • 加算/合計
  • 減算/否定
  • 乗算/倍数(数値が直接関与しない場合のみ2!)
  • 除算/モジュロ
  • 指数/対数
  • square / sqrt(これも数値に直接関係しない場合のみ2!)
  • ビット演算(bOR、bAND、bNOT、bXOR、ビットシフト)
  • 変数の設定/取得
  • スタック操作

出力で、または同様の機能を使用することはできませんeval()。また、上記以外のアクションを実行する関数を出力で使用することはできません。

ああ、もう一つ:私たちは出力が可能な限り多くの拠点として有効であることにしたいから、それが含まれていてもよいだけの数の定数である0110言語がa 1およびa として解釈しない限り、(10)などの数字は許可されません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のすべての出力の平均バイト数。

  • 10進スコア:コードが少なくとも3桁の小数点以下をサポートする場合、これは、で始まり、0.001で終わる一連の数値のすべての出力の平均バイト数であり10001.001毎回増加します。0.001, 1.002, 2.003...998.999, 1000.000次に、このスコアの50%を引き取ります。

  • 負のスコア:コードが負の数とゼロをサポートしている場合、これはから-1000までのすべての整数の出力の平均バイト数です0。次に、このスコアの10%を引き取ります。

(これらを計算する最も簡単な方法は、プログラム/関数を内部に持つループです。)

最終的なスコアは、上記の式のいずれかの平均です。

出力が非決定的(つまり、ランダムで、同じ入力で複数の実行が複数の一意の出力を生成する)の場合、各入力のスコアは、CPUでの10回の実行で最大の出力によって決定されます。

また、将来どのくらい貴重なコンピューターデータが使用されるかわからないので、ジェネレーターコードのバイト数は512バイト未満でなければなりません。

2週間で最低スコア(9月30日)が勝者として宣言されます。勝者の @ThomasKwaおめでとうございます!


リーダーボード

回答が正しく表示されることを確認するには、次のヘッダーで回答を開始してください。

# Language name/Other language name, X points

どこで Xあなたの答えの得点は。例:

# CJam/Pyth, 25.38 points

ご質問やご提案がありましたら、お知らせください。がんばろう!


保持する変数0または1デフォルトで変数を使用できますか?
デニス

@デニス私はそれで問題は見られないので、先に行きます!
ETHproductions

基数2とデフォルトの基数の間で基数変換を行うことができないと仮定しています。
ブルー

@muddyfishいいえ、出力でのベース変換は許可されていません。
ETHproductions

私たちも何かを使用することは許可されていないと思います Integer.parseInt("1000", 1+1+1+1+1+1+1+1+1+1)か?私はかなり確信しているparseInt用途にのみ許可された操作;-)
サンパウロEbermann

回答:


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

次の3つの命令のみが使用されます。

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(上の1ビットシフトを左hにそのシフト01、それぞれが)許可されます。sla hsl1 hはそれぞれ2バイトですが、出力が短くなる場合があります。


非常に素晴らしい、これまでのところ最低!これは、純粋なマシンコードが役立つ1つのインスタンスだと思います。;)
ETHproductions

2
+1これはおそらく無敵です。また、マシンコードを使用する天才(主に8ビットの命令セットといくつかの16ビットレジスタを持つCPU上)
レベルリバーセント

+変換する方法は奇妙decです。負の例を間違って読み続けています。
ETHproductions

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

これはゴルフのコードではないため、それぞれ%を長い表現に置き換えました。これでリンクが機能するはずです。
デニス

入力34は、それが良い仕事んどの入力1.与えます
のKishanクマール

2
@KishanKumar 検証では、1000の可能な入力すべてをテストします。出力1は、比較が成功したことを示します。
デニス

出力例をいくつか追加していただけますか?
パエロエベルマン

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. 10進数の平均= 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

@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

私はそれが「バランス三元」と呼ばれると信じています。
リルトシアスト

@ThomasKwa編集、ありがとう
レベルリバーセント

3

セイロン/セイロン、49.86 40.95ポイント

3番目のバージョンでは、ジェネレーターと509バイトのコードにCeylon 1.2を使用しています。

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でこのアルゴリズムを実装できるとは思いません。)詳細については、ここで2番目のバージョンについて説明します。(最初のバージョンは履歴で確認できます。正の数のみをサポートしていましたが、256バイトに収まりました。)

第二版

現在、2番目のバージョンは負の整数(および0)をサポートし、さらにを使用して少し短い出力を作成します-。(このバージョンは実際に許可された長さを使用しており、最初の長さは512ではなく256バイト未満にとどまりました。)

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関数は再帰を使用して実際の作業を行います。

Ceylon 1.2用の3番目のバージョン

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番目のバージョンと同じ基本原則を使用しますが、単なる2乗の代わりに、より高い数の累乗(2から8の指数を試行)を使用して、最短の結果を使用します。また、結果をキャッシュします。そうしないと、多くの再帰呼び出しを行うより大きな数値では許容できないほど遅くなります。

得点:

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

真ん中の大きなインデントされた構造は、3つのネストされた反復可能な内包表記であり、内側の2つはlet式の中にあります。これらは、expand関数を2回使用してネスト解除され、reduce関数はそれらの文字列の中で最も短いものを見つけます。

これを単一の理解で行えるようにするために、機能のリクエストを提出しました。

内包表記では、ルートr、指数x、および剰余(n-wまたはw-n)から文字列を構築しています。

let発現とmap機能はセイロン1.2で新たに追加されました。mapで置き換えることができましたHashMap(インポートにはより多くの文字が必要でしたが、新しいエントリごとに新しいマップを作成しないため、おそらくより高速になります)。のletような表現は、次のような句let (w = r ^ x)を使用することで置き換えることができます(そして、2つは必要ありませんでしたifif(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 =(6 ^ 2-4)^ 2-5 ^ 2 + 1ではなく、1000 =(3 ^ 2 + 1)^ 3になりました。


256バイトというプログラムの制限を誤って覚えていました... 512ではさらに多くのことができます。後で試してみます。
パエロエベルマン

いや、それは言うless than 512。だから、最大を使用することができます。511バイトの;)
mınxomaτ15年

私はこの言語を聞いたことがないのですか?!?:Oしかし、真剣に、優れた説明!他の人が回答で使用するテクニックを理解するのが大好きです。+1
ETHproductions

@ETHproductions私もこのサイトで約2週間前にそれを読んだだけで、気に入ってくれました。それで、よりよく知るために、ここではCeylonを使用して質問に答えようとします。
パエロエベルマン

2

Ruby / dc、 20.296 18.414 16.968

動的プログラミング!dc命令が与えられると、新しい式とその式の数値を返す関数のリストを定義します。次に、1事前に定義された状態から始めて、必要な値までのすべての到達可能な値のリストを作成します。

編集:

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]

生成された数字:

出力は完全に5つの異なる文字で構成され1ます。値1をスタックにプッシュします。dスタックの最上部を複製します。+-、および* それぞれ、2つのトップの値をポップし、それらの和、差、および製品を押します。生成された各式は、実行後に1つの値のみをスタックに追加します。

   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マシンコード以外のすべてを破っています(デニスのCJamも!)。-バイトカウント内に留まりながら演算子を追加できると思いますか?
ETHproductions

@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))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.