ย้อนกลับสถิติการสำรวจความคิดเห็นของวิศวกร


22

บทนำ

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

ตัวอย่าง: สัตว์เลี้ยงตัวโปรดของคุณคืออะไร?

  • หมา: 44.4%
  • แมว: 44.4%
  • เมาส์: 11.1%

เอาต์พุต: 9(จำนวนผู้ลงคะแนนต่ำสุดที่เป็นไปได้)

รายละเอียด

นี่คือข้อกำหนดสำหรับโปรแกรม / ฟังก์ชั่นของคุณ:

  • คุณจะได้รับอาร์เรย์ของค่าร้อยละเป็นอินพุต (บน stdin, เป็นฟังก์ชั่นการโต้แย้ง ฯลฯ )
  • ค่าเปอร์เซ็นต์แต่ละค่าจะถูกปัดเศษเป็นทศนิยมหนึ่งตำแหน่ง (เช่น, 44.4 44.4 11.1)
  • คำนวณจำนวนผู้ลงคะแนนขั้นต่ำที่เป็นไปได้ในการสำรวจความคิดเห็นซึ่งผลลัพธ์จะให้เปอร์เซ็นต์ที่แน่นอนเมื่อปัดเศษเป็นทศนิยมหนึ่งตำแหน่ง (บน stdout หรือค่าส่งคืนฟังก์ชัน)
  • โบนัส : -15 ตัวอักษรหากคุณสามารถแก้ปัญหาได้ในแบบ "ไม่สำคัญ" (กล่าวคือไม่เกี่ยวข้องกับการวนซ้ำของจำนวนผู้มีสิทธิเลือกตั้งที่เป็นไปได้ทั้งหมดจนกว่าคุณจะพบคนแรกที่ทำงาน)

ตัวอย่าง

>./pollreverse 44.4 44.4 11.1
9
>./pollreverse 26.7 53.3 20.0
15
>./pollreverse 48.4 13.7 21.6 6.5 9.8
153
>./pollreverse 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 99.6
2000
>./pollreverse 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 98.7
667
>./pollreverse 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 98.7
2000
>./pollreverse 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 97.8
401

เกณฑ์การให้คะแนน

นี่คือโค้ดกอล์ฟดังนั้นตัวละครที่สั้นที่สุดจึงชนะ โบนัสใด ๆ จะถูกหักออกจากจำนวนตัวอักษรทั้งหมด


2
ฉันคิดว่านี่น่าจะเป็นกรณีทดสอบที่น่าอึดอัดใจอีกสองสามข้อ 26.7 53.3 20.0(4 8 3 จาก 15), 48.4 13.7 21.6 6.5 9.8(74 21 33 10 15 จาก 153) ฯลฯ
Gareth

@Gareth: ความคิดที่ดี อัปเดตกับกรณีทดสอบของคุณ
mellamokb

ไม่ควรรวมคะแนนทั้งหมดเป็น 100%? มันไม่ได้อยู่ในชุดทดสอบสี่ชุดสุดท้าย
Ali1S232

@Gajet: ไม่เสมอไปไม่เท่ากับ 100% ทุกครั้งที่มีการปัดเศษคุณจะสูญเสียไป0.5%จากยอดรวมและทุกครั้งที่มีการปัดเศษขึ้นคุณจะเพิ่ม0.5%เป็นยอดรวม กรณีทดสอบสี่ชุดสุดท้ายถูกสร้างขึ้นโดยมีจุดประสงค์เพื่อใช้ประโยชน์จากปรากฏการณ์นี้อย่างเหมาะสมที่สุด ในกรณีทดสอบครั้งแรกที่ส่งผล2000ให้แต่ละ 9 รายการแรกแสดงถึงการ1ลงคะแนน (และถูกปัดเศษขึ้นทั้งหมด0.5%) ในขณะที่รายการสุดท้ายแทนการ1991ลงคะแนน (และถูกปัดเศษ ~ 0.5%) หากคุณคำนวณเปอร์เซ็นต์เหล่านั้นด้วยตนเองและปัดเศษทศนิยมเป็น 1 คุณจะเห็นว่าถูกต้องทั้งหมด
mellamokb

ฉันกำลังดิ้นรนกับคำตอบที่ไม่น่ารำคาญใน VBA (พยายามมาตั้งแต่ตอนนี้ยังไม่มีใคร) แต่ฉันกำลังทำอยู่!
Gaffi

คำตอบ:


2

APL (Dyalog Classic) , 48 43 ไบต์

-5 ไบต์โดยAdám

+/0(⊢+{(⌈/⍷⊢)⍺-⍵÷+/⍵})⍣{z≡⍎3⍕⍺÷+/⍺}⍨z←.01×⎕

โปรแกรมเต็มรูปแบบการป้อนข้อมูลจาก stdin

ลองออนไลน์! ลิงก์คือเวอร์ชันของ dfn

Ungolfed

normalize   ÷ +/
find_max  {⍵⍷⍨⌈/⍵}
round  {⍎3⍕⍵}
increase  {find_max  - normalize ⍵}
vote_totals  {z←⍺   (⊢+increase)⍣{z  round normalize ⍺} ⍵}
h  {+/ (.01×⍵) vote_totals 0}

ลองออนไลน์!

  • normalizeหาร ( ÷) องค์ประกอบทั้งหมดของอาร์กิวเมนต์ที่ถูกต้อง ( ) โดยผลรวมของมัน ( +/)
  • round(y)ปัดเศษทศนิยมเป็น y ถึง 3 โดยการจัดรูปแบบ ( ) แล้วประเมิน ( ) แต่ละองค์ประกอบของ y
  • find_max(y) ส่งคืนอาร์เรย์ที่มี 1 เมื่อพบ max (y) และ 0 ที่อื่น
  • increase(x,y) ใช้ x (เปอร์เซ็นต์เป้าหมาย) และ y (อาร์เรย์ของผลรวมการโหวตปัจจุบัน) และคำนวณตำแหน่งที่จะเพิ่ม 1 ใน y เพื่อให้เปอร์เซ็นต์ใกล้กับ x
  • vote_totals(x,y) ใช้ x (เปอร์เซ็นต์เป้าหมาย) และ y (ผลรวมคะแนนเริ่มต้น) และดำเนินการ f ซ้ำ ๆ เพิ่มคะแนนจนกระทั่งเปอร์เซ็นต์รอบเป็น x
    • ไวยากรณ์f ⍣ gหมายถึงการดำเนินการfซ้ำ ๆ จนกระทั่งg(y,f(y))เป็นจริง f(y)ในกรณีนี้เราไม่สนใจ
  • h(x) ตั้งค่า y เป็น 0 (เทียบเท่ากับอาร์เรย์ของ 0s เนื่องจาก vectorization) ดำเนินการ g และรวมผลรวมการลงคะแนนรอบสุดท้าย

7

Python, 154

def p(x):
 n=[1]*len(x);d=2;r=lambda z:round(1000.*z/d)/10
 while 1:
    if(map(r,n),sum(n))==(x,d):return d
    d+=1
    for i in range(len(x)):n[i]+=r(n[i])<x[i]

มันใช้งานได้สำหรับตัวอย่างสุดท้ายในขณะนี้

ตัวอย่างการทำงาน:

>>> p([44.4, 44.4, 11.1])
9
>>> p([26.7, 53.3, 20.0])
15
>>> p([48.4, 13.7, 21.6, 6.5, 9.8])
153
>>> p([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 99.6])
2000
>>> p([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 98.7])
667
>>> p([0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 98.7])
2000
>>> p([0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 97.8])
401

ฉันคิดว่ามีบางอย่างผิดปกติในตัวอย่างสุดท้ายของคุณ บางทีคุณอาจหมายถึง99.1ค่าสุดท้าย
Cristian Lupascu

2
ฉันคิดว่ามันถูกต้อง แต่มันค่อนข้างสับสน 1/2000 = 0.05%( 0.1%ปัดเศษ) และ1991/2000 = 99.55%( 99.6%ปัดเศษ) ดังนั้นหากมีตัวเลือก 10 ข้อในการสำรวจความคิดเห็นและอีกเก้าข้อได้รับการโหวตหนึ่งครั้งในขณะที่การโหวตครั้งสุดท้ายได้รับการลงคะแนน 1991 มันจะให้เปอร์เซ็นต์เหล่านั้น
grc

คุณถูก. ทางออกที่ดี BTW
Cristian Lupascu

ฉันคิดว่าคุณสามารถบันทึกได้อีก 3 ตัวอักษรโดยทำตามเคล็ดลับนี้: codegolf.stackexchange.com/a/58/3527
Cristian Lupascu

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

4

J, 57 ตัวอักษร

t=:".>'1'8!:0|:100*%/~i.1001
{.I.*/"1(t{~i.#t)e."1~1!:1[1

ใช้วิธีการเล็กน้อย ใช้อินพุตจากแป้นพิมพ์ tสร้างตารางการค้นหาและบรรทัดที่สองจะค้นหาอินพุตภายในตาราง ฉันสามารถให้คำอธิบายเพิ่มเติมของรหัสหากใครสนใจ

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


อืมสิ่งนี้ล้มเหลวสำหรับกรณีทดสอบใหม่ ฉันจะต้องหาวิธีแก้ไข
Gareth

4

Python, 154

def r(l):
 v=0
 while 1:
  v+=1;o=[round(y*v/100)for y in l];s=sum(o)
  if s: 
    if all(a==b for a,b in zip(l,[round(y*1000/s)/10for y in o])):return s

+1 ดูดี! ideone.com/k2Mgb ฉันพยายามค้นหากรณีทางพยาธิวิทยาเพื่อทำลายมันและฉันทำไม่ได้
mellamokb

ฉันไม่สามารถสร้าง ideone ได้เนื่องจากเกินเวลาที่กำหนด แต่คุณจะได้ผล[0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,99.6]อะไร
mellamokb

อืม ... ครึ่งชั่วโมงและโปรแกรมยังทำงานอยู่ ฉันคิดว่ามันอาจจะปลอดภัยที่จะบอกว่าเป็นเครื่องบด แต่ฉันไม่เห็นว่าเป็นคำตอบที่ถูกต้องเพราะมันรวม 100.5% และไม่ใช่ 100%
Blazer

2
1/2000 = 0.05%( 0.1%ปัดเศษ) และ1991/2000 = 99.55%( 99.6%ปัดเศษ) จริง ๆ แล้วมันรวม 100% แต่การปัดเศษทำให้สับสนจริงๆ
grc

3

VBA - 541

นี่เป็นข้อผิดพลาดบางอย่างที่เห็นได้ชัด แต่ฉันพยายามหาวิธีแก้ปัญหาที่ไม่น่าสนใจ / วนซ้ำจนกว่าฉันจะได้หมายเลขที่ถูกต้อง ฉันเล่นกอล์ฟไม่เต็มที่แม้ว่าฉันจะไม่คิดว่าจะมีอะไรเพิ่มในเรื่องนั้นอีก อย่างไรก็ตามฉันใช้เวลากับเรื่องนี้มากเกินไปและมันทำให้ฉันปวดหัวในตอนนี้ ไม่พูดถึงกฎอาจจะแตกหักมากและใช้มากหรือน้อยกับตัวอย่างเหล่านี้เท่านั้น

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

งานส่วนใหญ่เกี่ยวข้องกับการค้นหา gcd สำหรับชุดของตัวเลขที่ให้ไว้และฉันเรียงลำดับได้ผ่านFunction g()แม้ว่ามันจะไม่สมบูรณ์และน่าจะเป็นแหล่งที่มาของข้อผิดพลาดบางอย่างในผลลัพธ์ของฉัน

อินพุตเป็นสตริงของค่าที่คั่นด้วยช่องว่าง

Const q=10^10
Sub a(s)
e=Split(s)
m=1
f=UBound(e)
For i=0 To f
t=1/(e(i)/100)
m=m*t
n=IIf(n>t Or i=0,t,n)
x=IIf(x<t Or i=0,t,x)
Next
h=g(n,x)
i=(n*x)/(h)
If Int(i)=Round(Int(i*q)/q) Then
r=i
ElseIf (n+x)=(n*x) Then
r=(1/(n*x))/h/m
ElseIf x=Int(x) Then
r=x*(f+1)
Else
z=((n+x)+(n*x)+m)*h
y=m/(((m*h)/(f+1))+n)
r=IIf(y>z,z,y)
End If
Debug.Print Round(r)
End Sub
Function g(a,b)
x=Round(Int(a*q)/q,3)
y=Round(Int(b*q)/q,3)
If a Then
If b Then
If x>y Then
g=g(a-b,b)
ElseIf y>x Then
g=g(a,b-a)
Else
g=a
End If
End If
Else
g=b
End If
End Function

Testcases (อินพุต ==> คาดหวัง / ส่งคืน):

Passed:  

"95 5" ==> 20/20
"90 10" ==> 10/10
"46.7 53.3" ==> 15/15
"4.7 30.9 40.4 23.8" ==> 42/42
"44.4 44.4 11.1" ==> 9/9
"26.7 53.3 20.0" ==> 15/15
"48.4 13.7 21.6 6.5 9.8" ==> 153/153
"0.05 0.05 0.05 0.05 0.05 0.05 0.05 0.05 0.05 99.55" ==> 2000/2000
"0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 98.65" ==> 2000/2000
"0.149925 0.149925 0.149925 0.149925 0.149925 0.149925 0.149925 0.149925 0.149925 98.65067" ==> 667/667


Failed:  

"0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 99.6" ==> 2000/1000
"0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 98.7" ==> 2000/5000
"0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 98.7" ==> 667/1000
"0.14 0.14 0.14 0.14 0.14 0.14 0.14 0.14 0.14 98.65" ==> 667/10000
"0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 97.8" ==> 401/500
"0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 97.75" ==> 401/235
"0.249377 0.249377 0.249377 0.249377 0.249377 0.249377 0.249377 0.249377 0.249377 97.75561" ==> 401/14010

คุณสามารถหลวม 6 ไบต์โดยแปลงDebug.Print เป็นDebug.?
Taylor Scott

2

C # (. NET Core) 286 ไบต์

double M(string[]a){var p=a.Select(double.Parse).ToList();var n=p.Select(x=>1d).ToList();var c=2;for(;;){Func<double,double>f=x=>Math.Round(x*1000/c,(MidpointRounding)1)/10;if(n.Select(f).Zip(p,(x,y)=>x==y).All(z=>z)&&c==n.Sum())return c;c++;n=n.Zip(p,(x,y)=>x+(f(x)<y?1:0)).ToList();}}

ลองออนไลน์!

จำนวนไบต์ที่บันทึกไว้ต้องขอบคุณPeter Taylorและศูนย์รวมแห่งความไม่รู้


ฉันจะแก้ไขสิ่งนี้เพื่อทดสอบบน ideone.com ได้อย่างไร
Gareth

ฉันคิดว่าคุณหายไป}ในตอนท้าย
grc

@Gareth ฉันพยายามเรียกใช้งานบน ideone.com แต่ฉันคิดว่ามันใช้. NET Framework เวอร์ชั่นก่อนหน้า 4.0 เพราะมันไม่รู้จักZipเมธอดLinq
Cristian Lupascu

@grc ขอบคุณสำหรับการชี้ให้เห็นว่า Updated
Cristian Lupascu

1
@Gaffi: ไม่ C # มีการพิมพ์ที่เข้มงวด (เช่น Java) ดังนั้นจึงต้องเป็นบูลีน เนื่องจาก1>0สั้นกว่าtrueจึงเป็นที่ต้องการ
mellamokb

0

Python 3 , 140 139 137 ไบต์

f=lambda l,m=1,i=0,c=0,x=0:round(x*100,1)-l[i]and(x<1and f(l,m,i,c,x+1/m)or f(l,m+1))or l[i+1:]and f(l,m,i+1,c+x)or c+x-1and f(l,m+1)or m

ลองออนไลน์!

ให้คำตอบที่ถูกต้องสำหรับสองกรณีทดสอบแรกและวิ่งเข้าไปในขอบเขตการเรียกซ้ำของ Python สำหรับผู้อื่น ไม่น่าแปลกใจนักเนื่องจากทุกการตรวจสอบเกิดขึ้นในระดับการเรียกซ้ำ มันสั้น แต่ ...

(คำอธิบายของตัวแปรที่ใช้สามารถพบได้ในลิงค์ TIO)

f=lambda l,m=1,i=0,c=0,x=1:round(x*100,1)-l[i]and(x and f(l,m,i,c,x-1/m)or f(l,m+1))or l[i+1:]and f(l,m,i+1,c+x)or c+x-1and f(l,m+1)or m

ควรทำงานได้136ไบต์ แต่ไม่ใช่เนื่องจากความแม่นยำในการลอย

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