0〜9と4つの操作のみで数値を表現する


14

説明

Befungeは、stacksを使用する2次元プログラムです

つまり、5 + 6を行うには、と書く56+、という意味です。

56+
5    push 5 into stack
 6   push 6 into stack
  +  pop the first two items in the stack and add them up, and push the result into stack

(to those of you who do not know stacks, "push" just means add and "pop" just means take off)

ただし、知人が観察しているように、数字を56直接スタックにプッシュすることはできません。

そうするために、我々は書かなければならない78*、代わりにその乗算を7して8、スタックに製品をプッシュします。

詳細

入力は任意の形式で取得できます。つまり、プログラマの裁量により、STDINであるかどうかは問われません。

入力は正の整数になります(0負の整数を含めても負の整数でもない)。

出力は、これらの文字のみで構成される文字列になります0123456789+-*/(モジュロ使用しません%)。

目標は、上記の形式を使用して、入力を表すことができる最短の文字列を見つけることです。

たとえば、入力がの場合123、出力はになります67*99*+。出力は左から右に評価する必要があります。

許容される出力が複数ある場合(たとえば許容される場合もあります99*67*+)、いずれかを出力できます(すべてを出力してもボーナスはありません)。

さらなる説明

それでも67*99*+評価方法がわからない場合123は、詳細な説明があります。

stack    |operation|explanation
          67*99*+
[6]       6         push 6 to stack
[6,7]      7        push 7 to stack
[42]        *       pop two from stack and multiply, then put result to stack
[42,9]       9      push 9 to stack
[42,9,9]      9     push 9 to stack
[42,81]        *    pop two from stack and multiply, then put result to stack
[123]           +   pop two from stack and add, then put result to stack

TL; DR

プログラムは、上記で指定した形式を使用して、入力(数値)を表すことができる最短の文字列を見つける必要があります。

ノート

これはチャレンジなので、バイト単位の最短コードが優先されます。

明確化

-いずれかになりますx-yy-xプログラマの裁量で、。ただし、選択はソリューション内で一貫している必要があります。同様に/

サンプルプログラム

Lua、1862バイト(オンラインで試してみてください

私は著者なので、ゴルフは一切しません。

説明:

This uses the depth-first search method.

:深さ優先探索の詳細ここに

プログラム:

local input = (...) or 81

local function div(a,b)
    if b == 0 then
        return "error"
    end
    local result = a/b
    if result > 0 then
        return math.floor(result)
    else
        return math.ceil(result)
    end
end

local function eval(expr)
    local stack = {}
    for i=1,#expr do
        local c = expr:sub(i,i)
        if c:match('[0-9]') then
            table.insert(stack, tonumber(c))
        else
            local a = table.remove(stack)
            local b = table.remove(stack)
            if a and b then
                if c == '+' then
                    table.insert(stack, a+b)
                elseif c == '-' then
                    table.insert(stack, b-a)
                elseif c == '*' then
                    table.insert(stack, a*b)
                elseif c == '/' then
                    local test = div(b,a)
                    if test == "error" then
                        return -1
                    else
                        table.insert(stack, a+b)
                    end
                end
            else
                return -1
            end
        end
    end
    return table.remove(stack) or -1
end

local samples, temp = {""}, {}

while true do
    temp = {}
    for i=1,#samples do
        local s = samples[i]
        table.insert(temp, s..'0')
        table.insert(temp, s..'1')
        table.insert(temp, s..'2')
        table.insert(temp, s..'3')
        table.insert(temp, s..'4')
        table.insert(temp, s..'5')
        table.insert(temp, s..'6')
        table.insert(temp, s..'7')
        table.insert(temp, s..'8')
        table.insert(temp, s..'9')
        table.insert(temp, s..'+')
        table.insert(temp, s..'-')
        table.insert(temp, s..'*')
        table.insert(temp, s..'/')
    end
    for i=1,#temp do
        if input == eval(temp[i]) then
            print(temp[i])
            return
        end
    end
    samples = temp
end

ボーナス

Befunge(またはそのバリアント)を使用してコードを記述する場合のケーキ。


3
常にソートされた文字列を生成するかどうかを判断するのは難しいかもしれません。1つのアイデアは、たとえば30〜50の大きな数字のセットを生成し、すべての出力文字列の長さの合計でスコア付けすることです。ただし、そのスコアをコード長と組み合わせる方法がわからない
ルイスメンドー

4
こののサブセット。
アディソンクランプ

2
以下からの私の考えを超えるコピーチャット:「私はそれについて考えたが、私はサブセットがずっと簡単なものになると主張していると思いますので、1)無進、2)無山車、3)無重複や4)正のみ」
SP3000

1
@CoolestVetoこれは、古い回答を無効にするのに十分な違いがあります。
Rɪᴋᴇʀ

1
@CoolestVeto他の課題は、この課題の複製として閉じられるべきだと思います。
mbomb007

回答:


4

Python 2、278バイト

毎回最短の回答が得られる私の最高のソリューション。(しかし非常に遅い)

def e(c):
 s=[];x,y=s.append,s.pop
 while c:
  d,c=c[0],c[1:]
  if"/"<d<":":x(d)
  else:a,b=y(),y();x(str(eval(b+d+a)))
 return int(y())
def g(v):
 s="0123456789+-*";t=list(s)
 while 1:
  for x in t:
   try:
    if e(x)==v:return x
   except:0
  t=[x+y for x in t for y in s]

Python 2、437バイト

このソリューションはより長くなりますが、非常に高速です(ブルートフォースではありません)。そして、私はそれが常に最短の結果を返すことを確信しています。

r=range;l=len;a=input()
def f(n):
 if n<=9:return str(n)
 for d in r(9,1,-1):
  if n%d==0:return f(n/d)+"%d*"%d
 h=sum(map(int,list(str(n))))%9
 return f(n-h)+"%d+"%h
m={x:f(x) for x in r(a*9)}
for b in m:
 if a-b in m and l(m[b])+l(m[a-b])+1<l(m[a]):m[a]=m[a-b]+m[b]+"+"
 if a+b in m and l(m[b])+l(m[a+b])+1<l(m[a]):m[a]=m[a+b]+m[b]+"-"
 if b!=0 and a%b==0 and a/b in m and l(m[b])+l(m[a/b])+1<l(m[a]):m[a]=m[a/b]+m[b]+"*"
print m[a]

2
PPCGへようこそ!ここで楽しい時間を過ごせることを願っています。
漏れの修道女

1
@pbochinak私は有効なものを見つけたと思う。(13文字)をf(6551)返し25*8*9*7+9*8+9999***52*-(11文字)の方が優れています。eval上記の(質問内の)自分の関数で検証しました。
リーキー修道女

4
@pbochniak私の前のコメントが指摘しているように、この答えは現在の状態では無効です。修正作業中に一時的に削除することをお勧めします(他に何もない場合は、ダウン投票を引き付けるのを防ぐため)。
デニス

1
あなたの中だけですることができwhile c:
ヴェン

あなたが使用することができ;、(インデントブロックのバイト節約)の変数に別の割り当てへのVEN先端を、シンボルと何かの間に空白を取り除く、とt行くことができます。
電卓

4

Perlの、134の 133 132 128バイト

+5を含む-Xlp(コードにが含まれているため、余分に2つ'

STDINのターゲット番号で実行します:

perl -Xlp befour.pl <<< 123

befour.pl

@1{1..9}=1..9;$.+=2,map{for$a(%1){"+-*/"=~s%.%"\$1{\$-=$a$&$_/'$1{$a}$1{$_}$&'=~/^.{$.}\$/}||=\$&"%eegr}}%1until$\=$1{$_}}{

人為的な制限はなく、概念的にはある程度効率的ですが、高速化のために数バイトを犠牲にしたにもかかわらず、ひどい実行時間を持っています。長さ11のソリューション(たとえば、ターゲット番号6551)の生成には、システムで約5時間かかります。

さらに7バイトを犠牲にすると、速度が多少耐えられます。

@1{1..9}=1..9;$.+=2,map{for$a(@a){"+-*/"=~s%.%"\$1{\$-=$a$&$_/'$1{$a}$1{$_}$&'=~/^.{$.}\$/}||=\$&"%eegr}}@a=keys%1until$\=$1{$_}}{

長さ11のソリューションでは17分、長さ13のソリューションでは約5時間。長さ15が必要な最初の数値は16622で、約2日かかります。長さ17が必要な最初の数は73319です。

除算は0に向かって切り捨てることにより整数を返すと想定していることに注意してください(befunge 93仕様による)。


ドル記号は何をしますか?(私はPerlをまったく話さない)
リーキー修道女

1
@KennyLau $はスカラー値にアクセスします。ほとんどの言語であなたが書くところでa=4、perlは使用します$a=4。しかし、より複雑な変数のスカラーアクセスにも使用されます。例えば、$a{$b}ハッシュ(マップ、辞書)からのフェッチ%aをキースカラー値$b
トンHospel

2

C、550 545バイト

#define L strlen
#define y strcpy
#define t strcat
char c[9999][99];i=1,k=3;main(j){for(;i<10;i++)*c[i]=i+'0';for(;k--;){
for(i=1;i<9999;i++)for(j=1;j<=i;j++)*c[i]&&*c[j]&&(i+j>9998||*c[i+j]&&
L(c[i+j])<L(c[i])+L(c[j])+2||t(t(y(c[i+j],c[i]),c[j]),"+"),
i*j>9998||*c[i*j]&&L(c[i*j])<L(c[i])+L(c[j])+2||t(t(y(c[i*j],c[i]),c[j]),"*"));
for(i=9999;--i;)for(j=i;--j;)*c[i]&&*c[j]&&(*c[i/j]&&
L(c[i/j])<L(c[i])+L(c[j])+2||t(t(y(c[i/j],c[i]),c[j]),"/"),
*c[i-j]&&L(c[i-j])<L(c[i])+L(c[j])+2||t(t(y(c[i-j],c[i]),c[j]),"-"));}
scanf("%d",&i);printf("%s",c[i]);}

不要な改行(前処理ディレクティブの後の3つの改行を除くすべて)を削除した後の550 545バイト。

@Kenny Lau-入力として1〜9998の整数を受け取ることができますが、最適なソリューションが計算される入力の範囲は9998より小さいと思います。一方、メモリがあれば、両方の範囲を拡張できますそれを許可します。

プログラムは9998を超える数のスタックにプッシュすることはできません。 1〜9998(ダイクストラのアルゴリズムのように)。3回繰り返しても改善はありません。バイトを節約するために、k = 3をハードコーディングしました。

範囲を拡張するには、2つのことが必要です-定数9999および9998を変更し、改善がある限り外部ループで可変回数の反復を実行し、改善が行われないまでにかかる時間を確認し、定数k = 3をその値に変更します。


PPCGへようこそ!ここで楽しい時間を過ごせることを願っています。
リーキー修道女

これは6551テストに完全に合格します。このプログラムの有効範囲はどのくらいですか?
漏れの修道女

9999であると思います。この情報をソリューションに追加してください。
リーキー修道女

それはあなたが初期化することによって、いくつかのバイトを食べることができ、また、9998.であるべきijk前にmain()
リーキー修道女

1
@Kenny Lau-編集ありがとうございます。範囲の拡張について、実際に範囲を拡張するにはもう少し時間がかかることに気付きました。その情報を回答に含めました。
ミリバイト

2

Python 2、284バイト

免責事項:一部の値については永久に異常終了しますが、常に最短の文字列を返すことを保証する必要があり、人為的に課された範囲制限はありません...負の値でも機能します。:)

def f(v):
 i,z=0,'+-*/'
 while 1:
  s=('%x'%i).translate(__import__('string').maketrans('abcd',z),'ef');t=s;q=[];a,p=q.append,q.pop;i+=1
  try:
   while t:
    o,t=t[0],t[1:]
    if o in z:n,m=p(),p();a(eval(`m`+o+`n`))
    else:a(int(o))
   if p()==v and not q:return s
  except:pass

アルゴリズム:

  • 皮切りに i = 0
  • の16進値を表す文字列を取得しi、それぞれに置き換えabcd+-*/、すべてを削除しますef
  • 文字列を後置記法(RPN)として処理しようとしました
  • 成功し、結果が入力値と一致する場合、使用された文字列を返します。
  • それ以外の場合は、増分iして再試行してください。

「[t]いくつかの値について[...]永遠に」あなたはそれをテストしましたか?何の価値?
漏れの修道女

@KennyLau f(i)から計算するテストを作成しました0 <= i <= 65516551@pbochniakの元の送信を無効にするために使用した値を取得するため)。:今のところ、ほんの数分で実行されていて、ここではテストから最後の出力です 91 : 49+7* 3.020 s (total 108.174 s, worst 89: 5.827 s) :それはちょうど値92で終了-更新 92 : 149+7*+ 258.761 s (total 366.935 s, worst 92: 258.761 s)
ケン「ジョーイ」モッシャー

@KennyLau:テストだけで、最大値まで時間かけて実行している、とされてきたが113...完全なテスト出力を参照ここで(ペーストビン)の場合している興味を持って...
ケンのジョーイモッシャー

2

Python 2、182バイト

n=input()
L=[[[],""]]
while 1:
 s,c=L.pop(0);L+=[[s+[i],c+`i`]for i in range(10)]+(s[1:]and[[s[:-2]+[eval(`s[-2]`+o+`s[-1]`)],c+o]for o in"/+-*"[s[-1]==0:]])
 if[n]==s[-1:]:print c;E

そのため、わいせつに遅いので、入力221で1時間実行したままにしましたが、まだ終了していません。遅大量のは、私は幅優先探索のためのキューとしてリストを使用しているためで、.pop(0)あるO(n)リストの。

L(stack, code to reach stack)ペアを含む単なるキューです。各ステップでは、数字が常に追加され、スタックに少なくとも2つの要素がある場合は演算子が実行されます。除算は最後の要素が0でない場合にのみ実行されますが、除算は絶対に必要ではないという強い疑いがあります(ただし、除算する方法はありませんが、これは500までのケースです)。

プログラムNameErrorは、結果を(最終的に)出力した後にa を介して終了します。


;E最後に何をしていますか?
漏れの修道女

@KennyLauそれは他のどこにも定義されていないNameErrorので終了Eです
-Sp3000

うわー、そのような賢さ。
漏れの修道女

1

CJam、79

ri:M;A,:s:L;{L2m*{s,Y=},{~:A+AS*~!"/+-*">\f{\+}~}%Y2+:Y;_L@+:L;{S*~M=},:R!}gR0=

オンラインで試す

これはひどく非効率的ですが、十分なメモリと時間を与えられ、最終的には機能します。123は16GBのメモリを使い果たしますが、120と125は問題ありません。



0

Python 3、183バイト

e,n=enumerate,input()
v=list('0123456789')+[' '*n]*n*2
for i,s in e(v):
 for j,t in e(v):
  for o,k in zip('+*-',(i+j,i*j,i-j)):
   if 9<k<2*n:v[k]=min(v[k],s+t+o,key=len)
print(v[n])

速度は完全に不合理ではありません(123、221、1237、6551は数秒または数分で終了します)。ifステートメントを変更すると、if j<=i and <k<2*nさらに高速になりますが、コストは9バイト増えます。私は除算(/)を省きました。なぜなら、それがどのように必要になるかわからないからです。


ヒント:分割が必要です。
リーキー修道女
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.