ข้อผิดพลาดในการปัดเศษออกควบคุม


14

พื้นหลัง

คุณเพิ่งได้รับการว่าจ้างจาก บริษัท บัญชีขนาดเล็ก โลกของการบัญชีนั้นค่อนข้างต่างกับคุณดังนั้นคุณไม่แน่ใจว่าคุณกำลังทำตามแนวทางวิชาชีพทั้งหมดหรือไม่ โดยเฉพาะอย่างยิ่งคุณไม่ทราบว่าเมื่อใดที่คุณควรปัดเศษตัวเลขเหล่านั้นทั้งหมดและไปในทิศทางใดดังนั้นเวลาส่วนใหญ่ที่คุณเพิ่งจะใช้และหวังว่าจะได้สิ่งที่ดีที่สุด

อินพุต

อินพุตของคุณเป็นสตริงเดี่ยวที่แสดงถึงการคำนวณอย่างง่าย +-*/มันมีตัวเลขของจำนวนเต็มไม่ติดลบบางส่วนคั่นด้วยตัวอักษร สตริงอ่านจากซ้ายไปขวาและกฎความสำคัญปกติจะถูกละเว้นดังนั้น"23+1*3/4"หมายความว่า "เริ่มต้นด้วย 23 เพิ่ม 1 คูณด้วย 3 และหารด้วย 4" ผลลัพธ์คือ 18 อินพุตจะไม่ประกอบด้วยตัวเลขที่ขึ้นต้นด้วย0(ยกเว้น0ตัวเอง) หรือหารด้วยศูนย์

เอาท์พุต

ในแต่ละขั้นตอนของการคำนวณคุณสามารถปัดเศษผลลัพธ์ขึ้นหรือลงให้เป็นจำนวนเต็มที่ใกล้เคียงที่สุดหรือเก็บตามที่มันเป็น ในที่สุดคุณปัดขึ้นหรือลงเพื่อให้ได้ผลลัพธ์จำนวนเต็ม ผลลัพธ์ของคุณคือรายการจำนวนเต็มที่อาจเป็นผลมาจากการคำนวณเรียงลำดับและไม่มีการซ้ำซ้อน

กฎระเบียบ

คุณสามารถเขียนโปรแกรมเต็มหรือฟังก์ชั่น จำนวนไบต์ต่ำสุดที่ชนะและช่องโหว่มาตรฐานไม่ได้รับอนุญาต

กรณีทดสอบ

"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 มันควรจะทำงานอย่างน้อยเมื่อตัวเลขอินพุตและผลลัพธ์ระดับกลางทั้งหมดต่ำกว่า 10 ล้านค่าสัมบูรณ์ บริษัท บัญชีมีขนาดเล็กหลังจากทั้งหมด
Zgarb

จดกรณีทดสอบ1/3*9ซึ่งอาจล้มเหลวหากคุณใช้หมายเลขจุดลอยตัว
Claudiu

@ 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

@Caludiu ทุก ๆ การประเมินผลฉันบังคับให้มีการเพิ่มจำนวนความแม่นยำ (ในกรณีนี้คือการปันส่วน) โดยการเพิ่มตัวอักษร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)))

มันจะเก็บรายการของตัวเลขที่เป็นไปได้ทั้งหมดและในแต่ละขั้นตอนจะสร้างตัวเลขสามตัวสำหรับทุกหมายเลขในรายการแม้ว่าจะมีซ้ำกันก็ตาม ดังนั้นความซับซ้อนของรันไทม์จึงเป็นเลขยกกำลัง อย่างไรก็ตามมันใช้งานได้ทันทีสำหรับตัวอย่างเล็ก ๆ เหล่านี้ ซ้ำจะถูกลบออกในตอนท้าย

มันใช้fractions.Fractionในการแบ่งแน่นอนหลีกเลี่ยงความไม่แน่นอนของจุดลอยตัว

เพิ่ม 5 ตัวอักษร ( r=map(X,g)-> r=set(map(X,g))) เพื่อเพิ่มประสิทธิภาพอย่างมาก


นี่คือสนามกอล์ฟที่ง่ายในการเริ่มต้นด้วย: \Dเป็นคลาสของตัวละครที่กำหนดไว้ล่วงหน้าสำหรับการจับคู่ที่ไม่ใช่ตัวเลข
Sp3000

@orlp: แก้ไขทันที! (ฉันคิดว่า .. )
Claudiu

@Claudiu: ที่ควรจะเป็นอย่างใดอย่างหนึ่งหรือr"(\D)" "(\\D)"นอกจากนี้ถ้าคุณใช้งูหลาม 3 คุณสามารถเปลี่ยนการจัดทำดัชนีลงFมีการกำหนดติดดาวเช่น: A,B,*F=Fการใช้AและการBแทนF[0]และและได้รับการกำจัดF[1] F=F[2:]
Mac

@Mac: "\D"สิ้นสุดการทำงานต่อไปและมันก็สั้นลง มันไม่ใช่ลำดับการหลบหนีที่ถูกต้องดังนั้น Python จึงรวม\ และDคำต่อคำ เคล็ดลับ Python3 ดีจริงฉันจะลองดูแม้ว่าฉันจะต้องแทนที่ backticks ด้วยrepr()และเปลี่ยนmapผลลัพธ์เป็นรายการ การติดดาวเป็นสิ่งที่ฉันต้องการให้ Python 2 มี ..
Claudiu

2

Python 421 370 354 ไบต์

ขออภัยโปรดอดทนกับฉัน ฉันยังใหม่กับงูหลาม (ฉันแค่มองหาภาษาที่รองรับ fractiosn) และใช้ลูกเล่นบางอย่างที่ฉันรู้จักเพื่อทำให้รหัสสั้นลง แต่มันก็ยังเป็นสัตว์ประหลาดที่คิดว่ามีวิธีแก้ปัญหางูหลามที่มีขนาดเกือบครึ่งหนึ่ง ฉันเรียนรู้มากและคิดว่าฉันจะส่งมันต่อไป =)

เวอร์ชันใหม่ต้องขอบคุณ @ 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

สำหรับสิ่งหนึ่งคุณสามารถแทนที่เยื้องพื้นที่บางส่วนด้วยแท็บ (โดยทั่วไปแล้วมันแย่มาก แต่ทำงานได้ดีใน code golf: a tab == 1 ตัวอักษร) นอกจากนี้คุณยังสามารถใช้ dict แทนหลาย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

ว้าวขอบคุณมากฉันจะลองและใช้มัน! ฉันนับการเยื้องเป็นแท็บทั้งหมด แต่ฉันต้องแปลงเป็นช่องว่างที่นี่
ข้อบกพร่อง

คุณสามารถใช้ช่องว่างเดียว พวกเขาควรทำงาน
kirbyfan64sos

เท่าที่ฉันเห็นคุณใช้Fเพียงครั้งเดียวดังนั้นคุณสามารถทำได้from fractions import*และบันทึกบางไบต์ mathเช่นเดียวกันกับ ลบช่องว่างรอบ ๆ ออก=โดยไม่จำเป็น นอกจากนี้คุณควรกำหนดอินพุตให้sแทนการเข้ารหัสฮาร์ด
Zgarb

@flawr ลบทุกพื้นที่ไม่จำเป็น นอกจากนี้คุณต้องสามารถรับอินพุตใด ๆได้ ใช้s=input()แทนs = "1/3*9"ลบความคิดเห็นของคุณ ฯลฯ
mbomb007


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

Ungolfed:

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 ที่สั้นกว่า
cat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.