投票计数脚本没有正确添加

时间:2014-02-25 20:50:03

标签: php voting openstv

我正在尝试计算每个候选人的第一,第二和第三选择投票数(特别是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);

2 个答案:

答案 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):

google spreadsheet

使用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.这与你对梅加尔的第一名投票数相符。我认为你的脚本是正确的。