Lỗi làm tròn ngoài tầm kiểm soát


14

Lý lịch

Gần đây bạn đã được thuê bởi một công ty kế toán nhỏ. Thế giới kế toán có phần xa lạ với bạn, vì vậy bạn không chắc mình có tuân theo tất cả các hướng dẫn chuyên môn hay không. Cụ thể, bạn không biết khi nào bạn nên làm tròn tất cả những con số đó và theo hướng nào, vì vậy, hầu hết thời gian bạn chỉ chắp cánh và hy vọng điều tốt nhất.

Đầu vào

Đầu vào của bạn là một chuỗi đại diện cho một phép tính đơn giản. Nó chứa một số số nguyên không âm được phân định bởi các ký tự +-*/. Chuỗi đọc từ trái sang phải và các quy tắc ưu tiên thông thường bị bỏ qua, do đó, "23+1*3/4"có nghĩa là "bắt đầu bằng 23, thêm 1, nhân 3 và chia cho 4", kết quả là 18. Đầu vào sẽ không chứa các số bắt đầu bằng 0(ngoại trừ 0chính nó), cũng không chia cho số không.

Đầu ra

Ở mỗi giai đoạn tính toán, bạn có thể làm tròn kết quả lên hoặc xuống số nguyên gần nhất hoặc giữ nguyên như vậy. Cuối cùng, bạn làm tròn lên hoặc xuống để có kết quả số nguyên. Đầu ra của bạn là danh sách các số nguyên có thể xuất phát từ phép tính như vậy, được sắp xếp và không trùng lặp.

Quy tắc

Bạn có thể viết một chương trình đầy đủ hoặc một chức năng. Số byte thấp nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

Các trường hợp thử nghiệm

"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]

Chương trình có phải làm việc cho tất cả các đầu vào có thể (bất kể kích thước số), đầu vào kích thước giới hạn hoặc chỉ các trường hợp thử nghiệm không?
orlp

@orlp Nó sẽ hoạt động ít nhất khi tất cả các số đầu vào và kết quả trung gian ở dưới, giả sử, 10 triệu giá trị tuyệt đối. Các công ty kế toán là nhỏ, sau khi tất cả.
Zgarb

Lưu ý trường hợp kiểm tra 1/3*9, có thể thất bại nếu bạn sử dụng số dấu phẩy động.
Claudiu

@Claudiu Cảm ơn, tôi đã thêm nó vào thử thách.
Zgarb

Câu trả lời:


4

J, 84 byte

Bắt đầu từ danh sách 1 phần tử, hàm giữ tất cả các số trung gian có thể có trong danh sách bằng cách xóa biểu thức tiếp theo và thêm các bản sao được làm tròn lên và xuống.

Sẽ chơi gôn thêm và giải thích thêm vào ngày mai. Không thể tìm thấy những cách rõ ràng để chơi golf nhiều hơn.

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

Vượt qua tất cả các bài kiểm tra.

Sử dụng:

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

Hãy thử nó ở đây.


Làm thế nào để bạn đối phó với chúng như là lý trí thay vì phao - được xây dựng trong J? (Hoàn thành J noob tại đây)
Claudiu

@Claudiu Tại mỗi eval tôi buộc các số chính xác mở rộng (trong trường hợp này là hợp lý) bằng cách nối thêm chữ cái xở cuối danh sách.
ngẫu nhiên

3

Python 2, 220 ký tự

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

Nó giữ một danh sách tất cả các số có thể và ở mỗi bước, tạo ra ba số cho mỗi số trong danh sách, ngay cả khi có các bản sao. Do đó, độ phức tạp thời gian chạy là theo cấp số nhân. Tuy nhiên, nó hoạt động ngay lập tức cho những ví dụ nhỏ này. Dupes được loại bỏ ở cuối.

Nó sử dụng fractions.Fractionđể thực hiện phân chia chính xác, tránh sự thiếu chính xác điểm nổi.

Thêm 5 ký tự ( r=map(X,g)-> r=set(map(X,g))) để tăng hiệu suất đáng kể.


Đây là một môn đánh gôn dễ dàng để bắt đầu: \Dlà một lớp nhân vật được xác định trước để khớp với các chữ số không
Sp3000

@orlp: Đã sửa ngay! (Tôi nghĩ rằng ..)
Claudiu

@Claudiu: nên là r"(\D)"hoặc "(\\D)". Ngoài ra, nếu bạn sử dụng Python 3, bạn có thể thay thế việc lập chỉ mục thành Fgán gán có sao, ví dụ : A,B,*F=F, sử dụng ABthay vì F[0]F[1], và loại bỏ F=F[2:].
Mac

@Mac: "\D"cuối cùng vẫn hoạt động và nó ngắn hơn. Đây không phải là một chuỗi thoát hợp lệ vì vậy Python chỉ bao gồm \ Dnguyên văn. Mẹo Python3 tốt thực sự, tôi sẽ kiểm tra nó, mặc dù tôi sẽ phải thay thế backticks bằng repr()và biến mapkết quả thành một danh sách. Nhiệm vụ được gắn dấu sao là điều tôi ước Python 2 có ..
Claudiu

2

Python, 421 370 354 byte

Xin lỗi, xin hãy chịu đựng với tôi. Tôi thực sự mới với python (tôi chỉ tìm kiếm một ngôn ngữ hỗ trợ fractiosn) và sử dụng tất cả các thủ thuật mà tôi biết để rút ngắn mã nhưng nó vẫn là một con quái vật khi xem xét rằng có một giải pháp python có kích thước gần một nửa. Tôi đã học được rất nhiều và nghĩ rằng dù sao tôi cũng sẽ gửi nó =)

Phiên bản mới nhờ @ kirbyfan64sos và @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)))

Phiên bản cũ

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

Đối với một điều, bạn có thể thay thế một số thụt lề không gian bằng các tab (nó thường rất tệ, nhưng hoạt động tốt trong mã golf: một tab == 1 ký tự). Bạn cũng có thể sử dụng một dict thay vì vài ifs ( d={'+': operator.add, '-': operator.sub, ...}; d[op](a, b)). Ngoài ra, [floor(k) for k in n]có thể rút ngắn map(floor, n)và các n.addcuộc gọi có thể trở thành n.extend([floor(f), ceil(f), f]).
kirbyfan64sos

Wow cảm ơn bạn rất nhiều, tôi sẽ cố gắng thực hiện chúng! Tôi đã sẵn sàng đếm các vết lõm như các tab nhưng tôi phải chuyển đổi chúng thành khoảng trắng ở đây.
flawr

Bạn cũng có thể chỉ sử dụng các không gian duy nhất; họ nên làm việc
kirbyfan64sos

Theo như tôi có thể thấy, bạn Fchỉ sử dụng một lần, vì vậy bạn có thể làm from fractions import*và lưu một số byte. Tương tự với math. Loại bỏ các không gian xung quanh =, chúng là không cần thiết. Ngoài ra, bạn nên gán đầu vào sthay vì mã hóa cứng.
Zgarb

@flawr Xóa mọi không gian tùy chọn. Ngoài ra, bạn cần có khả năng chấp nhận bất kỳ đầu vào. Sử dụng s=input()thay vì s = "1/3*9", xóa nhận xét của bạn, v.v.
mbomb007

1

Toán học, 134

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

0

MATLAB, ký tự 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

Ung dung:

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

Trong khi viết bài này, tôi nhận ra rằng có một cách thậm chí còn ngắn hơn để làm điều này, mà tôi sẽ thêm vào sau khi viết xong.


0

VBA, 347 byte

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
Có khá nhiều việc chơi golf được thực hiện ở đây, chủ yếu là loại bỏ khoảng trắng thừa và chọn tên var ngắn hơn
con mèo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.