【发布时间】:2014-02-25 20:50:03
【问题描述】:
我正在尝试计算选举(特别是 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);
【问题讨论】:
-
嗯,我打开数据文件,我只看到 21563 行选票,而不是 21571。不知道为什么。
-
@birgire 奇怪。当我重新下载文件并将其与我在选举结束后立即下载的文件进行比较时,选票和姓名的顺序不同,如你所说,选票行减少了 8 行。但无论使用哪个文件,我最初的问题仍然存在:脚本的票数与 OpenSTV 的票数不匹配。