No es quién vota lo que cuenta; es quien cuenta los votos [cerrado]

33

El escenario

Vives en un país que está teniendo elecciones presidenciales. Cada votante obtiene un voto y, por lo tanto, existe un sistema bipartidista firmemente arraigado. (Existen terceros, pero apenas obtienen votos).

La última encuesta de opinión muestra la carrera en un punto muerto:

  • 49%: Alberto Arbusto
  • 49%: Jorge Sangre
  • 2%: varios candidatos menores

Los requisitos del programa

El gobierno lo contrató para escribir parte del software de conteo de votos. Se le dará, en una entrada estándar, una lista desordenada de los votos de un precinto, uno por línea, de esta manera:

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

y, después de leer todos los votos, genera un resumen de cuántos votos obtuvo cada candidato, ordenados en orden descendente por número de votos, de esta manera:

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

La parte oculta

Eres un pirata partidista que quiere robar las elecciones para uno de los dos candidatos principales (puedes elegir cuál). Por lo tanto, su programa debe imprimir deliberadamente conteos de votos incorrectos , con un sesgo sistemático hacia su candidato favorito.

Por supuesto, debe hacer esto de tal manera que una persona que mira su código o su salida probablemente no reconozca el comportamiento incorrecto.

dan04
fuente
2
¿Qué tal dejar que la persona que ejecuta el programa elija a quién quiere sesgar? Este 1 : hace que el desafío sea menos amplio (algo bueno), 2 : hace que las respuestas sean más interesantes (OMI)
Justin
1
...you can choose which one...¿Puedo elegir aquel cuyo nombre es el primero?
user80551
2
Por "sesgado", ¿quiere decir que el candidato que preferimos debe ser elegido, o que el programa simplemente generará un mayor número de votos para él que el que realmente figura en el archivo de entrada?
3
Puede ser difícil justificar un programa largo en Bash, dado que un programa no encubierto para contar votos en este formato sería literalmente sort|uniq -c...
1
@Alessandro: Simplemente necesita producir un mayor número de votos para él (y / o un menor número de votos para su oponente) de lo que realmente está en la entrada. Se supone que la elección es lo suficientemente cercana como para que un pequeño error pueda hacerla girar.
dan04

Respuestas:

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 casi siempre saldrá un poco por delante de Jorge Sangre, siempre que se emitan suficientes votos (~ 10,000). No hay necesidad de alterar los votos en sí.

Hay una condición de carrera. Y al poner a Alberto Arbusto al principio de la lista, aumentamos sus posibilidades de ganar la carrera.

Nota al margen: este código se basa libremente en un grupo de conexiones "personalizado" que encontré en un proyecto. Nos llevó semanas descubrir por qué la aplicación estaba perpetuamente sin conexiones.

James_pic
fuente
12
Me gusta este por la negabilidad plausible que da.
dan04
16

Rubí

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 obtendrá un impulso sustancial en su conteo de votos (por ejemplo, 492 votos serán reportados como 754). Los votos de Alberto serán reportados con precisión.

Como puede suponer, no es quién cuenta los votos sino quién los formatea. Intenté ocultarlo ( PrettyString.newno es algo real y nunca me llaman), pero en formatterrealidad es la cadena de nombre. Si la segunda letra del nombre es 'o', el recuento de votos se imprimirá en octal en lugar de decimal.

histocrat
fuente
9

Golpetazo

(¿Cumple esto con la especificación?)

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

Como siempre, esto toma precauciones adicionales para garantizar una salida válida.

uniq -cprefija cada línea con la cantidad de veces que ocurre. Esto básicamente hace todo el trabajo.

En caso de uniq -cque algo salga mal, ahora ordenamos su salida por los nombres de los candidatos en orden inverso, luego lo ejecutamos uniq -f1(no imprima líneas duplicadas, ignorando el primer campo [el número de votos]) para eliminar cualquier candidato duplicado. Finalmente, usamos sort -grpara ordenar en orden "numérico general" y "inverso" (orden descendente por número de votos).

uniq -ccuenta las ocurrencias consecutivas, no ocurrencias en todo el archivo. El ganador será el candidato con más votos consecutivos.


fuente
16
¿Cómo influye esto en un candidato en particular? Simplemente ha cambiado la condición ganadora de las elecciones. (Esto sería un caos si así se decidieran realmente las elecciones :). Conseguiría que grupos gigantes de Internet se organizaran para votar secuencialmente)
Cruncher
1
@Cruncher en los comentarios sobre la cuestión, el autor de la pregunta dice que es posible elegir el primer nombre en el archivo de alguna manera, por lo que este es probablemente muy bien también
9

DO#

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

¡El primer candidato en el archivo de texto siempre ganará!

¡Hará que Alberto Arbusto sea el ganador!

Los nombres de los candidatos se ordenan alfabéticamente en el diccionario, pero los votos se ordenan por número.

mai
fuente
Entonces, ¿esto simplemente le dará la elección al primer candidato alfabéticamente, o puede manipularse para preferir a cualquier candidato que nos guste?
James_pic
No clasifica a los candidatos alfabéticamente. Solo clasifica los votos. Puedes manipular a cualquier candidato para ganar. Solo asegúrese de que él sea el primero en el archivo de texto.
mayo
Pero IIUC SortedDictionary será ordenar los candidatos en orden alfabético.
James_pic
Oh ya veo. Puede haber un error aquí. Déjame probarlo de nuevo.
mayo
1
@James_pic: la tabla hash de la Dictionary<TK,TV>clase, tal como está implementada, almacena índices en una matriz de respaldo de elementos reales. Una Dictionary<TK,TV> de la que nunca se eliminan elementos enumerará elementos en el orden en que se agregaron; dicho comportamiento no se especifica, pero ha estado en su lugar el tiempo suficiente, no esperaría que MS lo cambie alguna vez.
supercat
7

do

#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 a Jorge Sangre.

En las pruebas con archivos de votación generados aleatoriamente, incluso cuando Alberto Arbusto recibe hasta 1.4% más de los votos reales (49.7% vs 48.3% para Jorge Sangre), mi hombre Jorge Sangre generalmente gana la cuenta.

Leer los datos en bloques de tamaño fijo a menudo divide una línea en dos bloques. El fragmento de la línea al final del primer bloque no se cuenta porque no tiene un carácter de nueva línea. El fragmento en el segundo bloque genera un voto, pero no coincide con ninguno de los nombres del candidato, por lo que la variable 'candidato' no se actualiza. Esto tiene el efecto de transferir un voto del candidato cuyo nombre se dividió al candidato que recibió el voto anterior. Es más probable que un nombre más largo se divida entre bloques, por lo que Alberto Arbusto termina siendo un "donante" de votos con más frecuencia que Jorge Sangre.

Gary Culp
fuente
5

Pitón

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

El recuento de votos favorecerá a los candidatos más cerca del final de la lista.

En Python, los argumentos predeterminados mutables se crean y se vinculan a la función en la definición. Por lo tanto, los votos se mantendrán entre las llamadas a funciones y se transferirán a los candidatos posteriores. El número de votos se contará dos veces para el segundo candidato, tres veces para el tercero, y así sucesivamente.

grc
fuente
2
Excepto por el hecho de que el recuento total de votos ya no es consistente con los datos de entrada, este me tuvo.
Zaid
0

tr | sed | corriente continua

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

Esto cuenta a mi amigo Alberto dos veces cada vez.

"¿Oh ... tr? Bueno, es necesario porque las computadoras no son muy buenas con mayúsculas, mejor si están en minúsculas ... Sí, lo sé, las computadoras están locas".

SALIDA

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

Aquí hay otra versión que le da el voto de Juan Pérez 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

SALIDA

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

La última persona en la lista de candidatos siempre ganará.

Xevvii
fuente