Не голосує той, хто голосує; це хто підраховує голоси [закрито]


33

Сценарій

Ви живете в країні, в якій проводяться президентські вибори. Кожен виборець отримує один голос, і тому існує міцно закріплена двопартійна система. (Треті сторони існують, але голоси майже не отримують).

Останнє опитування думки показує гонку в мертву спеку:

  • 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 : робить відповіді цікавішими (ІМО)
Джастін

1
...you can choose which one...Чи можу я вибрати того, чиє ім’я перше?
користувач80551

2
Під "упередженим" ви маєте на увазі, що кандидата, якого ми віддаємо перевагу, повинні бути обрані, або, якщо програма просто видасть за нього і більша кількість голосів, ніж той, який насправді міститься у вхідному файлі?

3
Це може бути важко виправдати довгу програму в Bash, враховуючи, що програма, яка не піддається підрахунку голосів у такому форматі, буде буквально просто sort|uniq -c...

1
@ Алессандро: Просто потрібно набрати більшу кількість голосів за нього (та / або меншу кількість голосів за його опонента), ніж те, що є насправді. Передбачається, що вибори є досить близькими, щоб невелика помилка могла змінити його.
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}"
}

Альберто Арбусто майже завжди вийде трохи попереду Хорхе Сангре за умови подання достатньої кількості голосів (~ 10 000). Не потрібно підробляти самі голоси.

Умови гонки. І, поклавши Альберто Арбусто раніше в цьому списку, ми збільшуємо його шанси на перемогу в гонці.

Побічна примітка: Цей код слабо базується на "спеціальному" пулі з'єднань, з яким я стикався в проекті. Ми зайняли у нас тижні, щоб з’ясувати, чому програма постійно перебуває поза зв’язками.


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

Хорхе Сангре отримає істотний приріст у своєму підрахунку голосів (наприклад, 492 голоси будуть повідомлені як 754). Голоси Альберто будуть повідомлені точно.

Як ви здогадуєтесь, голосувати не хто, а хто формулює голоси. Я намагався приховати це ( PrettyString.newне реальна річ і ніколи не називається), але formatterнасправді це рядок імен. Якщо друга літера назви є "о", підрахунок голосів друкується у восьмеричній формі замість десяткової.


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

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

Перший кандидат у текстовому файлі завжди переможе!

Це зробить Альберто Арбусто переможцем!

Імена кандидатів в алфавіті впорядковуються за алфавітом, але голоси впорядковуються за номером.


Тож це просто передасть вибори першому кандидату в алфавітному порядку, чи можна маніпулювати тим, щоб віддати перевагу будь-якому кандидату, який нам подобається?
James_pic

Він не сортує кандидатів за алфавітом. Він лише сортує голоси. Ви можете маніпулювати будь-яким кандидатом для перемоги. Просто переконайтесь, що він перший у текстовому файлі.
травень

Але МСК SortedDictionary буде сортувати кандидатів за алфавітом.
James_pic

О Я бачу. Тут може бути помилка. Дозвольте перевірити його ще раз.
травень

1
@James_pic: Хеш-таблиця Dictionary<TK,TV>класу, як реалізовано, зберігає індекси в резервному масиві фактичних елементів. A, Dictionary<TK,TV> з якого жоден елемент не буде видалений, будуть перераховані елементи в тому порядку, в який вони були додані; така поведінка не вказана, але вона існує досить довго, я б не очікував, що MS коли-небудь змінить її.
supercat

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

Віддає перевагу Хорхе Сангре.

Під час тестування з випадковим чином генерованих файлів голосів, навіть коли Альберто Арбусто отримує до 1,4% більше від фактичних голосів (49,7% проти 48,3% за Хорхе Сангре), мій чоловік Хорхе Сангре зазвичай перемагає підрахунок.

Читання даних у блоках фіксованого розміру часто розбиває рядок на два блоки. Фрагмент рядка в кінці першого блоку не враховується, оскільки він не має символу нової лінії. Фрагмент у другому блоці дійсно генерує голосування, але він не відповідає жодному з імен кандидата, тому змінна "kandidat" не оновлюється. Це призводить до перенесення голосу від кандидата, ім'я якого було розділене на кандидата, який отримав попереднє голосування. Більш імовірна назва, швидше за все, буде розділена на блоки, тому Альберто Арбусто в кінцевому підсумку стає "донором" голосу частіше, ніж Хорхе Сангре.


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

Підрахунок голосів сприятиме кандидатам ближче до кінця списку.

У Python створюються змінні аргументи за замовчуванням і прив'язуються до функції за визначенням. Таким чином, голосування зберігатимуться між функціональними викликами та передаватимуться наступним кандидатам. Кількість голосів буде підрахована двічі за другого кандидата, три рази за третього тощо.


2
За винятком того, що загальний підрахунок голосів більше не відповідає вхідним даним, у мене був такий.
Заїд

0

тр | 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

Це рахує мого приятеля Альберто двічі кожен раз.

"О - tr? Ну, це просто необхідно, тому що комп’ютери не дуже гарні з великої літери - краще, якщо вони всі маленькі літери .... Так, я знаю, комп'ютери божевільні".

ВИХІД

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

Ось ще одна версія, яка дає голос Хуана Переса Хорхе Сангре:

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

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

Останній у списку кандидатів завжди переможе.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.