制御不能の丸めエラー


14

バックグラウンド

最近、小さな会計事務所に雇われました。会計の世界はあなたにとっていくぶん外国のものなので、あなたがすべての専門家のガイドラインに従っているかどうかはわかりません。特に、これらすべての数値をいつ、どの方向に丸めるべきかわからないので、ほとんどの場合、あなたはそれを翼に乗せて最善を望みます。

入力

入力は、単純な計算を表す単一の文字列です。文字で区切られたいくつかの非負の整数が含まれています+-*/。文字列は左から右に読み取られ、通常の優先順位規則は無視されるため、"23+1*3/4"「23で始まり、1を加算し、3を乗算し、4で除算する」ことを意味します。結果は18になります。00それ自体を除く)、またはゼロによる除算。

出力

計算の各段階で、結果を最も近い整数に切り上げまたは切り捨てるか、そのままにしておくことができます。最後に、整数の結果を得るために切り上げまたは切り捨てます。あなたの出力は、そのような計算から生じる可能性のある整数のリストであり、ソートされ、重複はありません。

ルール

完全なプログラムまたは関数のいずれかを作成できます。最小のバイトカウントが優先され、標準の抜け穴は許可されません。

テストケース

"42" -> [42]
"2+0+4-0" -> [6]
"23+1*3/4" -> [18]
"5/2" -> [2,3]
"5/2+7/3*6-1" -> [17,18,19,23]
"23/2/2*30-170/3" -> [-7,-6,-2,-1,0,1,3,4]
"1/3*2*2*2*2*2*2" -> [0,16,20,21,22,24,32,64]
"1/3*9" -> [0,3,9]

プログラムは、可能なすべての入力(数のサイズに関係なく)、制限されたサイズの入力、またはテストケースのみで動作する必要がありますか?
-orlp

@orlpすべての入力数と中間結果が絶対値で1000万以下などの場合、少なくとも動作するはずです。結局のところ、会計事務所は小さいです。
Zgarb

1/3*9浮動小数点数を使用すると失敗する可能性があるテストケースに注意してください。
クラウディ

@Claudiuありがとう、チャレンジに追加しました。
-Zgarb

回答:


4

J、84バイト

1要素のリストから開始して、関数は次の式を評価し、切り上げられたコピーと切り捨てられたコピーを追加することにより、リスト内のすべての可能な中間番号を保持します。

さらにゴルフをし、明日説明を追加します。 もっとゴルフをする明白な方法を見つけることができません。

f=.3 :'/:~~.<.>((,>.,<.)@".@(":@],''x'',;@[))&.>/|.(>@{.;_2<\}.);:y rplc''/'';''%'''

すべてのテストに合格します。

使用法:

   f '1/3*2*2*2*2*2*2'
0 16 20 21 22 24 32 64
   f '1/3*9'
0 3 9

ここで試してみてください。


フロートの代わりに合理的にそれらをどのように扱いますか?それはJに組み込まれていますか?(ここでJ noobを完了します)
Claudiu

@Claudiu評価のたびxに、リストの最後に文字を追加することにより、拡張精度の数値(この場合は有理数)を強制します。
-randomra

3

Python 2、220文字

import re,sys,math as m,fractions as f
X=f.Fraction
M=map
F=['+']+re.split("(\D)",sys.argv[1])
r=[X(0)]
while F:U=[eval('f.'+`n`+F[0]+F[1])for n in r];r=M(X,U+M(m.floor,U)+M(m.ceil,U));F=F[2:]
print sorted(set(M(int,r)))

可能なすべての番号のリストを保持し、重複がある場合でも、各ステップで、リスト内のすべての番号に対して3つの番号を生成します。したがって、実行時の複雑さは指数関数的です。ただし、これらの小さな例ではすぐに動作します。デュープは最後に削除されます。

fractions.Fraction浮動小数点の不正確さを避けて、正確な除算を行うために使用します。

5文字(r=map(X,g)-> r=set(map(X,g)))を追加して、パフォーマンスを劇的に向上させます。


ここでオフに開始するための簡単なゴルフです:\D非数字にマッチするための定義済みの文字クラスがある
SP3000

@orlp:今すぐ修正!(私は思う..)
Claudiu

@Claudiu:r"(\D)"またはのいずれか"(\\D)"です。また、Python 3を使用している場合は、インデックス付けFをスター付き割り当てに置き換えることができます。たとえばA,B,*F=FAandのB代わりにF[0]andを使用しF[1]、を取り除きF=F[2:]ます。
Macの

@Mac:"\D"とにかく動作し、短くなります。Pythonはちょうど含まれますので、有効なエスケープシーケンスではありません\ し、D逐語的に。Python3の良いヒントです。チェックしてみますが、バックティックを置き換えてrepr()map結果をリストに変換する必要があります。スターを付けた割り当ては..私はPythonの2よかったものです
クラウディウ

2

Python、421 370 354バイト

すみません、我慢してください。私は本当にPythonを初めて使用し(fractiosnをサポートする言語を探していました)、コードを短縮するために知っていたいくつかのトリックをすべて使用しましたが、ほぼ半分のサイズのPythonソリューションがあることを考えるとまだモンスターです。私は多くを学び、とにかくそれを提出すると思いました=)

@ kirbyfan64sosと@Zgarbのおかげで新しいバージョン

from fractions import*
from math import*
import re,operator as z
s=input()
N=re.split(r'[\*\/\-\+]',s)
O=re.split(r'[0-9]+',s)[1:-1]
d={'+':z.add,'-':z.sub,'*':z.mul,'/':z.truediv}
l=[int(N[0])]#list of inters up to now
for i in range(len(O)): #iterate over all operations
    n=set()
    for f in l:
        f=d[O[i]](f,Fraction(int(N[i+1])))
        n.update([floor(f),ceil(f),f])
    l=n
print(set(map(floor,n)))

古いバージョン

from fractions import Fraction as F
from math import floor,ceil
import re
s=input()
N=re.split(r'[\*\/\-\+]',s)   #Numbers
O=re.split(r'[0-9]+',s)[1:-1] #Operators
l=[int(N[0])]
for i in range(len(O)): #Iterate over all operators
    n=set()
    for f in l:           #Iterate over all possible numbers
        g=F(int(N[i+1]))
        o=O[i]
        if o=='/':
            f/=g
        elif o=='*':
            f*=g
        elif o=='-':
            f-=g
        else:
            f+=g
        n.add(floor(f))  #Add all possible numbers to a new set 
        n.add(ceil(f))   # the 'set' structure prevents from having multiple copies
        n.add(f)         # which is a really nice feature
    l=n                #repeat
print(set([floor(k) for k in n])) #also remove the unrounded ones

ひとつには、スペースのインデントの一部をタブに置き換えることができます(一般的には残念ですが、コードゴルフではうまく機能します:タブ== 1文字)。いくつかifのs(d={'+': operator.add, '-': operator.sub, ...}; d[op](a, b))の代わりに辞書を使用することもできます。また、[floor(k) for k in n]に短縮できmap(floor, n)n.add呼び出しはになりn.extend([floor(f), ceil(f), f])ます。
kirbyfan64sos

本当にありがとうございました、私はそれらを試して実装するつもりです!私はすでにインデントをタブとして数えていましたが、ここではスペースに変換する必要がありました。
-flawr

単一のスペースを使用することもできます。彼らは動作するはずです。
kirbyfan64sos

私が見る限り、あなたはF一度だけ使用するので、あなたはfrom fractions import*いくつかのバイトを保存できます。と同じmath。周囲のスペースを削除します=。これらは不要です。また、sハードコーディングの代わりに入力を割り当てる必要があります。
ズガルブ

@flawrオプションのスペースをすべて削除します。また、あなたが受け入れることができるようにする必要があります任意の入力を。使用するs=input()よりもs = "1/3*9"、コメントを削除するなど
-mbomb007

1

Mathematica、134

Union@Flatten@{Floor@#,Ceiling@#}&@ToExpression@StringReplace[#,x:("+"|"-"|"*"|"/"~~NumberString):>"//{Floor@#,#,Ceiling@#}"~~x~~"&"]&

0

MATLAB、283文字

function[u]=w(s)
s=[' ' strsplit(regexprep(s,'\D',' $& '))];s=reshape(s,[2,size(s,2)/2]);o=s(1,:);d=cellfun(@str2num,s(2,:));a=d(1);for n=2:size(o,2)switch o{n}case'+';a=a+d(n);case'-'a=a-d(n);case'/'a=a/d(n);case'*'a=a*d(n);end;a=[ceil(a);a;floor(a)];end;u=unique(a(mod(a,1)==0))end

ゴルフをしていない:

function [u] = WingitRound(i)
    i=[' ' strsplit(regexprep(i,'\D',' $& '))];
    i=reshape(i,[2,size(i,2)/2]);

    o=i(1,:);
    n=cellfun(@str2num,i(2,:));

    a=n(1);

    for n=2:size(o,2)
        switch o{n}
            case '+'
                a = a + n(n);
            case '-'
                a = a - n(n);
            case '/'
                a = a / n(n);
            case '*'
                a = a * n(n);
        end
        a = [ceil(a);a;floor(a)];
    end

    u=unique(a(mod(a,1)==0)));
end

これを書いている間、私はこれを行うより短い方法があることに気づきました。それを書き終えたら追加します。


0

VBA、347バイト

Function OoCRE(inp As String)
ct = 0
i = 1
Do While i < Len(inp)
c = Mid(inp, i, 1)
If Not IsNumeric(c) Then
ct = ct + 1
If ct = 2 Then
inp = Round(Application.Evaluate(Left(inp, i - 1))) & Right(inp, Len(inp) - (i - 1))
i = InStr(1, inp, c)
ct = 1
End If
End If
OoCRE = Round(Application.Evaluate(inp))
i = i + 1
Loop
End Function

1
主に余分に空白文字を削除し、短いVAR名を選択する、ここで行われるゴルフのかなり多くがあります
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.