反向工程师轮询统计


22

介绍

给定民意测验中的一组选择百分比,请计算民意测验中必须存在的最少选民人数才能生成这些统计数据。

示例:您最喜欢的宠物是什么?

  • 狗: 44.4%
  • 猫: 44.4%
  • 老鼠: 11.1%

输出:(9最少可能的选民人数)

眼镜

这是您的程序/功能的要求:

  • 您将得到一个百分比值数组作为输入(在stdin上,作为函数参数等)。
  • 每个百分比值都是一个四舍五入到小数点后一位的数字(例如44.4 44.4 11.1)。
  • 计算民意测验的最小可能投票人数,当四舍五入到小数点后一位(标准输出或函数返回值)时,其投票结果将产生准确的百分比。
  • 奖励:-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 15 3),48.4 13.7 21.6 6.5 9.8(74 21 33 10 153 15)等
加雷

@加雷斯:好主意。更新了您的测试用例。
mellamokb

所有选票的总和不应该是100%吗?它不在最后四个测试用例中
Ali1S232

@Gajet:不,它并不总是等于100%。每次进行四舍五入时,您都会0.5%从总数中亏损,而每次进行四舍五入时,您都会0.5%得出总计。特意构建了最后四个测试用例,以最佳地利用这一现象。在结果为的第一个测试用例中2000,前9个条目中的每一个均代表1表决(均已向上舍入0.5%),而最后一个代表1991表决(并已舍入〜0.5%)。如果您手动计算这些百分比并四舍五入到小数点后一位,您会发现它们都是正确的。
mellamokb

我正在努力解决VBA中的重要问题(到目前为止,一直没有尝试过),但是我正在努力!
加菲2012年

Answers:


2

APL(Dyalog Classic)48 43字节

-5字节,由Adám编写

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

完整程序从stdin输入。

在线尝试!链接是dfn版本。

不打高尔夫球

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

在线尝试!

  • normalize将(÷)右参数()的所有元素除以(sum +/)。
  • round(y)通过格式化()然后将y的每个元素求值(),将y 舍入到小数点后3位。
  • find_max(y) 返回一个数组,该数组的1找到max(y),其他地方为0。
  • increase(x,y) 取x(目标百分比)和y(当前投票总数的数组)并计算在y中加1的位置,以使百分比更接近x。
  • vote_totals(x,y) 取x(目标百分比)和y(开始投票总数)并重复执行f,添加投票直到百分比取整为x。
    • 该语法f ⍣ g意味着f重复执行直到g(y,f(y))为true。在这种情况下,我们将忽略f(y)
  • h(x) 将y设置为0(由于矢量化,等于0的数组),执行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 2012年

2
我认为这是正确的,但令人困惑。1/2000 = 0.05%0.1%四舍五入)和1991/2000 = 99.55%99.6%四舍五入)。因此,如果民意调查有十种选择,而其中有九种获得一次投票,而最后一次获得1991年投票,那么它将给出这些百分比。
grc 2012年

你是对的。伟大的解决方案,顺便说一句。
Cristian Lupascu 2012年

我认为您可以按照以下提示节省3个字符:codegolf.stackexchange.com/a/58/3527
Cristian Lupascu 2012年

谢谢,w0lf。我现在对其进行了更新,以包括选项卡。如果有人想知道,选项卡显示为四个空格。
grc 2012年

4

J,57个字符

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

用了平凡的方法。它需要键盘输入。t创建一个查找表,第二行在表中查找输入。如果有人感兴趣,我可以提供代码的扩展解释。

我曾经研究过使用百分比来创建分数,然后获得分数的最低形式来计算数字,但是我无法找到一种方法来使其与结果四舍五入。


嗯,这对于新的测试用例是失败的。我将不得不寻求修复。
Gareth 2012年

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 '04 -4-24

由于超出时间限制,我无法在ideone上生成,但是您得到什么结果[0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,99.6]呢?
mellamokb '04

嗯...半个小时,程序仍在运行。我认为可以肯定地说这是一个突破。但是,我看不出这是一个有效的答案,因为它总计为100.5%,而不是100%
Blazer 2012年

2
1/2000 = 0.05%0.1%四舍五入)和1991/2000 = 99.55%99.6%四舍五入)。因此,它实际上总计为100%,但是四舍五入使它确实令人困惑。
grc 2012年

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

测试用例(输入==>预期/返回):

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

您可以通过转换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 2012年

我认为您}最后缺少一个。
grc 2012年

@Gareth我尝试在ideone.com上执行它,但是我认为它使用的是.NET Framework版本早于4.0,因为它无法识别Linq Zip方法。
Cristian Lupascu 2012年

@grc感谢您指出这一点。更新。
Cristian Lupascu 2012年

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个字节,但不是因为float精度。

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.