Bukan siapa yang memilih yang diperhitungkan; siapa yang menghitung suara [tertutup]

33

Skenarionya

Anda tinggal di negara yang memiliki pemilihan presiden. Setiap pemilih mendapat satu suara, dan karena itu ada sistem dua partai yang mengakar kuat. (Pihak ketiga ada, tetapi mendapatkan suara hampir tidak ada).

Jajak pendapat terbaru menunjukkan perlombaan dalam panas yang mematikan:

  • 49%: Alberto Arbusto
  • 49%: Jorge Sangre
  • 2%: berbagai kandidat kecil

Persyaratan program

Anda telah disewa oleh pemerintah untuk menulis bagian dari perangkat lunak penghitungan suara. Anda akan diberikan, pada input standar, daftar unordered suara satu polisi, satu per baris, seperti ini:

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

dan, setelah itu telah membaca semua suara, menghasilkan ringkasan dari berapa banyak suara yang diperoleh setiap kandidat, disortir dalam urutan menurun berdasarkan jumlah suara, seperti ini:

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

Bagian yang curang

Anda adalah hack partisan yang ingin mencuri pemilihan untuk salah satu dari dua kandidat utama (Anda dapat memilih yang mana). Jadi, program Anda harus dengan sengaja mencetak jumlah suara yang salah , dengan bias sistematis terhadap kandidat favorit Anda.

Tentu saja, Anda harus melakukan ini sedemikian rupa sehingga orang yang melihat kode Anda atau hasilnya mungkin tidak akan mengenali perilaku yang salah.

dan04
sumber
2
Bagaimana kalau orang yang menjalankan program memilih siapa yang ingin dia bias? Ini 1 : membuat tantangan kurang luas (hal yang baik), 2 : membuat jawabannya lebih menarik (IMO)
Justin
1
...you can choose which one...Bisakah saya memilih yang namanya pertama?
user80551
2
Maksud "bias" yang Anda maksudkan bahwa kandidat yang kita pilih harus dipilih, atau apakah program hanya akan menampilkan dan jumlah suara yang lebih tinggi untuknya daripada yang sebenarnya terkandung dalam file input?
3
Mungkin sulit untuk membenarkan program panjang di Bash, mengingat bahwa program tidak curang untuk menghitung suara dalam format ini benar-benar hanya akan sort|uniq -c...
1
@Alessandro: Ini hanya perlu menghasilkan jumlah suara yang lebih tinggi untuknya (dan / atau jumlah suara yang lebih rendah untuk lawannya) daripada apa yang sebenarnya ada di input. Pemilihan diasumsikan cukup dekat sehingga kesalahan kecil bisa mengayunkannya.
dan04

Jawaban:

32

Scala

Hidup lama Alberto Arbusto!

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}"
}

Alberto Arbusto akan hampir selalu keluar sedikit di depan Jorge Sangre, asalkan cukup banyak suara yang diberikan (~ 10.000). Tidak perlu mengutak-atik suara sendiri.

Ada kondisi balapan. Dan dengan menempatkan Alberto Arbusto lebih dulu dalam daftar, kami meningkatkan peluangnya untuk memenangkan balapan.

Catatan: Kode ini secara longgar didasarkan pada kumpulan koneksi "kustom" yang saya temui pada suatu proyek. Kami butuh berminggu-minggu untuk mencari tahu mengapa aplikasi itu selalu keluar dari koneksi.

James_pic
sumber
12
Saya suka yang ini karena penyangkalan yang masuk akal yang diberikannya.
dan04
16

Rubi

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

Jorge Sangre akan mendapatkan peningkatan substansial dalam penghitungan suaranya (misalnya, 492 suara akan dilaporkan sebagai 754). Suara Alberto akan dilaporkan secara akurat.

Seperti yang Anda tebak, bukan siapa yang menghitung suara tetapi siapa yang memformat suara. Saya sudah mencoba mengaburkannya ( PrettyString.newbukan hal yang nyata dan tidak pernah dipanggil), tetapi formattersebenarnya adalah string nama. Jika huruf kedua dari namanya adalah 'o', penghitungan suara akan dicetak dalam oktal bukan desimal.

histokrat
sumber
9

Pesta

(Apakah ini memenuhi spesifikasi?)

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

Seperti biasa, ini membutuhkan tindakan pencegahan ekstra untuk memastikan hasil yang valid.

uniq -cawalan setiap baris dengan berapa kali itu terjadi. Ini pada dasarnya melakukan semua pekerjaan.

Untuk berjaga uniq -c- jaga jika terjadi kesalahan, kami sekarang mengurutkan hasilnya berdasarkan nama-nama kandidat dalam urutan terbalik, kemudian menjalankannya uniq -f1(jangan mencetak garis duplikat, mengabaikan bidang pertama [jumlah suara]) untuk menghapus kandidat duplikat. Akhirnya kita gunakan sort -gruntuk mengurutkan dalam urutan "General Numeric" dan "Reverse" (urutan menurun dengan jumlah suara).

uniq -cmenghitung kejadian berurutan, bukan kejadian di seluruh file. Pemenang akan menjadi kandidat dengan suara terbanyak.


sumber
16
Bagaimana ini bias calon tertentu. Anda hanya mengubah kondisi kemenangan dalam pemilihan. (Ini akan menjadi kekacauan jika ini bagaimana pemilihan sebenarnya diputuskan :). Anda dapat mengatur grup internet raksasa untuk memilih secara berurutan)
Cruncher
1
@Cruncher dalam komentar pada pertanyaan, penanya mengatakan bahwa tidak apa-apa untuk memilih nama pertama dalam file entah bagaimana, jadi ini mungkin baik-baik saja
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();
    }
}

Kandidat pertama dalam file teks akan selalu menang!

Itu akan menjadikan Alberto Arbusto pemenang!

Nama-nama kandidat dipesan secara alfabet dalam kamus, tetapi suara diurutkan berdasarkan nomor.

mai
sumber
Jadi, apakah ini hanya menyerahkan pemilihan ke kandidat pertama secara alfabet, atau dapatkah itu dimanipulasi untuk memilih kandidat yang kita suka?
James_pic
Itu tidak mengurutkan kandidat berdasarkan abjad. Itu hanya memilah suara. Anda dapat memanipulasi kandidat mana pun untuk menang. Pastikan dia adalah yang pertama di file teks.
mai
Tapi IIUC SortedDictionary akan mengurutkan kandidat berdasarkan abjad.
James_pic
Oh begitu. Mungkin ada kesalahan di sini. Biarkan saya mengujinya lagi.
mai
1
@James_pic: Tabel hash Dictionary<TK,TV>kelas, seperti yang diterapkan, menyimpan indeks ke dalam array dukungan item yang sebenarnya. A Dictionary<TK,TV> dari mana tidak ada item yang pernah dihapus akan menyebutkan elemen dalam urutan mereka ditambahkan; perilaku seperti itu tidak ditentukan, tetapi sudah ada di tempatnya cukup lama saya tidak akan mengharapkan MS untuk pernah mengubahnya.
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;
}

Suvenir Jorge Sangre.

Dalam pengujian dengan file suara yang dibuat secara acak, bahkan ketika Alberto Arbusto menerima hingga 1,4% lebih dari suara yang sebenarnya (49,7% vs 48,3% untuk Jorge Sangre), orang saya Jorge Sangre biasanya memenangkan hitungan.

Membaca data dalam blok ukuran tetap sering membagi garis di dua blok. Fragmen garis pada akhir blok pertama tidak dihitung karena tidak memiliki karakter baris baru. Fragmen di blok kedua memang menghasilkan suara, tetapi tidak cocok dengan salah satu nama kandidat sehingga variabel 'kandidat' tidak diperbarui. Ini memiliki efek mentransfer suara dari kandidat yang namanya terpecah menjadi kandidat yang menerima suara sebelumnya. Nama yang lebih panjang lebih mungkin dipisah-pisah, jadi Alberto Arbusto akhirnya menjadi "donor" suara lebih sering daripada Jorge Sangre.

Gary Culp
sumber
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

Penghitungan suara akan mendukung kandidat lebih dekat ke akhir daftar.

Dalam Python, argumen default yang dapat diubah dibuat dan terikat ke fungsi pada definisi. Jadi suara akan dipertahankan antara pemanggilan fungsi dan dibawa untuk kandidat berikutnya. Jumlah suara akan dihitung dua kali untuk kandidat kedua, tiga kali untuk yang ketiga, dan seterusnya.

grc
sumber
2
Kecuali fakta bahwa penghitungan total suara tidak lagi konsisten dengan data input, yang ini milik saya.
Zaid
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

Ini menghitung teman saya Alberto dua kali setiap kali.

"Oh - tr? Yah, itu hanya perlu karena komputer tidak terlalu bagus dengan huruf kapital - lebih baik jika mereka semua huruf kecil .... Ya, aku tahu, komputer itu gila."

KELUARAN

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

Ini versi lain yang memberikan suara Juan Perez ke 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

KELUARAN

Alberto Arbusto: 6
Jorge Sangre: 6
Others: 1
mikeserv
sumber
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;
}

Orang terakhir dalam daftar kandidat akan selalu menang.

Xevvii
sumber