누가 투표를하는지는 중요하지 않습니다. 투표 수를 세는 사람 [폐쇄]


33

시나리오

대통령 선거가있는 나라에 살고 있습니다. 각 유권자는 1 표를 얻으 므로 확고한 2 자 시스템이 있습니다. (타사들은 존재하지만 투표권은 거의 없습니다).

최근 여론 조사에서는 열악한 경쟁 속에서 인종을 보여줍니다.

  • 49 % : 알베르토 아르 부스 토
  • 49 % : 호르헤 상그레
  • 2 % : 다양한 부전공 후보

프로그램 요구 사항

귀하는 투표 계산 소프트웨어의 일부를 작성하기 위해 정부에 고용되었습니다. 다음과 같이 표준 입력에서 한 선거구의 투표 목록을 한 줄에 하나씩 순서대로 표시합니다.

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 : 답을 더 흥미롭게 만듭니다 (IMO)
Justin

1
...you can choose which one...이름이 처음 인 사람을 선택할 수 있습니까?
user80551

2
"바이어스 드 (biased)"란 우리가 선호하는 후보가 선출되어야합니까, 아니면 프로그램이 입력 파일에 실제로 포함 된 것보다 더 많은 수의 투표를 단순히 출력 할 것입니까?

3
이 형식으로 투표를 계산하는 비공 인 프로그램이 문자 그대로 다음과 같은 점을 고려하면 Bash에서 긴 프로그램을 정당화하는 것이 어려울 수 있습니다 sort|uniq -c.

1
@Alessandro : 그것은 실제로 입력에있는 것보다 더 많은 수의 득표 수 (및 / 또는 상대의 득표 수)를 출력하면됩니다. 선거는 작은 오류로 인해 선거가 시작될 수있을 정도로 충분히 가까운 것으로 추정됩니다.
dan04

답변:


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

Alberto Arbusto는 충분한 투표가 이루어지면 (~ 10,000) 거의 항상 Jorge Sangre보다 약간 앞서 나올 것입니다. 투표 자체를 조작 할 필요가 없습니다.

경쟁 조건이 있습니다. 그리고 Alberto Arbusto를 먼저 목록에 올리면 레이스에서 우승 할 가능성이 높아집니다.

참고 :이 코드는 프로젝트에서 발생한 "사용자 지정"연결 풀을 기준으로 느슨하게 작성되었습니다. 애플리케이션이 연결이 끊어진 이유를 파악하는 데 몇 주가 걸렸습니다.


12
나는 그럴듯한 부인 가능성 때문에 이것을 좋아한다.
dan04

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

Jorge Sangre는 그의 투표 수를 크게 늘릴 것입니다 (예 : 492 표는 754로 표시됩니다). Alberto의 투표는 정확하게보고 될 것입니다.

당신이 짐작할 수 있듯이, 누가 투표를 세는지가 아니라 누가 투표의 형식을 정합니까? 나는 그것을 모호하려고 노력했지만 ( PrettyString.new실제가 아니며 결코 호출되지 않습니다) formatter실제로는 이름 문자열입니다. 이름의 두 번째 문자가 'o'이면 투표 수가 10 진수 대신 8 진수로 인쇄됩니다.


9

세게 때리다

(이것이 사양을 충족합니까?)

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

항상 그렇듯이 유효한 출력을 보장하기 위해 추가 예방 조치가 필요합니다.

uniq -c각 줄 앞에 발생 횟수가 붙습니다. 이것은 기본적으로 모든 작업을 수행합니다.

uniq -c잘못된 일이 발생할 경우 , 후보의 이름을 기준으로 결과를 역순으로 정렬 한 다음 uniq -f1중복 된 후보를 제거하기 위해 첫 번째 필드 (투표 수)를 무시하고 중복 행을 인쇄하지 마십시오. 마지막으로 sort -gr"일반 숫자"와 "역"순서로 정렬합니다 (투표 수에 따라 내림차순).

uniq -c전체 파일에서 발생하는 것이 아니라 연속적인 발생을 계산합니다. 가장 많은 표를 얻은 후보자가 승자가됩니다.


16
이것은 특정 후보를 어떻게 편향 시키는가. 당신은 단순히 선거의 승리 조건을 변경했습니다. (이것이 선거가 실제로 결정된 방식이라면 혼란이 될 것입니다 :). 당신은 순차적으로 투표를 조직하는 거대한 인터넷 그룹을 얻게 될 것입니다)
Cruncher

1
질문에 대한 의견에서 @Cruncher는 어떤 식 으로든 파일에서 이름을 선택하는 것이

9

기음#

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

텍스트 파일의 첫 번째 후보자는 항상 승리합니다!

Alberto Arbusto 가 승자 가 될 것입니다 !

후보자의 이름은 사전에서 사전 순으로 정렬되지만 투표는 번호순으로 정렬됩니다.


그렇다면 이것은 첫 번째 후보자에게 선거를 알파벳 순으로 넘기거나 우리가 좋아하는 후보자를 선호하도록 조작 할 수 있습니까?
James_pic

후보자를 알파벳순으로 정렬하지 않습니다. 투표 만 정렬합니다. 당신은 이길 후보를 조작 할 수 있습니다. 텍스트 파일에서 첫 번째 사람인지 확인하십시오.
mai

그러나 IIUC SortedDictionary 후보자를 사전 순으로 정렬합니다.
James_pic

아, 알겠습니다 여기에 실수가있을 수 있습니다. 다시 테스트하겠습니다.
mai

1
@James_pic : Dictionary<TK,TV>구현 된 클래스 의 해시 테이블은 인덱스를 실제 항목의 백업 배열에 저장합니다. Dictionary<TK,TV> 항목이 이제까지 삭제되지 않습니다있는 가 추가 된 순서대로 요소를 열거합니다; 그러한 행동은 명시되어 있지 않지만 MS가 그것을 바꿀 것으로 예상하지 않을 정도로 오래되었습니다.
supercat 2016 년

7

기음

#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의 48.3 % vs. 47.2 %) 내 남자 Jorge Sangre가 일반적으로 이깁니다.

고정 크기 블록에서 데이터를 읽으면 종종 두 블록에 선이 분할됩니다. 첫 번째 블록 끝에있는 줄 조각은 줄 바꿈 문자가 없으므로 계산되지 않습니다. 두 번째 블록의 조각은 투표를 생성하지만 후보자의 이름과 일치하지 않으므로 '후보'변수가 업데이트되지 않습니다. 이는 이름이 나뉘어 진 후보자에서 이전 투표를받은 후보자에게 투표권을 이전시키는 효과가 있습니다. 더 긴 이름은 여러 블록으로 나뉘어 질 가능성이 높기 때문에 Alberto Arbusto는 Jorge Sangre보다 더 자주 "공여국"으로 표결됩니다.


5

파이썬

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

투표 수는 목록의 끝에 가까운 후보를 선호합니다.

파이썬에서는 변경 가능한 기본 인수가 만들어지고 정의시 함수에 바인딩됩니다. 따라서 투표는 함수 호출 사이에 유지되고 후속 후보에 대해 이월됩니다. 투표 수는 두 번째 후보의 경우 두 번, 세 번째의 경우 세 번 등으로 계산됩니다.


2
총 투표 수가 더 이상 입력 데이터와 일치하지 않는다는 사실을 제외하고는 저에게 있습니다.
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

이것은 매번 내 친구 Alberto를 두 번 계산합니다.

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

자바 스크립트

    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.