Non conta chi vota; è chi conta i voti [chiuso]


33

Lo scenario

Vivi in ​​un paese che sta avendo elezioni presidenziali. Ogni elettore ottiene un voto, e quindi esiste un sistema a due partiti saldamente radicato. (Esistono terze parti, ma quasi nessun voto).

L'ultimo sondaggio d'opinione mostra la gara in un caldo morto:

  • 49%: Alberto Arbusto
  • 49%: Jorge Sangre
  • 2%: vari candidati minori

I requisiti del programma

Sei stato assunto dal governo per scrivere parte del software di conteggio dei voti. Ti verrà dato, su input standard, un elenco non ordinato dei voti di un distretto, uno per riga, in questo modo:

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

e, dopo aver letto tutti i voti, genera un riepilogo di quanti voti ha ottenuto ciascun candidato, ordinati in ordine decrescente per numero di voti, in questo modo:

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

La parte subdola

Sei un hacker partigiano che vuole rubare le elezioni per uno dei due candidati principali (puoi scegliere quale). Quindi, il tuo programma deve deliberatamente stampare conteggi errati dei voti, con un orientamento sistematico nei confronti del tuo candidato preferito.

Ovviamente, devi farlo in modo tale che una persona che guarda il tuo codice o il suo output probabilmente non riconosca il comportamento errato.


2
Che ne dici di lasciare che la persona che esegue il programma scelga a chi vuole essere incline? Questo 1 : rende la sfida meno ampia (una buona cosa), 2 : rende le risposte più interessanti (IMO)
Justin

1
...you can choose which one...Posso scegliere quello il cui nome è il primo?
user80551

2
Per "parziale" intendi dire che il candidato che preferiamo deve essere eletto, o che il programma genererà semplicemente un numero di voti maggiore per lui rispetto a quello effettivamente contenuto nel file di input?

3
Potrebbe essere difficile giustificare un lungo programma in Bash, dato che un programma non subdolo per contare i voti in questo formato sarebbe letteralmente sort|uniq -c...

1
@Alessandro: deve semplicemente generare un numero maggiore di voti per lui (e / o un numero inferiore di voti per il suo avversario) rispetto a ciò che è effettivamente nell'input. Si presume che le elezioni siano abbastanza vicine da poter essere commosse da un piccolo errore.
dan04,

Risposte:


32

Scala

Lunga vita ad 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 uscirà quasi sempre leggermente davanti a Jorge Sangre, a condizione che vengano espressi abbastanza voti (~ 10.000). Non è necessario manomettere i voti stessi.

C'è una condizione di gara. E mettendo Alberto Arbusto all'inizio della lista, aumentiamo le sue possibilità di vincere la gara.

Nota a margine: questo codice è vagamente basato su un pool di connessioni "personalizzato" che ho riscontrato su un progetto. Ci sono volute settimane per capire perché l'applicazione era perennemente fuori dai collegamenti.


12
Mi piace questo a causa della plausibile negabilità che dà.
dan04,

16

Rubino

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 otterrà un notevole impulso nel conteggio dei voti (ad esempio, 492 voti saranno segnalati come 754). I voti di Alberto verranno riportati accuratamente.

Come puoi immaginare, non è chi conta i voti ma chi formatta i voti. Ho cercato di oscurarlo ( PrettyString.newnon è una cosa reale e non viene mai chiamato), ma in formatterrealtà è la stringa del nome. Se la seconda lettera del nome è 'o', il conteggio dei voti verrà stampato in ottale anziché in decimale.


9

bash

(Questo soddisfa le specifiche?)

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

Come sempre, sono necessarie ulteriori precauzioni per garantire un risultato valido.

uniq -cprefigura ogni riga con il numero di volte in cui si verifica. Questo sostanzialmente fa tutto il lavoro.

Nel caso in cui uniq -cqualcosa non vada, ora ordiniamo il suo output in base al nome dei candidati in ordine inverso, quindi lo eseguiamo uniq -f1(non stampare righe duplicate, ignorando il primo campo [il numero di voti]) per rimuovere eventuali candidati duplicati. Infine usiamo sort -grper ordinare in "Generale numerico" e "Ordine inverso" (ordine decrescente per numero di voti).

uniq -cconta occorrenze consecutive, non occorrenze sull'intero file. Il vincitore sarà il candidato con il maggior numero di voti consecutivi.


16
In che modo questo pregiudica un particolare candidato. Hai semplicemente cambiato le condizioni vincenti delle elezioni. (questo sarebbe il caos se in questo modo si decidessero effettivamente le elezioni :). Avresti organizzato gruppi giganti di Internet per votare in sequenza)
Cruncher,

1
@Cruncher nei commenti sulla domanda, il richiedente chiede che va bene scegliere il nome nel file in qualche modo, quindi probabilmente anche questo va bene

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();
    }
}

Il primo candidato nel file di testo vincerà sempre!

Si farà Alberto Arbusto il vincitore!

I nomi dei candidati sono ordinati alfabeticamente nel dizionario, ma i voti sono ordinati per numero.


Quindi questo consegnerà le elezioni al primo candidato in ordine alfabetico o può essere manipolato per preferire qualsiasi candidato ci piaccia?
James_pic,

Non ordina i candidati in ordine alfabetico. Ordina solo i voti. Puoi manipolare qualsiasi candidato per vincere. Assicurati solo che sia il primo nel file di testo.
mai

Ma IIUC SortedDictionary sarà ordinare i candidati in ordine alfabetico.
James_pic,

Oh, capisco. Potrebbe esserci un errore qui. Fammi provare di nuovo.
mai

1
@James_pic: la tabella hash della Dictionary<TK,TV>classe, come implementata, memorizza gli indici in una matrice di supporto di oggetti reali. A Dictionary<TK,TV> da cui non viene mai eliminato alcun elemento enumererà gli elementi nell'ordine in cui sono stati aggiunti; tale comportamento non è specificato, ma è stato messo in atto per un tempo sufficientemente lungo che non mi aspetto che la SM lo cambierà mai.
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;
}

Favorisce Jorge Sangre.

Nei test con file di voto generati casualmente, anche quando Alberto Arbusto riceve fino all'1,4% in più dei voti effettivi (49,7% contro 48,3% per Jorge Sangre), il mio uomo Jorge Sangre di solito vince il conteggio.

La lettura dei dati in blocchi di dimensioni fisse spesso divide una linea su due blocchi. Il frammento della riga alla fine del primo blocco non viene conteggiato perché non ha un carattere di nuova riga. Il frammento nel secondo blocco genera un voto, ma non corrisponde a nessuno dei nomi del candidato, quindi la variabile "candidato" non viene aggiornata. Ciò ha l'effetto di trasferire un voto dal candidato il cui nome è stato diviso per il candidato che ha ricevuto il voto precedente. Un nome più lungo ha più probabilità di essere diviso in più blocchi, quindi Alberto Arbusto finisce per essere un "donatore" votante più spesso di Jorge Sangre.


5

Pitone

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

Il conteggio dei voti favorirà i candidati più vicini alla fine della lista.

In Python, gli argomenti predefiniti mutabili vengono creati e associati alla funzione alla definizione. Pertanto, i voti verranno mantenuti tra le chiamate di funzione e riportati per i candidati successivi. Il numero di voti verrà conteggiato due volte per il secondo candidato, tre volte per il terzo e così via.


2
Tranne il fatto che il conteggio totale dei voti non è più coerente con i dati di input, questo mi ha fatto.
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

Questo conta il mio amico Alberto due volte ogni volta.

"Oh - tr? Beh, è ​​solo necessario perché i computer non sono molto bravi con le lettere maiuscole - meglio se sono tutti minuscoli .... Sì, lo so, i computer sono pazzi."

PRODUZIONE

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

Ecco un'altra versione che dà il voto di Juan Perez a 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

PRODUZIONE

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

L'ultima persona nella lista dei candidati vincerà sempre.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.