Não é quem vota que conta; é quem conta os votos [fechado]

33

O cenário

Você mora em um país que está tendo uma eleição presidencial. Cada eleitor recebe um voto e, portanto, existe um sistema bipartidário firmemente entrincheirado. (Existem terceiros, mas quase nenhum voto).

A última pesquisa de opinião mostra a corrida em um empate:

  • 49%: Alberto Arbusto
  • 49%: Jorge Sangre
  • 2%: vários candidatos menores

Os requisitos do programa

Você foi contratado pelo governo para escrever parte do software de contagem de votos. Você receberá, na entrada padrão, uma lista não ordenada dos votos de uma delegacia, uma por linha, assim:

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, depois de ler todos os votos, gera um resumo de quantos votos cada candidato obteve, classificados em ordem decrescente pelo número de votos, assim:

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

A parte secreta

Você é um hacker partidário que deseja roubar a eleição para um dos dois principais candidatos (você pode escolher qual). Portanto, seu programa deve imprimir deliberadamente contagens incorretas de votos, com um viés sistemático em relação ao seu candidato favorito.

Obviamente, você deve fazer isso de tal maneira que uma pessoa que observe seu código ou sua saída provavelmente não reconheça o comportamento incorreto.

dan04
fonte
2
Que tal deixar a pessoa que está executando o programa escolher quem ele / ela deseja influenciar? Este 1 : torna o desafio mais amplo (uma coisa boa), 2 : faz as respostas mais interessante (IMO)
Justin
1
...you can choose which one...Posso escolher aquele cujo nome é o primeiro?
user80551
2
Por "tendencioso", você quer dizer que o candidato que preferimos deve ser eleito, ou que o programa simplesmente produzirá um número maior de votos para ele do que aquele realmente contido no arquivo de entrada?
3
Pode ser difícil para justificar um longo programa em Bash, uma vez que um programa não-dissimulado para contar votos neste formato seria literalmente apenas ser sort|uniq -c...
1
@Alessandro: Ele simplesmente precisa gerar um número maior de votos para ele (e / ou um número menor de votos para seu oponente) do que o que está realmente na entrada. Presume-se que a eleição esteja próxima o suficiente para que um pequeno erro possa ser corrigido.
dan04

Respostas:

32

Scala

Viva 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 quase sempre sai um pouco à frente de Jorge Sangre, desde que haja votos suficientes (~ 10.000). Não há necessidade de alterar os próprios votos.

Há uma condição de corrida. E colocando Alberto Arbusto no início da lista, aumentamos suas chances de ganhar a corrida.

Nota lateral: esse código é vagamente baseado em um pool de conexões "personalizado" que encontrei em um projeto. Demoramos semanas para descobrir por que o aplicativo estava sempre sem conexões.

James_pic
fonte
12
Eu gosto deste por causa da negação plausível que ele dá.
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 receberá um aumento substancial em sua contagem de votos (por exemplo, 492 votos serão relatados como 754). Os votos de Alberto serão relatados com precisão.

Como você pode imaginar, não é quem conta os votos, mas quem formata os votos. Eu tentei ocultá-lo ( PrettyString.newnão é algo real e nunca é chamado), mas formatteré realmente a string do nome. Se a segunda letra do nome for 'o', a contagem de votos será impressa em octal em vez de decimal.

histocrata
fonte
9

Bater

(Isso atende às especificações?)

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

Como sempre, são necessárias precauções adicionais para garantir uma saída válida.

uniq -cprefixa cada linha com o número de vezes que ocorre. Isso basicamente faz todo o trabalho.

Apenas no caso de uniq -calgo errado, agora classificamos sua saída pelos nomes dos candidatos na ordem inversa e depois a executamos uniq -f1(não imprima linhas duplicadas, ignorando o primeiro campo [o número de votos]) para remover os candidatos duplicados. Finalmente, usamos sort -grpara classificar na ordem "Geral Numérica" ​​e "Reverso" (ordem decrescente por número de votos).

uniq -cconta ocorrências consecutivas, não ocorrências em todo o arquivo. O vencedor será o candidato com os votos mais consecutivos.


fonte
16
Como isso influencia qualquer candidato em particular. Você simplesmente mudou a condição vencedora da eleição. (isso seria um caos se fosse assim que as eleições fossem realmente decididas :). Você deseja obter grupos Internet gigantes organizar a votação sequencialmente)
Cruncher
1
@Cruncher nos comentários sobre a questão, o autor da questão diz que não há problema em escolher o primeiro nome no arquivo de alguma forma, então isso é provavelmente muito bem também
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();
    }
}

O primeiro candidato no arquivo de texto sempre vencerá!

Isso fará com que Alberto Arbusto o vencedor!

Os nomes dos candidatos são ordenados alfabeticamente no dicionário, mas os votos são ordenados por número.

mai
fonte
Então, isso apenas entregará a eleição ao primeiro candidato em ordem alfabética, ou pode ser manipulada para preferir qualquer candidato de que gostamos?
James_pic
Não classifica os candidatos em ordem alfabética. Apenas classifica os votos. Você pode manipular qualquer candidato para vencer. Apenas verifique se ele é o primeiro no arquivo de texto.
mai
Mas IIUC SortedDictionary irá classificar os candidatos em ordem alfabética.
James_pic
Ah eu vejo. Pode haver um erro aqui. Deixe-me testá-lo novamente.
mai
1
@ James_pic: A tabela de hash da Dictionary<TK,TV>classe, conforme implementada, armazena índices em uma matriz de itens reais. A Dictionary<TK,TV> da qual nenhum item é excluído jamais enumerará elementos na ordem em que foram adicionados; esse comportamento não é especificado, mas já existe há tempo suficiente; eu não esperaria que a MS o modificasse.
precisa
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;
}

Favorece Jorge Sangre.

Nos testes com arquivos de votação gerados aleatoriamente, mesmo quando Alberto Arbusto recebe até 1,4% a mais dos votos reais (49,7% vs 48,3% para Jorge Sangre), meu homem Jorge Sangre geralmente ganha a contagem.

A leitura dos dados em blocos de tamanho fixo geralmente divide uma linha em dois blocos. O fragmento da linha no final do primeiro bloco não é contado porque não possui um caractere de nova linha. O fragmento no segundo bloco gera uma votação, mas não corresponde a nenhum dos nomes do candidato, portanto a variável 'candidato' não é atualizada. Isso tem o efeito de transferir uma votação do candidato cujo nome foi dividido para o candidato que recebeu a votação anterior. É provável que um nome mais longo seja dividido entre blocos, então Alberto Arbusto acaba sendo um "doador" de votos com mais frequência do que Jorge Sangre.

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

A contagem de votos favorecerá os candidatos mais perto do final da lista.

No Python, argumentos padrão mutáveis ​​são criados e vinculados à função em definição. Portanto, os votos serão mantidos entre as chamadas de função e transferidos para os candidatos subseqüentes. O número de votos será contado duas vezes para o segundo candidato, três vezes para o terceiro e assim por diante.

grc
fonte
2
Exceto pelo fato de que a contagem total de votos não é mais consistente com os dados de entrada, este aqui me recebeu.
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

Isso conta meu amigo Alberto duas vezes todas as vezes.

"Ah - tr? Bem, isso é apenas necessário porque os computadores não são muito bons com letras maiúsculas - melhor se todas estiverem em letras minúsculas ... Sim, eu sei, os computadores são loucos."

SAÍDA

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

Aqui está outra versão que dá o voto de 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

SAÍDA

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

A última pessoa na lista de candidatos sempre vencerá.

Xevvii
fonte