【问题标题】:Vote counting script is not adding up correctly计票脚本未正确加起来
【发布时间】: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 的票数不匹配。

标签: php voting openstv


【解决方案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()修改了你的脚本。

所以现在第一个个选项的数量似乎是一样的。

【讨论】:

  • 肯定使用相同的数据。 election page 有 OpenSTV 的下载,您可以自己查看。
  • 你是指来自stackoverflow.com/election/download-result/5的数据吗?好吧,正如我们所见证的那样,它可能已经发生了变化;-) 也许有些行带有不同的定界符?至少您的脚本在下载链接的最新数据上与 Google 电子表格一致。您能否分享您最初用于测试的数据,以便我将其输入 Google 电子表格?
  • 原始数据:pastee.org/xfutu。但这没有什么区别。无论我使用哪个文件,问题都是它与 OpenSTV 不匹配。
  • 我刚刚安装了 OpenSTV,从导入的 .blt 文件运行选举时,有很多选举方法可供选择。默认为“苏格兰 STV”。 “Meek STV”是选举中使用的一种。例如,当我选择“批准投票”时,我得到一个包含 2 列的表格,候选人 + 总数,并且总数列中的数字与您的脚本和 Google 电子表格相匹配。所以看起来有一些额外的规则应用于 OpenSTV 中的进程。
  • 我只是不明白为什么它说“第一选择的数量”,但数字是错误的。
【解决方案2】:

当我计算回车数时,后跟这个字符串“1 10”,我得到的总数是 1903。这与你对 meagar 的第一名投票数相匹配。我认为你的脚本是正确的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 2013-11-21
    相关资源
    最近更新 更多