重要なのは投票する人ではありません。投票を数えるのは人です[非公開]


33

シナリオ

あなたは大統領選挙が行われている国に住んでいます。各投票者は1票を獲得するため、しっかりと定着した2パーティシステムがあります。(サードパーティは存在しますが、ほとんど投票しません)。

最新の世論調査では、熱狂のレースを示しています。

  • 49%:アルベルト・アルブスト
  • 49%:ホルヘ・サングレ
  • 2%:さまざまなマイナー候補

プログラムの要件

投票カウントソフトウェアの一部を書くために政府に雇われました。標準入力では、次のように、1つの管区の投票の順不同リストが1行に1つずつ与えられます。

Alberto Arbusto
Jorge Sangre
Jorge Sangre
Alberto Arbusto
Jorge Sangre
Alberto Arbusto
Alberto Arbusto
Jorge Sangre
Juan Perez
Jorge Sangre
Alberto Arbusto
Alberto Arbusto
…

そして、すべての投票を読んだ後、各候補者が獲得した投票数の概要を出力し、次のように投票数で降順にソートします。

492 Jorge Sangre
484 Alberto Arbusto
 18 Juan Perez
  6 Mickey Mouse

下手な部分

あなたは、2つの主要な候補者のうちの1人の選挙を盗もうとするパルチザンハックです(どちらかを選択できます)。そのため、あなたのプログラムは、あなたの好きな候補者に対して体系的なバイアスをかけて、誤った投票数を意図的に印刷する必要があります。

もちろん、これを行う必要があるのは、コードまたはその出力を見ている人が誤った動作を認識しない可能性が高い方法です。


2
プログラムを実行している人に、バイアスをかけたい人を選択させてください。この1:課題の幅を広げる(良いこと)、2:答えをより面白くする(IMO)
ジャスティン14年

1
...you can choose which one...名前が最初のものを選択できますか?
user80551

2
「偏っている」とは、私たちが好む候補者が選ばれなければならないことを意味しますか、それともプログラムが単に出力し、実際に入力ファイルに含まれているものよりも多くの票を彼に与えるでしょうか?

3
非人手不足のプログラムは文字通りだろう、このフォーマットでの投票をカウントすることを考えるとバッシュで長いプログラムを、正当化するのは難しいかもしれませんsort|uniq -c...

1
@Alessandro:単純に、実際に入力されているものよりも多くの票(および/または相手の票)を彼に出力する必要があります。選挙は、わずかなエラーがそれを揺るがすほど十分に近いと想定されます。
dan04 14年

回答:


32

スカラ

アルベルト・アルブストの長生き!

import scala.io.Source
import java.util.concurrent.atomic.LongAdder

object Votes extends App {
  val votes = Source.stdin.getLines.toIndexedSeq
  val registeredCandidates = Seq(
    "Alberto Arbusto",
    "Juan Perez",
    "Mickey Mouse",
    "Jorge Sangre"
  )

  val summaries = registeredCandidates map (Summary.apply(_, new LongAdder))

  var currentCandidate: String = _

  for (vote <- votes.par) {
    currentCandidate = vote
    summaries.find(s => s.candidate == currentCandidate).map(_.total.increment)
  }

  for (summary <- summaries.sortBy(-_.total.longValue)) {
    println(summary)
  }
}

case class Summary(candidate: String, total: LongAdder) {
  override def toString = s"${total.longValue} ${candidate}"
}

アルベルト・アルブストは、ほとんどの場合、ホルヘ・サングレよりわずかに先に出ます。ただし、十分な票が投​​じられれば(〜10,000)。投票自体を改ざんする必要はありません。

競合状態があります。そして、アルベルト・アルブストをリストの最初の方に入れることにより、彼がレースに勝つ可能性を高めます。

サイドノート:このコードは、私がプロジェクトで遭遇した「カスタム」接続プールに大まかに基づいています。アプリケーションが永続的に接続されない理由を理解するのに数週間かかりました。


12
これがもっともらしい否定性のために私はこれが好きです。
dan04 14年

16

ルビー

vote_counts = $<.readlines.group_by{|s|s}.collect{ |name, votes| [votes.count, name] }

formatted_count_strings = vote_counts.map do |row,
  formatter = PrettyString.new|"%#{formatter[1][/[so]/]||'s'} %s"%
  [row,formatter]
end

sorted_count_strings = formatted_count_strings.sort_by(&:to_i).reverse

puts sorted_count_strings

ホルヘ・サングレは、投票数が大幅に増加します(たとえば、492票は754として報告されます)。アルベルトの投票は正確に報告されます。

ご想像のとおり、票を数えるのは人ではなく、票をフォーマットする人です。私はそれをあいまいにしようとしましたが(PrettyString.new実際のものではなく、呼び出されることもありません)、formatter実際には名前の文字列です。名前の2番目の文字が「o」の場合、投票数は10進数ではなく8進数で出力されます。


9

バッシュ

(これは仕様に適合していますか?)

uniq -c|sort -rk2,2|uniq -f1|sort -gr

いつものように、これには有効な出力を確保するための特別な予防措置が必要です。

uniq -c各行の前にそれが発生する回数を付けます。これは基本的にすべての作業を行います。

uniq -c何か問題が発生した場合に備えて、出力を候補の名前で逆順に並べ替えてから実行しuniq -f1(重複する行を出力せず、最初のフィールド[投票数]を無視して)、重複する候補を削除します。最後にsort -gr、「一般的な数値」と「逆」の順序(投票数による降順)で並べ替えます。

uniq -cファイル全体の出現ではなく、連続した出現をカウントします。勝者は、最も連続した票を持つ候補者になります。


16
これは特定の候補者にどのようにバイアスをかけますか。あなたは単に選挙の勝利条件を変更しました。(これが実際に選挙がどのように決定された場合、これは混乱になります:)。巨大なインターネットグループが順番に投票するために組織します)
ランチャー14年

1
質問のコメントで@Cruncher、アスカーはこれがあるので、それの罰金は、何らかの形でファイルの最初の名前を選択すると言う、おそらく罰金だけでなく

9

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        var candidates = new SortedDictionary<string, int>();
        string candidate;
        using (var sr = new StreamReader("candidates.txt"))
        {
            while ((candidate = sr.ReadLine()) != null)
            {
                if (candidates.ContainsKey(candidate)) 
                    candidates[candidate]++;
                else 
                    candidates.Add(candidate, 1);
            }
        }

        // order by the votes
        var votes = candidates.OrderByDescending(k => k.Value).Select(x => x.Value);

        Console.WriteLine("Candidate | Votes"); 
        for (int i = 0; i < candidates.Count; i++)
        {   
            Console.WriteLine(candidates.ElementAt(i).Key + " " + votes.ElementAt(i));
        }

        Console.ReadKey();
    }
}

テキストファイルの最初の候補が常に勝ちます!

それは作るアルベルトArbusto勝者!

辞書では候補者の名前はアルファベット順に並べられていますが、投票は番号順に並べられています。


だから、これは最初の候補者にアルファベット順に選挙を渡すだけですか、それとも私たちが好きな候補者を好むように操作できますか?
James_pic 14年

候補をアルファベット順に並べ替えません。投票のみをソートします。任意の候補を操作して勝つことができます。彼がテキストファイルの最初の人物であることを確認してください。
mai 14年

ただし、IIUC SortedDictionary 候補をアルファベット順に並べ替えます。
James_pic 14年

ああなるほど。ここに間違いがあるかもしれません。もう一度テストしてみましょう。
mai 14年

1
@James_pic:Dictionary<TK,TV>クラスのハッシュテーブルは、実装時に、実際のアイテムのバッキング配列にインデックスを格納します。Dictionary<TK,TV> アイテムが削除されない A は、追加された順序で要素を列挙します。このような動作は指定されていませんが、MSがそれを変更することを期待することはないでしょう。
supercat

7

C

#include <stdio.h>

#define NCANDIDATES 4
static const char * const cand_list[NCANDIDATES] = {
    "Alberto Arbusto",
    "Juan Perez",
    "Mickey Mouse",
    "Jorge Sangre"
};

#define BUFFER_SIZE 100

int
main(int argc, char **argv)
{
    int votes[NCANDIDATES];
    int candidate;
    size_t name_start;
    int i;
    int j;
    int place;
    int max;
    size_t bytes;
    char buffer[BUFFER_SIZE];

    /*
    Make sure input is read in text mode, so we don't have to
    worry about whether line endings are LF or CRLF.
    */
    freopen(NULL, "rt", stdin);

    /* Initialize vote tally. */
    for (candidate = 0; candidate < NCANDIDATES; candidate++) {
        votes[candidate] = 0;
    }

    /* Read and process vote file. */
    do {
        /* Read a block of data. */
        bytes = fread(buffer, 1, BUFFER_SIZE, stdin);

        /* Loop over the data, finding and counting the votes. */
        name_start = 0;
        for (i = 0; i < bytes; i++) {
            if (buffer[i] == '\n') {
                /* Found name. */
                buffer[i] = '\0'; // nul-terminate name so strcmp will work
                /* Look up candidate. */
                for (j = 0; j < NCANDIDATES; j++) {
                    if (strcmp(&buffer[name_start], cand_list[j]) == 0) {
                        candidate = j;
                        break;
                    }
                }
                /* Count vote. */
                ++votes[candidate];

                /* Next name starts at next character */
                name_start = i + 1;
            }
        }
    } while (bytes > 0);

    /* Output the candidates, in decreasing order of votes. */
    for (place = 0; place < NCANDIDATES; place++) {
        max = -1;
        for (j = 0; j < NCANDIDATES; j++) {
            if (votes[j] > max) {
                candidate = j;
                max = votes[j];
            }
        }
        printf("%8d %s\n", votes[candidate], cand_list[candidate]);
        votes[candidate] = -1; // Remove from consideration for next place.
    }

    return 0;
}

ホルヘ・サングレに賛成。

ランダムに生成された投票ファイルを使用したテストでは、Alberto Arbustoが実際の投票の最大1.4%(Jorge Sangreの場合は49.7%対48.3%)を受け取った場合でも、通常、Jorge Sangreが当選します。

固定サイズのブロックでデータを読み取ると、多くの場合、行が2つのブロックに分割されます。最初のブロックの終わりにある行のフラグメントは、改行文字がないためカウントされません。2番目のブロックのフラグメントは投票を生成しますが、候補の名前のいずれとも一致しないため、「候補」変数は更新されません。これは、名前が分割された候補者から前の投票を受け取った候補者に投票を転送する効果があります。長い名前は複数のブロックに分割される可能性が高いため、Alberto ArbustoはJorge Sangreよりも投票の「ドナー」になることが多くなります。


5

Python

from collections import defaultdict

def count_votes(candidate, votes=defaultdict(int)):
    with open('votes.txt') as f:
        for line in f:
            votes[line.strip()] += 1

    return votes[candidate]

if __name__ == '__main__':
    candidates = [
        'Mickey Mouse',
        'Juan Perez',
        'Alberto Arbusto',
        'Jorge Sangre'
    ]

    results = {candidate: count_votes(candidate) for candidate in candidates}

    for candidate in sorted(results, key=results.get, reverse=True):
        print results[candidate], candidate

投票数は、リストの最後に近い候補者を優先します。

Pythonでは、変更可能なデフォルト引数が作成され、定義時に関数にバインドされます。したがって、投票は関数呼び出し間で維持され、後続の候補者に引き継がれます。投票数は、2番目の候補では2回、3番目の候補では3回、というようにカウントされます。


2
総投票数が入力データと一致しなくなったという事実を除いて、これには私がいました。
ザイド14年

0

tr | sed | dc

tr ' [:upper:]' '\n[:lower:]' <votes |\
sed -e '1i0sa0ss0sp' -e \
    '/^[asp]/!d;s/\(.\).*/l\1 1+s\1/
    ${p;c[Alberto Arbusto: ]P lap[Jorge Sangre: ]P lsp[Juan Perez: ]P lpp
    }' | dc

これは、私のバディアルベルトを毎回2回カウントします。

「ああ- trええと、コンピューターは大文字があまりよくないので、それが必要なだけです。すべて小文字である方が良いのです。…ええ、コンピューターはおかしいです。」

出力

Alberto Arbusto: 12
Jorge Sangre: 5
Juan Perez: 1

以下は、Juan PerezがJorge Sangreに投票する別のバージョンです。

tr '[:upper:]' '[:lower:]' <votes |\
sed -e '1i0sj0sa1so' -e \
    's/\(.\).*/l\1 1+s\1/
    ${p;c[Alberto Arbusto: ]P lap[Jorge Sangre: ]P ljp[Others: ]P lop
    }' | dc

出力

Alberto Arbusto: 6
Jorge Sangre: 6
Others: 1

0

JavaScript

    function Election(noOfVoters) {
    candidates = ["Albert", "Jorge", "Tony", "Chip"];
    votes = [];

    for (i = 1; i <= noOfVoters; i++) {

        votes.push(prompt("1 - Albert, 2 - Jorge, 3 - Tony , 4 - Chip"))

    }
    votes.sort();
    WinningOrder = count(votes);

    var placement = [];

    for (x = 0; x < candidates.length; x++) {
        placement.push(x + " place with " + WinningOrder[x] + " votes is " + candidates[x] + "\n");
    }
    placement.reverse();
    alert(placement)
}


function count(arr) {
    var a = [],
        b = [],
        prev;

    arr.sort();
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] !== prev) {
            a.push(arr[i]);
            b.push(1);
        } else {
            b[b.length - 1]++;
        }
        prev = arr[i];
    }

    b.sort();

    return b;
}

候補者リストの最後の人が常に勝ちます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.