Boost logo

Boost :

From: Jason Hise (chaos_at_[hidden])
Date: 2005-03-31 02:08:21


I thought it would be fun to quickly try to write a program to do IRV
voting. Hopefully it can be used to make the lives of the people
counting the votes a bit easier. The file piped into cin should list
each voter's choices in descending order on separate lines after a line
containing only the string "vote:". For instance, the following input
represents four unnamed voters, each of whom was allowed three votes,
and who made first choices of a, b, c, and a, respectively.

vote:
a
b
c
vote:
b
c
d
vote:
c
d
e
vote:
a
b
f

Running the program with this input results in the following output.

clearing votes for a
clearing votes for b
clearing votes for c
clearing votes for d
clearing votes for e
clearing votes for f
a now has 1 votes
b now has 1 votes
c now has 1 votes
a now has 2 votes
d has been removed from the running
e has been removed from the running
f has been removed from the running
clearing votes for a
clearing votes for b
clearing votes for c
a now has 1 votes
b now has 1 votes
c now has 1 votes
a now has 2 votes
b has been removed from the running
c has been removed from the running
clearing votes for a
a now has 1 votes
a now has 2 votes

WINNER:
a

If I made any errors in my implementation of the voting algorithm,
please let me know. I hope someone finds this useful, but if not, at
least it was fun to write :)

-Jason


#include <string>
#include <vector>
#include <list>
#include <map>
#include <iostream>

using namespace std;

int main ( )
{
    string s;
    list < string > vote;
    vector < list < string > > votes;
    map < string, size_t > candidates;

    while ( true )
    {
        getline ( cin, s );
        if ( cin.eof ( ) )
        {
            if ( !vote.empty ( ) ) votes.push_back ( vote );
            break;
        }

        if ( s == "vote:" )
        {
            if ( !vote.empty ( ) )
            {
                votes.push_back ( vote );
                vote.clear ( );
            }
        }
        else
        {
            candidates.insert ( map < string, size_t >::value_type ( s, 0 ) );
            vote.push_back ( s );
        }
    }

    bool winner = false;
    size_t min_votes;
    map < string, size_t >::iterator c_iter, c_next;
    vector < list < string > >::iterator vl_iter;

    while ( !winner )
    {
        c_iter = candidates.begin ( );
        while ( c_iter != candidates.end ( ) )
        {
            cout << "clearing votes for " << c_iter->first << endl;
            c_iter->second = 0;
            ++c_iter;
        }

        vl_iter = votes.begin ( );
        while ( vl_iter != votes.end ( ) )
        {
            list < string >::iterator v_iter ( vl_iter->begin ( ) );
            while ( v_iter != vl_iter->end ( ) )
            {
                c_iter = candidates.find ( *v_iter );
                if ( c_iter != candidates.end ( ) )
                {
                    ++( c_iter->second );
                    cout << c_iter->first << " now has " << c_iter->second << " votes" << endl;
                    break;
                }

                ++v_iter;
            }

            ++vl_iter;
        }

        c_iter = candidates.begin ( );
        min_votes = c_iter->second;
        winner = true;
        while ( c_iter != candidates.end ( ) )
        {
            if ( c_iter->second < min_votes )
            {
                min_votes = c_iter->second;
                winner = false;
            }
            ++c_iter;
        }

        if ( winner )
        {
            if ( candidates.size ( ) > 1 )
            {
                cout << endl << "TIE, WINNERS WERE:" << endl;
            }
            else
            {
                cout << endl << "WINNER:" << endl;
            }
        }

        c_iter = candidates.begin ( );
        while ( c_iter != candidates.end ( ) )
        {
            c_next = c_iter;
            ++c_next;

            if ( winner )
            {
                cout << c_iter->first << endl;
            }
            else if ( c_iter->second == min_votes )
            {
                cout << c_iter->first << " has been removed from the running" << endl;
                candidates.erase ( c_iter );
            }

            c_iter = c_next;
        }
    }

    return 0;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk