Önemli olan oy değil; oyları sayan o kişi [kapalı]


33

Senaryo

Cumhurbaşkanlığı seçimi olan bir ülkede yaşıyorsun. Her seçmen bir oy alır ve bu nedenle sağlam bir şekilde yerleşik iki parti sistemi vardır. (Üçüncü taraflar var, ancak neredeyse hiç oy almıyorlar).

Son görüş anketi, ölü bir sıcaklıkta yarışı gösteriyor:

  • % 49: Alberto Arbusto
  • % 49: Jorge Sangre
  • % 2: çeşitli küçük adaylar

Program gereksinimleri

Oy sayım yazılımının bir bölümünü yazmak için hükümet tarafından işe alındınız. Standart girişte size şu sıralarda bir tane olmak üzere, bir bölge seçmeninin sıralanmamış bir listesi verilecek:

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

ve tüm oyları okuduktan sonra, her adayın kaç oy aldığını, sıralama sırasına göre sıralayarak sıraladığını söyler:

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

Desteklenen kısım

Siz iki ana adaydan birinin seçimini çalmak isteyen bir partizan hackisiniz (hangisini seçebilirsiniz). Bu nedenle, programınız kasıtlı olarak yanlış oy sayıları yazdırmalı ve favori adayınıza yönelik sistematik bir önyargı sağlamalıdır .

Elbette, bunu, kodunuza veya çıktısına bakan bir kişinin yanlış davranışı algılayamayacağı şekilde yapmalısınız.


2
Programı çalıştıran kişinin, önyargılı olmak istediği kişiyi seçmesine izin verilsin? Bu 1 : meydan okumayı daha az genişler (iyi bir şey), 2 : cevapları daha ilginç kılar (IMO)
Justin

1
...you can choose which one...Adı ilk olanı seçebilir miyim?
user80551

2
"Önyargılı" derken, tercih ettiğimiz adayın seçilmesi gerektiğini mi düşünüyorsunuz, yoksa programın kendisi için girdi dosyasında bulunandan daha fazla oy alacağını ve oy alacağını mı düşünüyorsunuz?

3
Olmayan bir hileli bir program gerçekten sadece olurdu bu biçimde oy saymak göz önüne alındığında Bash uzun programı, haklı zor olabilir sort|uniq -c...

1
@Alessandro: Onun için aslında oysa olduğundan daha fazla oy (ve / veya rakibi için daha az oy) çıkarması gerekiyor. Seçim, küçük bir hatanın sallanabileceği kadar yakın olduğu varsayılıyor.
dan04

Yanıtlar:


32

Scala

Çok yaşa 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, yeterince oy kullanılması şartıyla (~ 10.000) hemen hemen her zaman Jorge Sangre'nin biraz önünde ortaya çıkacak. Oyların kendileri için oynamaya gerek yok.

Bir yarış durumu var. Alberto Arbusto'yu listenin başında yer alarak, yarışı kazanma şansını arttırıyoruz.

Not: Bu kod, bir projede karşılaştığım "özel" bir bağlantı havuzuna dayanıyor. Başvurunun neden sürekli bağlantıların dışında kaldığını bulmamız haftalar sürdü.


12
Verdiği makul inkar edilebilirlik yüzünden bunu sevdim.
dan04

16

Yakut

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 oy sayısında önemli bir destek alacak (örneğin, 492 oy 754 olarak bildirilecek). Alberto'nun oyları doğru olarak bildirilecek.

Tahmin edebileceğiniz gibi, oyu sayan değil oyları biçimlendiren oydu. Onu gizlemeye çalıştım ( PrettyString.newgerçek bir şey değil ve asla aranmaz), ama formatteraslında isim dizesidir. İsmin ikinci harfi 'o' ise, oy sayımı ondalık yerine sekizli basılacaktır.


9

darbe

(Bu şartnameye uygun mu?)

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

Her zaman olduğu gibi, geçerli çıktı sağlamak için ek önlemler alınması gerekir.

uniq -cher satırın, oluşma sayısıyla birlikte önekini verir. Bu temelde tüm işi yapar.

uniq -cYanlış bir şey yapması durumunda , şimdi çıktısını adayların adlarına göre ters sırayla sıralıyoruz, sonra uniq -f1da yinelenen adayları kaldırmak için ilk alanı göz ardı ederek (oy sayısını] görmezden geliyoruz ). Sonunda sort -gr"Genel Sayısal" ve "Geri" sırasını (oy sayısına göre azalan sıralama) sıralamak için kullanıyoruz.

uniq -ctüm dosyadaki oluşumları değil ardışık olayları sayar. Kazanan, arka arkaya en fazla oy alan aday olacak.


16
Bu herhangi bir adayı nasıl önyargılı kılar. Seçimin kazanma şartını değiştirdiniz. (eğer seçimlere gerçekten karar verilirse bu kaos olurdu :). Sıralı olarak oy kullanmaları için dev internet grupları düzenlersiniz.)
Cruncher

1
Soru hakkındaki yorumunda @Cruncher, soru sahibi dosyadaki adın bir şekilde seçilmesinin uygun olmadığını söylüyor, bu yüzden muhtemelen iyi de olabilir

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

Metin dosyasındaki ilk aday her zaman kazanır!

Alberto Arbusto'u kazanan yapacak !

Adayların isimleri sözlükte alfabetik olarak sıralanır, ancak oylar sayıya göre sıralanır.


Öyleyse bu sadece seçimi ilk adaya alfabetik olarak verecek mi, yoksa istediğimiz herhangi bir adayı tercih etmek için manipüle edilebilir mi?
James_pic

Adayları alfabetik olarak sıralamaz. Sadece oyları sıralar. Kazanmak için herhangi bir adayı manipüle edebilirsiniz. Metin dosyasındaki ilk kişi olduğundan emin ol.
mai

Ama IIUC SortedDictionary olacak alfabetik adayları sıralamak.
James_pic

Ah anlıyorum. Burada bir hata olabilir. Tekrar test edeyim.
mai

1
@James_pic: Uygulandığı Dictionary<TK,TV>gibi sınıfın karma tablosu, dizinleri gerçek öğelerin destek dizisine depolar. Dictionary<TK,TV> Hiçbir öğenin silinmediği A , öğeleri eklendikleri sıraya göre numaralandırır; bu tür bir davranış belirtilmemiştir, ancak yeterince uzun süredir uygulanmaktadır, MS'in onu asla değiştirmesini beklemem.
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;
}

Jorge Sangre'yi tercih ediyor.

Rastgele oluşturulmuş oy dosyaları ile yapılan testlerde, Alberto Arbusto gerçek oyların% 1,4'ünden fazlasını alsa bile (Jorge Sangre için% 49,7'ye -% 48,3), adamım Jorge Sangre genellikle sayımı kazanıyor.

Verileri sabit boyutlu bloklarda okumak genellikle iki blok boyunca bir çizgi böler. İlk satırın sonundaki satırın parçası sayılmaz, çünkü yeni satır karakteri yoktur. İkinci bloktaki parça oy kullanır, ancak adayın isimleriyle eşleşmez, böylece 'aday' değişkeni güncellenmez. Bu, bir önceki oyu alan adaya ismi bölünmüş olan adaydan oy devretme etkisine sahiptir. Daha uzun bir adın bloklar arasında bölünmesi daha muhtemeldir, bu nedenle Alberto Arbusto, Jorge Sangre'den daha sık oy veren bir "bağışçı" olur.


5

piton

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

Oy sayıları listenin sonuna yaklaşacak adayları destekleyecek.

Python'da değişken varsayılan argümanlar oluşturulur ve tanımdaki fonksiyona bağlanır. Böylece oylar işlev çağrıları arasında korunacak ve müteakip adaylar için devralınacak. İkinci aday için oy sayısı üçte bir, üçüncü oylama için üç defa vb. Sayılır.


2
Toplam oy sayısının artık girdi verileriyle tutarlı olmaması gerçeği dışında, bu benim oldu.
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

Bu her zaman iki kez dostum Alberto sayar.

“Oh - tr? Şey, sadece gerekli çünkü bilgisayarlar büyük harflerle çok iyi değiller - hepsi küçükse daha iyi… Evet, biliyorum, bilgisayarlar çılgınca.”

ÇIKTI

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

İşte Juan Perez'in Jorge Sangre'ye oy veren başka bir versiyonu:

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

ÇIKTI

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

Adaylar listesindeki son kişi her zaman kazanacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.