失控舍入错误


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 2015年

@orlp它应该至少在所有输入数字和中间结果的绝对值都低于1000万时才起作用。毕竟,会计师事务所很小。
Zgarb 2015年

注意测试用例1/3*9,如果使用浮点数,则可能会失败。
Claudiu 2015年

@Claudiu谢谢,我将其添加到了挑战中。
Zgarb 2015年

Answers:


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 2015年

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)))

它会保留所有可能数字的列表,并在每个步骤中为列表中的每个数字生成三个数字,即使有重复也是如此。因此,运行时复杂度是指数级的。但是,对于这些小例子,它立即起作用。最终将重复删除。

它用 fractions.Fraction进行精确除法,避免浮点不正确。

添加5个字符(r=map(X,g)-> r=set(map(X,g)))可大大提高性能。


这是一个容易开始的高尔夫:\D是预定义的字符类,用于匹配非数字
Sp3000,2015年

@orlp:现在修复!(我认为..)
Claudiu

@Claudiu:应该是r"(\D)""(\\D)"。另外,如果您使用Python 3,则可以用F加星标的赋值替换索引,例如:A,B,*F=F,使用Aand B代替F[0]and F[1],并摆脱F=F[2:]
Mac

@Mac:"\D"无论如何最终都可以工作,而且时间更短。这不是有效的转义序列,因此Python仅包含\ and 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个字符)。您也可以使用字典而不是几个ifs(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 2015年

哇,非常感谢您,我将尝试实施它们!我已经把缩进算作制表符了,但是我不得不将它们转换成空格。
瑕疵的

您也可以只使用一个空格。他们应该工作。
kirbyfan64sos 2015年

据我所知,您F只使用一次,因此可以from fractions import*保存一些字节。与相同math。删除周围的空格=,它们是不必要的。另外,您应该将输入分配给s而不是硬编码。
Zgarb 2015年

@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名称
2015年
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.