Kỹ sư đảo ngược thống kê bỏ phiếu


22

Giới thiệu

Đưa ra một tỷ lệ phần trăm các lựa chọn trong một cuộc thăm dò, tính toán số lượng cử tri tối thiểu phải có trong cuộc thăm dò để tạo ra những thống kê đó.

Ví dụ: Thú cưng yêu thích của bạn là gì?

  • Chó: 44.4%
  • Con mèo: 44.4%
  • Chuột: 11.1%

Đầu ra: 9(số cử tri tối thiểu có thể)

Thông số kỹ thuật

Dưới đây là các yêu cầu cho chương trình / chức năng của bạn:

  • Bạn được cung cấp một mảng các giá trị phần trăm làm đầu vào (trên stdin, làm đối số hàm, v.v.)
  • Mỗi giá trị phần trăm là một số được làm tròn đến một chữ số thập phân (ví dụ 44.4 44.4 11.1:).
  • Tính số lượng cử tri tối thiểu có thể có trong cuộc thăm dò mà kết quả của họ sẽ mang lại tỷ lệ phần trăm chính xác khi được làm tròn đến một vị trí thập phân (trên thiết bị xuất chuẩn hoặc giá trị trả về của hàm).
  • Phần thưởng : -15 ký tự nếu bạn có thể giải theo cách "không tầm thường" (nghĩa là không liên quan đến việc lặp qua mọi # cử tri có thể cho đến khi bạn tìm ra cách đầu tiên hoạt động)

Thí dụ

>./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

Chấm điểm

Đây là môn đánh gôn, vì vậy các nhân vật ngắn nhất có thể thắng. Bất kỳ phần thưởng nào được trừ thêm vào tổng số ký tự.


2
Tôi nghĩ rằng điều này có thể làm với một vài trường hợp khó xử hơn để thử nghiệm. 26.7 53.3 20.0(4 8 3 trên 15), 48.4 13.7 21.6 6.5 9.8(74 21 33 10 15 trên 153), v.v.
Gareth

@Gareth: Suy nghĩ tốt. Cập nhật với các trường hợp thử nghiệm của bạn.
mellamokb

không nên tổng số phiếu là 100%? nó không có trong bốn bản thử nghiệm cuối cùng
Ali1S232

@Gajet: Không, không phải lúc nào cũng bằng 100%. Mỗi lần có một vòng làm tròn, bạn mất đến 0.5%tổng số, và mỗi lần có một vòng làm tròn, bạn cộng lại 0.5%thành tổng số. Bốn trường hợp thử nghiệm cuối cùng được xây dựng có chủ đích để khai thác tối ưu hiện tượng này. Trong trường hợp thử nghiệm đầu tiên có kết quả 2000, mỗi trong số 9 mục đầu tiên đại diện cho 1phiếu bầu (và tất cả được làm tròn lên0.5% ), trong khi trường hợp cuối cùng đại diện cho 1991phiếu bầu (và được làm tròn xuống ~ 0.5%). Nếu bạn tính toán các tỷ lệ phần trăm theo cách thủ công và làm tròn đến 1 chữ số thập phân, bạn sẽ thấy tất cả đều đúng.
mellamokb

Tôi đang vật lộn với câu trả lời không tầm thường trong VBA (cố gắng cho đến nay, không có ai), nhưng tôi đang làm việc với nó!
Gaffi

Câu trả lời:


2

APL (Dyalog Classic) , 48 43 byte

-5 byte bởi Adám

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

Chương trình đầy đủ lấy đầu vào từ stdin.

Hãy thử trực tuyến! Liên kết là phiên bản dfn.

Bị đánh cắp

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

Hãy thử trực tuyến!

  • normalizechia ( ÷) tất cả các phần tử của đối số đúng của nó ( ) cho tổng của nó ( +/).
  • round(y)làm tròn y đến 3 vị trí thập phân bằng cách định dạng ( ) và sau đó đánh giá ( ) từng phần tử của y.
  • find_max(y) trả về một mảng với 1 trong đó max (y) được tìm thấy và 0 ở nơi khác.
  • increase(x,y) lấy x (tỷ lệ phần trăm mục tiêu) và y (mảng tổng số phiếu hiện tại) và tính toán vị trí thêm 1 trong y để đưa tỷ lệ phần trăm gần hơn với x.
  • vote_totals(x,y) lấy x (tỷ lệ phần trăm mục tiêu) và y (tổng số phiếu bắt đầu) và thực hiện f liên tục, thêm phiếu cho đến khi tỷ lệ phần trăm làm tròn thành x.
    • Cú pháp f ⍣ gcó nghĩa là thực thi fnhiều lần cho đến khig(y,f(y)) đúng. Trong trường hợp này, chúng tôi bỏ qua f(y).
  • h(x) đặt y thành 0 (tương đương với một mảng 0 do vector hóa), thực hiện g và tính tổng các phiếu bầu cuối cùng.

7

Con trăn, 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]

Nó hoạt động cho ví dụ cuối cùng bây giờ.

Ví dụ chạy:

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

Tôi nghĩ rằng một cái gì đó có thể sai trong ví dụ cuối cùng của bạn; có lẽ bạn có nghĩa 99.1là giá trị cuối cùng
Cristian Lupascu

2
Tôi nghĩ nó đúng nhưng nó khá khó hiểu. 1/2000 = 0.05%( 0.1%làm tròn) và 1991/2000 = 99.55%( 99.6%làm tròn). Vì vậy, nếu có mười lựa chọn trong một cuộc thăm dò và chín trong số đó được bỏ phiếu một lần trong khi lần cuối cùng nhận được 1991 phiếu bầu, thì nó sẽ cho tỷ lệ phần trăm đó.
grc

Bạn đúng. Giải pháp tuyệt vời, BTW.
Cristian Lupascu

Tôi nghĩ bạn có thể tiết kiệm thêm 3 ký tự bằng cách làm theo mẹo này: codegolf.stackexchange.com/a/58/3527
Cristian Lupascu

Cảm ơn, w0lf. Tôi đã cập nhật nó ngay bây giờ để bao gồm các tab. Các tab hiển thị dưới dạng bốn khoảng trắng nếu có ai thắc mắc.
grc

4

J, 57 ký tự

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

Sử dụng phương pháp tầm thường. Nó nhận đầu vào từ bàn phím. ttạo một bảng tra cứu và dòng thứ hai tìm kiếm đầu vào trong bảng. Tôi có thể cung cấp một lời giải thích mở rộng về mã nếu có ai quan tâm.

Tôi đã xem xét việc sử dụng tỷ lệ phần trăm để tạo ra một phân số sau đó lấy dạng phân số thấp nhất để tìm ra con số, nhưng tôi không thể tìm ra cách để làm cho nó hoạt động với việc làm tròn kết quả.


Hmm, điều này không thành công cho trường hợp thử nghiệm mới. Tôi sẽ phải tìm cách khắc phục.
Gareth

4

Con trăn, 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 Có vẻ tốt! ideone.com/k2Mgb . Tôi đã cố gắng tìm một trường hợp bệnh lý để phá vỡ nó và tôi không thể.
mellamokb

Tôi không thể tạo trên ideone do vượt quá giới hạn thời gian, nhưng bạn nhận được kết quả gì [0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,99.6]?
mellamokb

hmm ... nửa tiếng và chương trình vẫn đang chạy. Tôi nghĩ rằng nó có thể an toàn để nói rằng đó là một breaker. tuy nhiên, tôi không thấy làm thế nào đó có thể là một câu trả lời hợp lệ bởi vì nó có tổng số 100,5% chứ không phải 100%
Blazer

2
1/2000 = 0.05%( 0.1%làm tròn) và 1991/2000 = 99.55%( 99.6%làm tròn). Vì vậy, nó thực sự tổng cộng 100%, nhưng làm tròn làm cho nó thực sự khó hiểu.
grc

3

VBA - 541

Điều này có một số lỗi rõ ràng, nhưng đó là nỗ lực của tôi để tìm một giải pháp không tầm thường / lặp đi lặp lại cho đến khi tôi nhận được số phải. Tôi chưa chơi golf hoàn toàn, mặc dù tôi không nghĩ có nhiều điều để nói thêm. Tuy nhiên, tôi đã dành quá nhiều thời gian cho việc này và điều đó làm tôi đau đầu. Chưa kể, các quy tắc có lẽ rất bị phá vỡ và chỉ áp dụng ít nhiều cho các ví dụ này.

Điều này thực hiện rất tốt đối với rất nhiều bài kiểm tra đơn giản mà tôi đã chạy, (tức là tổng số, 2 hoặc 3 đầu vào) nhưng nó không thành công đối với một số bài kiểm tra được đưa ra bởi thử thách. Tuy nhiên, tôi thấy rằng nếu bạn tăng độ chính xác thập phân của đầu vào (ngoài phạm vi thử thách), độ chính xác sẽ được cải thiện.

Phần lớn công việc liên quan đến việc tìm gcd cho tập hợp các số được cung cấp và tôi đã hiểu được điều đó Function g(), mặc dù nó chắc chắn không đầy đủ và có khả năng là nguồn gây ra ít nhất một số lỗi trong kết quả đầu ra của tôi.

Đầu vào là một chuỗi các giá trị được phân tách bằng dấu cách.

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

Testcase (đầu vào ==> dự kiến ​​/ trả lại):

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

bạn có thể mất 6 byte bằng cách chuyển đổi Debug.Print sangDebug.?
Taylor Scott

2

C # (.NET Core) , 286 byte

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();}}

Hãy thử trực tuyến!

Đã lưu rất nhiều byte nhờ Peter TaylorHiện thân của sự thiếu hiểu biết


Làm cách nào tôi có thể sửa đổi điều này để kiểm tra nó trên ideone.com?
Gareth

Tôi nghĩ rằng bạn đang thiếu một }ở cuối.
grc

@Gareth Tôi đã thử thực thi nó trên ideone.com, nhưng tôi nghĩ rằng nó sử dụng phiên bản .NET framework sớm hơn 4.0, vì nó không nhận ra Zipphương thức Linq .
Cristian Lupascu

@grc Cảm ơn bạn đã chỉ ra điều đó. Cập nhật.
Cristian Lupascu

1
@Gaffi: Không, C # có kiểu gõ nghiêm ngặt (như Java) nên nó phải là kiểu boolean. Vì 1>0là ngắn hơn true, nó được ưa thích.
mellamokb

0

Python 3 , 140 139 137 byte

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

Hãy thử trực tuyến!

Đưa ra câu trả lời đúng cho hai trường hợp thử nghiệm đầu tiên và chạy vào các giới hạn đệ quy của Python cho các trường hợp khác. Điều này không có gì đáng ngạc nhiên, vì mọi kiểm tra được thực hiện ở cấp độ đệ quy mới. Nó ngắn, mặc dù ...

(Có thể tìm thấy giải thích về các biến được sử dụng trong liên kết 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

nên làm việc cho 136 byte, nhưng không phải do độ chính xác float.

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.