我正在尝试计算每个候选人的第一,第二和第三选择投票数(特别是Stack Overflow 2014主持人选举)。我下载了the data file并打开了它。基于我对文件格式的基本解释,我编写了一个PHP脚本来计算投票:
<?php
$lines = file("stackoverflow-com-2014-election-results.blt");
unset($lines[0]);
$ballots = 0;
$first = array();
$second = array();
$third = array();
for ($i = 1;; $i++) {
$line = explode(" ", trim($lines[$i]));
if ($line[0] != 1) break;
$ballots++;
@$first[$line[1]]++;
@$second[$line[2]]++;
@$third[$line[3]]++;
}
$names = array();
for ($i++; $i < count($lines); $i++) {
$names[count($names) + 1] = trim(trim($lines[$i]), '"');
}
printf("%20s%8s%8s%8s%8s\n", "Name", "1st", "2nd", "3rd", "Total");
print(str_repeat("-", 52) . "\n");
foreach ($names as $id => $name) {
printf("%20s%8s%8s%8s%8s\n", $name,
$first[$id], $second[$id], $third[$id],
$first[$id] + $second[$id] + $third[$id]);
}
print(str_repeat("-", 52) . "\n");
printf("Ballots: %d\n", $ballots);
当我在命令行运行它时会打印出这个表:
Name 1st 2nd 3rd Total
----------------------------------------------------
Undo 1358 1425 1814 4597
bluefeet 3352 3148 2287 8787
0x7fffffff 1932 2147 2159 6238
Bohemian 5678 2935 2415 11028
Jon Clements 1531 1527 1618 4676
Doorknob 1165 1720 1753 4638
Raghav Sood 1358 1565 1571 4494
Siddharth Rout 1732 1872 1866 5470
Matt 1381 1988 2009 5378
meagar 1903 2382 2881 7166
----------------------------------------------------
Ballots: 21571
我的问题是,当我在同一个文件上运行OpenSTV时,我无法得到这个。 “首选数量”都略有不同:
Ballot file contains 21571 non-empty ballots.
Counting votes for Stack Overflow Moderator Election 2014 using Meek STV.
10 candidates running for 3 seats.
R|Undo |bluefeet |0x7fffffff |Bohemian |Jon Clements
| | | | |
|--------------+--------------+--------------+--------------+--------------
|Doorknob |Raghav Sood |Siddharth Rout|Matt |meagar
| | | | |
|--------------+--------------+--------------+--------------+--------------
|Exhausted |Surplus |Threshold
| | |
=============================================================================
1| 1379.000000| 3372.000000| 1951.000000| 5707.000000| 1545.000000
| 1181.000000| 1375.000000| 1749.000000| 1389.000000| 1923.000000
| 0.000000| 314.249999| 5392.750001
|--------------------------------------------------------------------------
| Count of first choices. Candidate Bohemian has reached the threshold and
| is elected.
=============================================================================
[...]
我做错了什么?或者OpenSTV采用不同的方式做什么?
更新:我的脚本 已损坏,因为它没有考虑使用第二个或第三个选项编码的某些行,而没有事先选择设置。我猜这是由于选举中的用户有时会取消选择先前的选择:在选择了两个候选人之后,取消选择第一个候选人应该将剩下的唯一候选人视为用户的首选。
修正版:
<?php
$lines = file("stackoverflow-com-2014-election-results.blt");
$line = explode(" ", trim($lines[0]));
$numCandidates = $line[0];
$numChoices = $line[1];
$choiceVotes = array_fill(1, $numChoices, array_fill(1, $numCandidates, 0));
$totalBallots = 0;
for ($i = 1;; $i++) {
$line = explode(" ", trim($lines[$i]));
if ($line[0] == 0) break;
$totalBallots++;
for ($j = 1, $k = 1; $j <= $numChoices; $j++) {
if ($line[$j] != 0) $choiceVotes[$k++][$line[$j]]++;
}
}
$names = array();
for ($j = 1; $j <= $numCandidates; $j++) {
$names[$j] = trim(trim($lines[$j + $i]), '"');
}
$rowFormat = "%20s" . str_repeat("%8s", $numChoices) . "%8s\n";
$separator = str_repeat("-", 20 + (8 * $numChoices) + 8) . "\n";
$row = array("Name");
for ($i = 1; $i <= $numChoices; $i++) $row[] = $i . gmdate('S', $i * 86400 - 1);
$row[] = "Total";
vprintf($rowFormat, $row);
print $separator;
foreach ($names as $id => $name) {
$row = array($name);
$candidateTotal = 0;
for ($i = 1; $i <= $numChoices; $i++) {
$votes = $choiceVotes[$i][$id];
$row[] = $votes;
$candidateTotal += $votes;
}
$row[] = $candidateTotal;
vprintf($rowFormat, $row);
}
print $separator;
printf("Ballots: %d\n", $totalBallots);
答案 0 :(得分:1)
我在包含21563
选票行的data file上运行了您的脚本:
Name 1st 2nd 3rd Total
----------------------------------------------------
meagar 1903 2382 2881 7166
Raghav Sood 1357 1564 1570 4491
Bohemian 5674 2935 2415 11024
0x7fffffff 1932 2146 2159 6237
Undo 1358 1424 1814 4596
bluefeet 3352 3146 2284 8782
Matt 1380 1988 2009 5377
Jon Clements 1531 1526 1616 4673
Siddharth Rout 1731 1871 1865 5467
Doorknob 1165 1720 1752 4637
----------------------------------------------------
Ballots: 21563
我还将其导入Google电子表格(link):
使用countif()
为您的脚本提供相同的结果。例如:
=countif( data!B:B;$A2)
计算单元格C2
的值。
所以我必须得出结论,你没有使用相同的数据。
中的数据https://stackoverflow.com/election/download-result/5
发表问题后,甚至发生了变化。
所以这样的投票行:
1 0 6 0 0
列:
Weight 1st 2nd 3rd end
似乎被视为:
1 6 0
通过OpenSTV,即6
作为第一选择,0
投票被忽略。
我做了一个测试,删除了0
个选项(link to the modified .blt file)
OpenSTV的结果:
Ballot file contains 10 candidates and 21563 ballots.
No candidates have withdrawn.
Ballot file contains 21563 non-empty ballots.
Counting votes for Stack Overflow Moderator Election 2014 using Meek STV.
10 candidates running for 3 seats.
R|meagar |Raghav Sood |Bohemian |0x7fffffff |Undo |bluefeet |Matt
| | | | | | |
|-------------+-------------+-------------+-------------+-------------+-------------+-------------
|Jon Clements |Siddharth Rou|Doorknob |Exhausted |Surplus |Threshold
| |t | | | |
====================================================================================================
1| 1923.000000| 1374.000000| 5703.000000| 1951.000000| 1379.000000| 3372.000000| 1388.000000
| 1544.000000| 1748.000000| 1181.000000| 0.000000| 312.249999| 5390.750001
|-------------------------------------------------------------------------------------------------
| Count of first choices. Candidate Bohemian has reached the threshold and is elected.
====================================================================================================
脚本的结果:
Name 1st 2nd 3rd Total
----------------------------------------------------
meagar 1923 2378 2865 7166
Raghav Sood 1374 1558 1559 4491
Bohemian 5703 2922 2399 11024
0x7fffffff 1951 2143 2143 6237
Undo 1379 1419 1798 4596
bluefeet 3372 3138 2272 8782
Matt 1388 1991 1998 5377
Jon Clements 1544 1516 1613 4673
Siddharth Rout 1748 1870 1849 5467
Doorknob 1181 1724 1732 4637
----------------------------------------------------
Ballots: 21563
我使用isset()
修改了您的脚本。
所以 1st 选择的数量现在似乎是相同的。
答案 1 :(得分:0)
当我计算回车次数,然后是这个字符串“1 10”时,我得到总数1903.这与你对梅加尔的第一名投票数相符。我认为你的脚本是正确的。