title: Good Versus Evil

text:
# Question
Title: Good Versus Evil
# Results - July 19, 2014

The current King of the Hill is Mercenary by user Fabigler! Keep submitting entries and knock him off of his throne!

**Click here to view the Scoreboard.**

Programs submitted on or before July 19, 2014 were included. All other submissions will be included in future trials. New results should be posted around August 9, so that gives you plenty of time.

---

Illustrated by Chris Rainbolt, my brother and a fresh graduate from Savannah College of Art and Design

# Introduction

The angels and demons are fighting and, as usual, using earth as their battleground. Humans are stuck in the middle and are being forced to take sides. An unknown neutral force rewards those who consistently fight for the losing side.

# The Game

Each trial, you will be pseudorandomly paired and then shuffled with between 20 and 30 other submissions. Each trial will consist of 1000 rounds. Each round, you will be passed an input and be expected to produce output. Your output will be recorded and scored. This process will be repeated 1000 times.

**Input**

You will receive a single argument that represents the past votes of each player. Rounds are delimited by comma. A `0` represents a player who sided with Evil that round. A `1` represents a player who sided with Good. Within a trial, the players will always be in the same order. Your own vote will be included, but not explicitly identified. For example:

> 101,100,100

In this example, three rounds have been completed and three players are competing. Player one always sided with Good. Player two always sided with Evil. Player three swapped from Good in round 1 to Evil in rounds 2 and 3. One of those players was you.

**Output**

Java Submissions

* Return the string `good` if you want to side with Good.
* Return the string `evil` if you want to side with Evil.

Non-Java Submissions

* Output the string `good` to stdout if you want to side with Good.
* Output the string `evil` to stdout if you want to side with Evil.

If your program outputs or returns anything else, throws an exception, does not compile, or takes longer than one second to output anything on this exact machine, then it will be disqualified.

**Scoring**

Scores will be posted in a Google docs spreadsheet for easy viewing as soon as I can compile all the current entries. Don't worry - I will keep running trials for as long as you guys keep submitting programs!

* You receive 3 points for siding with the majority during a round.
* You receive n - 1 points for siding with the minority during a round, where n is the number of consecutive times you have sided with the minority.

Your score will be the median of 5 trials. Each trial consists of 1000 rounds.

# Deliverables

**Non-Java Submissions**

You must submit a unique title, a program, and a Windows command line string that will run your program. Remember that an argument may be appended to that string. For example:

* `python Angel.py`
    + Note that this one has no args. This is round one! Be prepared for this.
* `python Angel.py 11011,00101,11101,11111,00001,11001,11001`

**Java Submissions**

You must submit a unique title and a Java class that extends the abstract Human class written below.

```
public abstract class Human {
    public abstract String takeSides(String history) throws Exception;
}

```

# Testing

If you want to test your own submission, follow the instructions here.

# Additional Notes

You may submit as many different submissions as you want. Submissions that appear to be colluding will be disqualified. The author of this challenge will be the only judge on that matter.

A new instance of your program or Java class will be created every time it is called upon. You may persist information by writing to a file. You may not modify the structure or behavior of anything except your own class.

Players will be shuffled before the trial starts. Demon and Angel will participate in every trial. If the number of players is even, Petyr Baelish will also join. Demon fights for Evil, Angel for Good, and Petyr Baelish chooses a pseudorandom side.

# Answer
## The Mercenary

Always sides with the one who paid the most money last round.

Taking into account that good people earn statistically more.

```
package Humans;
public class Mercenary extends Human {
    public String takeSides(String history) {
        // first round random!
        if (history.length() == 0) {
            return Math.random() >= 0.5 ? "good" : "evil";
        }

        String[] rounds = history.split(",");
        String lastRound = rounds[rounds.length - 1];

        double goodMoneyPaid = 0;
        double evilMoneyPaid = 0;
        for (char c : lastRound.toCharArray()) {
                switch (c) {
                case '0':
                    goodMoneyPaid = goodMoneyPaid + 0.2; //statistically proven: good people have more reliable incomes
                    break;
                case '1':
                    evilMoneyPaid++;
                    break;
                default:
                    break;
                }
        }

        if (goodMoneyPaid > evilMoneyPaid)
        {
            return "good";
        } else {
            return "evil";
        }
    }
}

```
> 11 votes

# Answer
## Hipster, Ruby

```
if ARGV.length == 0
    puts ["good", "evil"].sample
else
    last_round = ARGV[0].split(',').last
    n_players = last_round.length
    puts last_round.count('1') > n_players/2 ? "evil" : "good"
end

```

Simply goes with last round's minority, just because everything else is mainstream.

Run like

```
ruby hipster.rb

```
> 39 votes

# Answer
# Petyr Baelish

You never know whose side Petyr Baelish is on.

```
package Humans;

/**
 * Always keep your foes confused. If they are never certain who you are or
 * what you want, they cannot know what you are likely to do next.
 * @author Rusher
 */
public class PetyrBaelish extends Human {

    /**
     * Randomly take the side of good or evil.
     * @param history The past votes of every player
     * @return A String "good" or "evil
     */
    public String takeSides(String history) {
        return Math.random() < 0.5 ? "good" : "evil";
    }
}

```

This entry will only be included if the number of players is even. This ensures that there will always be a majority.
> 30 votes

# Answer
## C++, The Meta Scientist

This one does essentially the same as The Scientist, but doesn't operate on rounds as a whole but on the individual players. It tries to map a wave (or a constant function) to each player separately and predicts their move in the next round. From the resulted round prediction, The Meta Scientist chooses whichever side looks like having a majority.

```
#include <iostream>
#include <utility>
#include <cstdlib>
#include <cstring>
#if 0
#define DBG(st) {st}
#else
#define DBG(st)
#endif

#define WINDOW (200)

using namespace std;

int main(int argc,char **argv){
    if(argc==1){
        cout<<(rand()%2?"good":"evil")<<endl;
        return 0;
    }
    DBG(cerr<<"WINDOW="<<WINDOW<<endl;)
    int nump,numr;
    nump=strchr(argv[1],',')-argv[1];
    numr=(strlen(argv[1])+1)/(nump+1);
    int period,r,p;
    int score,*scores=new int[WINDOW];
    int max; //some score will always get above 0, because if some score<0, the inverted wave will be >0.
    int phase,phasemax;
    int predicted=0; //The predicted number of goods for the next round
    int fromround=numr-WINDOW;
    if(fromround<0)fromround=0;
    pair<int,int> maxat; //period, phase
    DBG(cerr<<"Players:"<<endl;)
    for(p=0;p<nump;p++){
        DBG(cerr<<" p"<<p<<": ";)
        for(r=fromround;r<numr;r++)if(argv[1][r*(nump+1)+p]!=argv[1][p])break;
        if(r==numr){
            DBG(cerr<<"All equal! prediction="<<argv[1][p]<<endl;)
            predicted+=argv[1][(numr-1)*(nump+1)+p]-'0';
            continue;
        }
        max=0;
        maxat={-1,-1};
        for(period=1;period<=WINDOW;period++){
            scores[period-1]=0;
            phasemax=-1;
            for(phase=0;phase<2*period;phase++){
                score=0;
                for(r=fromround;r<numr;r++){
                    if(argv[1][r*(nump+1)+p]-'0'==1-(r+phase)%(2*period)/period)score++;
                    else score--;
                }
                if(score>scores[period-1]){
                    scores[period-1]=score;
                    phasemax=phase;
                }
            }
            if(scores[period-1]>max){
                max=scores[period-1];
                maxat.first=period;
                maxat.second=phasemax;
            }
            DBG(cerr<<scores[period-1]<<" ";)
        }
        DBG(cerr<<"(max="<<max<<" at {"<<maxat.first<<","<<maxat.second<<"})"<<endl;)
        DBG(cerr<<"     prediction: 1-("<<numr<<"+"<<maxat.second<<")%(2*"<<maxat.first<<")/"<<maxat.first<<"="<<(1-(numr+maxat.second)%(2*maxat.first)/maxat.first)<<endl;)
        predicted+=(1-(numr+maxat.second)%(2*maxat.first)/maxat.first);
    }
    DBG(cerr<<"Predicted outcome: "<<predicted<<" good + "<<(nump-predicted)<<" evil"<<endl;)
    if(predicted>nump/2)cout<<"evil"<<endl; //pick minority
    else cout<<"good"<<endl;
    delete[] scores;
    return 0;
}

```

If you want to turn on debug statements, change the line reading `#if 0` to `#if 1`.

Compile with `g++ -O3 -std=c++0x -o MetaScientist MetaScientist.cpp` (you don't need warnings, so no `-Wall`) and run with `MetaScientist.exe` (possibly including the argument of course). If you ask really nicely I can provide you with a Windows executable.

**EDIT:** Apparently, the previous version ran out of time around 600 rounds into the game. This shouldn't do that. Its time consumption is controlled by the `#define WINDOW (...)` line, more is slower but looks further back.
> 29 votes

# Answer
# Angel

The purest player of all.

**Program**

```
print "good"

```

**Command**

```
python Angel.py

```
> 27 votes

# Answer
# Artemis Fowl

```
package Humans;

public class ArtemisFowl extends Human {
    public final String takeSides(String history) {
        int good = 0, evil = 0;
        for(int i = 0; i < history.length(); i++)   {
            switch(history.charAt(i))   {
                case '0': evil++; break;
                case '1': good++; break;
            }
        }
        if(good % 5 == 0){
           return "good";
        } else if (evil % 5 == 0){
           return "evil";
        } else {
           if(good > evil){
              return "good";
           } else if(evil > good){
              return "evil";
           } else {
              return Math.random() >= 0.5 ? "good" : "evil";
           }
        }
    }
}

```

In Book 7, *The Atlantis Complex*, Artemis Fowl contracted a psychological disease (called Atlantis complex) that forced him to do everything in multiples of 5 (speaking, actions, etc). When he couldn't do it in some multiple of 5, he panicked. I do basically that: see if good or evil (intentional bias) is divisible by 5, if neither is, then I panic & see which was greater & run with that or panic even further & randomly choose.
> 24 votes

# Answer
**Disparnumerophobic**

Odd numbers are terrifying.

```
package Humans;

public class Disparnumerophobic extends Human {
    public final String takeSides(String history) {
        int good = 0, evil = 0;
        for(int i = 0; i < history.length(); i++)   {
            switch(history.charAt(i))   {
                case '0': evil++; break;
                case '1': good++;
            }
        }
        if(good%2 == 1 && evil%2 == 0)  return "evil";
        if(evil%2 == 1 && good%2 == 0)  return "good";
        // well shit....
        return Math.random() >= 0.5 ? "good" : "evil";
    }
}

```
> 19 votes

# Answer
# Linus, Ruby

Seeks to confound analysts by always breaking the pattern.

```
num_rounds = ARGV[0].to_s.count(',')
LINUS_SEQ = 0xcb13b2d3734ecb4dc8cb134b232c4d3b2dcd3b2d3734ec4d2c8cb134b234dcd3b2d3734ec4d2c8cb134b23734ecb4dcd3b2c4d232c4d2c8cb13b2d3734ecb4dcb232c4d2c8cb13b2d3734ecb4dc8cb134b232c4d3b2dcd3b2d3734ec4d2c8cb134b234dcd3b2d3734ec4d2c8cb134b23734ecb4dcd3b2c4d2c8cb134b2
puts %w[good evil][LINUS_SEQ[num_rounds]]

```

Save as `linus.rb` and run with `ruby linus.rb`
> 17 votes

# Answer
# The BackPacker

Determinates a player that has chosen the matching minority the most yet and chooses his last vote.

```
package Humans;

public class BackPacker extends Human {
    // toggles weather the BackPacker thinks majority is better vs. minority is better
    private static final boolean goWithMajority = false;

    @Override
    public final String takeSides(String history)  {
        if (history == null || history.equals(""))
            return "evil";
        String[] roundVotes = history.split(",");
        int players = roundVotes[0].length();
        int[] winningPlayers = new int[players];
        for (String nextRound : roundVotes) {
            boolean didGoodWin = didGoodWin(nextRound, players);
            for (int player = 0; player < nextRound.length(); player++) {
                boolean playerVotedGood = nextRound.charAt(player) == '1';
                winningPlayers[player] += didPlayerWin(didGoodWin, playerVotedGood);
            }
        }
        int bestScore = -1;
        for (int nextPlayer : winningPlayers)
            if (bestScore < nextPlayer)
                bestScore = nextPlayer;
        int bestPlayer = 0;
        for (int ii = 0; ii < players; ii++) {
            if (winningPlayers[ii] == bestScore) {
                bestPlayer = ii;
                break;
            }
        }
        if (roundVotes[roundVotes.length - 1].charAt(bestPlayer) == '1')
            return "good";
        return "evil";
    }

    private int didPlayerWin(boolean didGoodWin, boolean playerVotedGood) {
        if(goWithMajority) {
            return ((didGoodWin && playerVotedGood) || (!didGoodWin && !playerVotedGood)) ? 1 : 0;
        } else {
            return ((!didGoodWin && playerVotedGood) || (didGoodWin && !playerVotedGood)) ? 1 : 0;
        }
    }

    private boolean didGoodWin(String round, int players) {
        int good = 0;
        for (char next : round.toCharArray())
            good += next == '1' ? 1 : 0;
        return (good * 2) > players;
    }
}

```

# The CrowdFollower

Determinates a player that has chosen the matching majority the most yet and chooses his last vote.

```
package Humans;

public class CrowdFollower extends Human {
    // toggles weather the FrontPacker thinks majority is better vs. minority is better
    private static final boolean goWithMajority = true;

    @Override
    public final String takeSides(String history)  {
        if (history == null || history.equals(""))
            return "evil";
        String[] roundVotes = history.split(",");
        int players = roundVotes[0].length();
        int[] winningPlayers = new int[players];
        for (String nextRound : roundVotes) {
            boolean didGoodWin = didGoodWin(nextRound, players);
            for (int player = 0; player < nextRound.length(); player++) {
                boolean playerVotedGood = nextRound.charAt(player) == '1';
                winningPlayers[player] += didPlayerWin(didGoodWin, playerVotedGood);
            }
        }
        int bestScore = -1;
        for (int nextPlayer : winningPlayers)
            if (bestScore < nextPlayer)
                bestScore = nextPlayer;
        int bestPlayer = 0;
        for (int ii = 0; ii < players; ii++) {
            if (winningPlayers[ii] == bestScore) {
                bestPlayer = ii;
                break;
            }
        }
        if (roundVotes[roundVotes.length - 1].charAt(bestPlayer) == '1')
            return "good";
        return "evil";
    }

    private int didPlayerWin(boolean didGoodWin, boolean playerVotedGood) {
        if(goWithMajority) {
            return ((didGoodWin && playerVotedGood) || (!didGoodWin && !playerVotedGood)) ? 1 : 0;
        } else playerVotedGood                return ((!didGoodWin && good) || (didGoodWin && !playerVotedGood)) ? 1 : 0;
        }
    }

    private boolean didGoodWin(String round, int players) {
        int good = 0;
        for (char next : round.toCharArray())
            good += next == '1' ? 1 : 0;
        return (good * 2) > players;
    }
}

```
> 16 votes

# Answer
## C++, The Scientist

This one tries to, with the history of what the majority chose per round in `wave` (`majority()` gives the majority's choice on a round), fit a wave to the data, of wavelength `2*period` and phase `phase`. Thus, given `0,1,1,1,0,1,0,1,1,1,0,0,0,1,0` it selects `period=3, phase=5` (`maxat=={3,5}`): its scores become `9 3 11 5 5 3 5 7 9 7 7 7 7 7 7`. It loops over all possible periods and if, for that period, the score is higher than for the current maximum, it stores `{period,phase}` for which that occurred.

It then extrapolates the found wave to the next round and takes the predicted majority.

```
#include <iostream>
#include <utility>
#include <cstdlib>
#include <cstring>
#if 0
#define DBG(st) {st}
#else
#define DBG(st)
#endif

#define WINDOW (700)

using namespace std;

int majority(const char *r){
    int p=0,a=0,b=0;
    while(true){
        if(r[p]=='1')a++;
        else if(r[p]=='0')b++;
        else break;
        p++;
    }
    return a>b;
}

int main(int argc,char **argv){
    if(argc==1){
        cout<<(rand()%2?"good":"evil")<<endl;
        return 0;
    }
    DBG(cerr<<"WINDOW="<<WINDOW<<endl;)
    int nump,numr;
    nump=strchr(argv[1],',')-argv[1];
    numr=(strlen(argv[1])+1)/(nump+1);
    int fromround=numr-30;
    if(fromround<0)fromround=0;
    int period,r;
    int *wave=new int[WINDOW];
    bool allequal=true;
    DBG(cerr<<"wave: ";)
    for(r=fromround;r<numr;r++){
        wave[r-fromround]=majority(argv[1]+r*(nump+1));
        if(wave[r-fromround]!=wave[0])allequal=false;
        DBG(cerr<<wave[r]<<" ";)
    }
    DBG(cerr<<endl;)
    if(allequal){
        DBG(cerr<<"All equal!"<<endl;)
        if(wave[numr-1]==1)cout<<"evil"<<endl; //choose for minority
        else cout<<"good"<<endl;
        return 0;
    }
    int score,*scores=new int[WINDOW];
    int max=0; //some score will always get above 0, because if some score<0, the inverted wave will be >0.
    int phase,phasemax;
    pair<int,int> maxat(-1,-1); //period, phase
    DBG(cerr<<"scores: ";)
    for(period=1;period<=WINDOW;period++){
        scores[period-1]=0;
        phasemax=-1;
        for(phase=0;phase<2*period;phase++){
            score=0;
            for(r=fromround;r<numr;r++){
                if(wave[r]==1-(r+phase)%(2*period)/period)score++;
                else score--;
            }
            if(score>scores[period-1]){
                scores[period-1]=score;
                phasemax=phase;
            }
        }
        if(scores[period-1]>max){
            max=scores[period-1];
            maxat.first=period;
            maxat.second=phasemax;
        }
        DBG(cerr<<scores[period-1]<<" ";)
    }
    DBG(cerr<<"(max="<<max<<" at {"<<maxat.first<<","<<maxat.second<<"})"<<endl;)
    DBG(cerr<<" max: ("<<numr<<"+"<<maxat.second<<")%(2*"<<maxat.first<<")/"<<maxat.first<<"=="<<((numr+maxat.second)%(2*maxat.first)/maxat.first)<<endl;)
    if(1-(numr+maxat.second)%(2*maxat.first)/maxat.first==1)cout<<"evil"<<endl; //choose for minority
    else cout<<"good"<<endl;
    delete[] wave;
    delete[] scores;
    return 0;
}

```

Compile with `g++ -O3 -std=c++0x -o Scientist Scientist.cpp` (you don't need warnings, so no `-Wall`) and run with `Scientist.exe` (possibly including the argument of course). If you ask really nicely I can provide you with a Windows executable.

Oh, and don't dare messing with the input format. It'll do strange things otherwise.

**EDIT:** Apparently, the previous version ran out of time around 600 rounds into the game. This shouldn't do that. Its time consumption is controlled by the `#define WINDOW (...)` line, more is slower but looks further back.
> 15 votes

# Answer
## Fortune Teller

This is still work in progress. I haven't tested it yet. I just wanted to see if the OP thinks it breaks the rules or not.

The idea is to simulate the next round by executing all other participants a few times to get a probability of the outcome and act accordingly.

```
package Humans;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import sun.net.www.protocol.file.FileURLConnection;

public class FortuneTeller extends Human {

/**
 * Code from http://stackoverflow.com/a/22462785 Private helper method
 *
 * @param directory The directory to start with
 * @param pckgname The package name to search for. Will be needed for
 * getting the Class object.
 * @param classes if a file isn't loaded but still is in the directory
 * @throws ClassNotFoundException
 */
private static void checkDirectory(File directory, String pckgname,
        ArrayList<Class<?>> classes) throws ClassNotFoundException {
    File tmpDirectory;

    if (directory.exists() && directory.isDirectory()) {
        final String[] files = directory.list();

        for (final String file : files) {
            if (file.endsWith(".class")) {
                try {
                    classes.add(Class.forName(pckgname + '.'
                            + file.substring(0, file.length() - 6)));
                } catch (final NoClassDefFoundError e) {
                // do nothing. this class hasn't been found by the
                    // loader, and we don't care.
                }
            } else if ((tmpDirectory = new File(directory, file))
                    .isDirectory()) {
                checkDirectory(tmpDirectory, pckgname + "." + file, classes);
            }
        }
    }
}

/**
 * Private helper method.
 *
 * @param connection the connection to the jar
 * @param pckgname the package name to search for
 * @param classes the current ArrayList of all classes. This method will
 * simply add new classes.
 * @throws ClassNotFoundException if a file isn't loaded but still is in the
 * jar file
 * @throws IOException if it can't correctly read from the jar file.
 */
private static void checkJarFile(JarURLConnection connection,
        String pckgname, ArrayList<Class<?>> classes)
        throws ClassNotFoundException, IOException {
    final JarFile jarFile = connection.getJarFile();
    final Enumeration<JarEntry> entries = jarFile.entries();
    String name;

    for (JarEntry jarEntry = null; entries.hasMoreElements()
            && ((jarEntry = entries.nextElement()) != null);) {
        name = jarEntry.getName();

        if (name.contains(".class")) {
            name = name.substring(0, name.length() - 6).replace('/', '.');

            if (name.contains(pckgname)) {
                classes.add(Class.forName(name));
            }
        }
    }
}

/**
 * Attempts to list all the classes in the specified package as determined
 * by the context class loader
 *
 * @param pckgname the package name to search
 * @return a list of classes that exist within that package
 * @throws ClassNotFoundException if something went wrong
 */
private static ArrayList<Class<?>> getClassesForPackage(String pckgname)
        throws ClassNotFoundException {
    final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();

    try {
        final ClassLoader cld = Thread.currentThread()
                .getContextClassLoader();

        if (cld == null) {
            throw new ClassNotFoundException("Can't get class loader.");
        }

        final Enumeration<URL> resources = cld.getResources(pckgname
                .replace('.', '/'));
        URLConnection connection;

        for (URL url = null; resources.hasMoreElements()
                && ((url = resources.nextElement()) != null);) {
            try {
                connection = url.openConnection();

                if (connection instanceof JarURLConnection) {
                    checkJarFile((JarURLConnection) connection, pckgname,
                            classes);
                } else if (connection instanceof FileURLConnection) {
                    try {
                        checkDirectory(
                                new File(URLDecoder.decode(url.getPath(),
                                                "UTF-8")), pckgname, classes);
                    } catch (final UnsupportedEncodingException ex) {
                        throw new ClassNotFoundException(
                                pckgname
                                + " does not appear to be a valid package (Unsupported encoding)",
                                ex);
                    }
                } else {
                    throw new ClassNotFoundException(pckgname + " ("
                            + url.getPath()
                            + ") does not appear to be a valid package");
                }
            } catch (final IOException ioex) {
                throw new ClassNotFoundException(
                        "IOException was thrown when trying to get all resources for "
                        + pckgname, ioex);
            }
        }
    } catch (final NullPointerException ex) {
        throw new ClassNotFoundException(
                pckgname
                + " does not appear to be a valid package (Null pointer exception)",
                ex);
    } catch (final IOException ioex) {
        throw new ClassNotFoundException(
                "IOException was thrown when trying to get all resources for "
                + pckgname, ioex);
    }

    return classes;
}

private static boolean isRecursiveCall = false;
private static ArrayList<Class<?>> classes;

static {
    if (classes == null) {
        try {
            classes = getClassesForPackage("Humans");
        } catch (ClassNotFoundException ex) {

        }
    }
}

private String doThePetyrBaelish() {
    return Math.random() >= 0.5 ? "good" : "evil";
}

@Override
public String takeSides(String history) {
    if (isRecursiveCall) {
        return doThePetyrBaelish();
    }
    isRecursiveCall = true;

    int currentRoundGoodCount = 0;
    float probabilityOfGood = 0;
    int roundCount = 0;
    int voteCount = 0;

    do {
        for (int i = 0; i < classes.size(); i++) {
            try {
                if (classes.get(i).getName() == "Humans.FortuneTeller") {
                    continue;
                }

                Human human = (Human) classes.get(i).newInstance();
                String response = human.takeSides(history);
                switch (response) {
                    case "good":
                        currentRoundGoodCount++;
                        voteCount++;
                        break;
                    case "evil":
                        voteCount++;
                        break;
                    default:
                        break;
                }
            } catch (Exception e) {
            }
        }

        probabilityOfGood = (probabilityOfGood * roundCount
                + (float) currentRoundGoodCount / voteCount) / (roundCount + 1);

        roundCount++;
        currentRoundGoodCount = 0;
        voteCount = 0;

    } while (roundCount < 11);

    isRecursiveCall = false;
    if (probabilityOfGood > .7) {
        return "evil";
    }
    if (probabilityOfGood < .3) {
        return "good";
    }

    return doThePetyrBaelish();
}

}

```
> 15 votes

# Answer
## Code Runner

So, to make things interesting, I created a script to automatically download the code from every posted answer, compile it if necessary, and then run all of the solutions according to the rules. This way, people can check how they are doing. Just save this script to run\_all.py (requires BeautifulSoup) and then:

```
usage:
To get the latest code: 'python run_all.py get'
To run the submissions: 'python run_all.py run <optional num_runs>'

```

A few things:

1. If you want to add support for more languages, or alternatively remove support for some, see `def submission_type(lang)`.
2. Extending the script should be fairly easy, even for languages that require compilation (see `CPPSubmission`). The language type is grabbed from the meta code tag `< !-- language: lang-java -- >`, so make sure to add it if you want your code to be run (Remove the extra spaces before and after the \<\>). **UPDATE**: There is now some extremely basic inference to try and detect the language if it is not defined.
3. If your code fails to run at all, or fails to finish within the allotted time, it will be added to `blacklist.text` and will be removed from future trials automatically. If you fix your code, just remove your entry from the blacklist and re-run `get`,

Currently supported languages:

```
 submission_types =  {
    'lang-ruby': RubySubmission,
    'lang-python': PythonSubmission,
    'lang-py': PythonSubmission,
    'lang-java': JavaSubmission,
    'lang-Java': JavaSubmission,
    'lang-javascript': NodeSubmission,
    'lang-cpp': CPPSubmission,
    'lang-c': CSubmission,
    'lang-lua': LuaSubmission,
    'lang-r': RSubmission,
    'lang-fortran': FortranSubmission,
    'lang-bash': BashSubmission
}

```

Without further ado:

```
import urllib2
import hashlib
import os
import re
import subprocess
import shutil
import time
import multiprocessing
import tempfile
import sys
from bs4 import BeautifulSoup

__run_java__ = """
public class Run {
    public static void main(String[] args) {
        String input = "";
        Human h = new __REPLACE_ME__();
        if(args.length == 1)
            input = args[0];
        try {
            System.out.println(h.takeSides(input));
        }
        catch(Exception e) {
        }
    }
}
"""

__human_java__ = """
public abstract class Human {
    public abstract String takeSides(String history) throws Exception;
}
"""

class Submission():
    def __init__(self, name, code):
        self.name = name
        self.code = code

    def submissions_dir(self):
        return 'submission'

    def base_name(self):
        return 'run'

    def submission_path(self):
        return os.path.join(self.submissions_dir(), self.name)

    def extension(self):
        return ""

    def save_submission(self):
        self.save_code()

    def full_command(self, input):
        return []

    def full_path(self):
        file_name = "%s.%s" % (self.base_name(), self.extension())
        full_path = os.path.join(self.submission_path(), file_name)
        return full_path

    def save_code(self):
        if not os.path.exists(self.submission_path()):
            os.makedirs(self.submission_path())

        with open(self.full_path(), 'w') as f:
            f.write(self.code)

    def write_err(self, err):
        with open(self.error_log(), 'w') as f:
            f.write(err)

    def error_log(self):
        return os.path.join(self.submission_path(), 'error.txt')

    def run_submission(self, input):
        command = self.full_command()
        if input is not None:
            command.append(input)
        try:
            output,err,exit_code = run(command,timeout=1)
            if len(err) > 0:
                self.write_err(err)
            return output
        except Exception as e:
            self.write_err(str(e))
            return ""

class CPPSubmission(Submission):
    def bin_path(self):
        return os.path.join(self.submission_path(), self.base_name())

    def save_submission(self):
        self.save_code()
        compile_cmd = ['g++', '-O3', '-std=c++0x', '-o', self.bin_path(), self.full_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'cpp'

    def full_command(self):
        return [self.bin_path()]

class CSubmission(Submission):
    def bin_path(self):
        return os.path.join(self.submission_path(), self.base_name())

    def save_submission(self):
        self.save_code()
        compile_cmd = ['gcc', '-o', self.bin_path(), self.full_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'c'

    def full_command(self):
        return [self.bin_path()]

class FortranSubmission(Submission):
    def bin_path(self):
        return os.path.join(self.submission_path(), self.base_name())

    def save_submission(self):
        self.save_code()
        compile_cmd = ['gfortran', '-fno-range-check', '-o', self.bin_path(), self.full_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'f90'

    def full_command(self):
        return [self.bin_path()]

class JavaSubmission(Submission):
    def base_name(self):
        class_name = re.search(r'class (\w+) extends', self.code)
        file_name = class_name.group(1)
        return file_name

    def human_base_name(self):
        return 'Human'

    def run_base_name(self):
        return 'Run'

    def full_name(self, base_name):
        return '%s.%s' % (base_name, self.extension())

    def human_path(self):
        return os.path.join(self.submission_path(), self.full_name(self.human_base_name()))

    def run_path(self):
        return os.path.join(self.submission_path(), self.full_name(self.run_base_name()))

    def replace_in_file(self, file_name, str_orig, str_new):
        old_data = open(file_name).read()
        new_data = old_data.replace(str_orig, str_new)

        with open(file_name, 'w') as f:
            f.write(new_data)

    def write_code_to_file(self, code_str, file_name):
        with open(file_name, 'w') as f:
            f.write(code_str)

    def save_submission(self):
        self.save_code()
        self.write_code_to_file(__human_java__, self.human_path())
        self.write_code_to_file(__run_java__, self.run_path())

        self.replace_in_file(self.run_path(), '__REPLACE_ME__', self.base_name())
        self.replace_in_file(self.full_path(), 'package Humans;', '')

        compile_cmd = ['javac', '-cp', self.submission_path(), self.run_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'java'

    def full_command(self):
        return ['java', '-cp', self.submission_path(), self.run_base_name()]

class PythonSubmission(Submission):
    def full_command(self):
        return ['python', self.full_path()]

    def extension(self):
        return 'py'

class RubySubmission(Submission):
    def full_command(self):
        return ['ruby', self.full_path()]

    def extension(self):
        return 'rb'

class NodeSubmission(Submission):
    def full_command(self):
        return ['node', self.full_path()]

    def extension(self):
        return 'js'

class LuaSubmission(Submission):
    def full_command(self):
        return ['lua', self.full_path()]

    def extension(self):
        return 'lua'

class RSubmission(Submission):
    def full_command(self):
        return ['Rscript', self.full_path()]

    def extension(self):
        return 'R'

class BashSubmission(Submission):
    def full_command(self):
        return [self.full_path()]

    def extension(self):
        return '.sh'

class Scraper():
    def download_page(self, url, use_cache = True, force_cache_update = False):
        file_name = hashlib.sha1(url).hexdigest()

        if not os.path.exists('cache'):
            os.makedirs('cache')

        full_path = os.path.join('cache', file_name)
        file_exists = os.path.isfile(full_path)

        if use_cache and file_exists and not force_cache_update:
            html = open(full_path, 'r').read()
            return html

        opener = urllib2.build_opener()
        opener.addheaders = [('User-agent', 'Mozilla/5.0')]
        response = opener.open(url)
        html = response.read()

        if use_cache:
            f = open(full_path, 'w')
            f.write(html)
            f.close()

        return html

    def parse_post(self, post):
        name = post.find(text=lambda t: len(t.strip()) > 0)
        pre = post.find('pre')
        lang = pre.attrs['class'][0] if pre.has_attr('class') else None
        code = pre.find('code').text
        user = post.find(class_='user-details').find(text=True)
        return {'name':name,'lang':lang,'code':code,'user':user}

    def parse_posts(self, html):
        soup = BeautifulSoup(html)
        # Skip the first post
        posts = soup.find_all(class_ = 'answercell')
        return [self.parse_post(post) for post in posts]

    def get_submissions(self,  page = 1, force_cache_update = False):
        url = "http://codegolf.stackexchange.com/questions/33137/good-versus-evil?page=%i&tab=votes#tab-top" % page
        html = self.download_page(url, use_cache = True, force_cache_update = force_cache_update)
        submissions = self.parse_posts(html)
        return submissions

class Timeout(Exception):
    pass

def run(command, timeout=10):
    proc = subprocess.Popen(command, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    poll_seconds = .250
    deadline = time.time()+timeout
    while time.time() < deadline and proc.poll() == None:
        time.sleep(poll_seconds)

    if proc.poll() == None:
        if float(sys.version[:3]) >= 2.6:
            proc.terminate()
        raise Timeout()

    stdout, stderr = proc.communicate()
    return stdout, stderr, proc.returncode

def guess_lang(code):
    if re.search(r'class .* extends Human', code):
        return 'lang-java'
    if re.search(r'import sys', code):
        return 'lang-python'
    if re.search(r'puts', code) and (re.search(r'ARGV', code) or re.search(r'\%w', code)):
        return 'lang-ruby'
    if re.search(r'console\.log', code):
        return 'lang-javascript'
    if re.search(r'program', code) and re.search(r'subroutine', code):
        return 'lang-fortran'
    if re.search(r'@echo off', code):
        return 'lang-bash'
    return None

def submission_type(lang, code):
    submission_types =  {
        'lang-ruby': RubySubmission,
        'lang-python': PythonSubmission,
        'lang-py': PythonSubmission,
        'lang-java': JavaSubmission,
        'lang-Java': JavaSubmission,
        'lang-javascript': NodeSubmission,
        'lang-cpp': CPPSubmission,
        'lang-c': CSubmission,
        'lang-lua': LuaSubmission,
        'lang-r': RSubmission,
        'lang-fortran': FortranSubmission,
        'lang-bash': BashSubmission
    }

    klass = submission_types.get(lang)

    if klass is None:
        lang = guess_lang(code)
        klass = submission_types.get(lang)

    return klass

def instantiate(submission):
    lang = submission['lang']
    code = submission['code']
    name = submission['name']

    klass = submission_type(lang, code)
    if klass is not None:
        instance = klass(name, code)
        return instance
    print "Entry %s invalid - lang not supported: %s" % (name, lang)
    return None

def get_all_instances(force_update):
    scraper = Scraper()

    print 'Scraping Submissions..'

    pages = [1,2,3]
    submissions_by_page = [scraper.get_submissions(page=i, force_cache_update=force_update) for i in pages]
    submissions = [item for sublist in submissions_by_page for item in sublist]

    # Get instances
    raw_instances = [instantiate(s) for s in submissions]
    instances = [i for i in raw_instances if i]

    print "Using %i/%i Submissions" % (len(instances), len(submissions))

    return instances

def save_submissions(instances):
    print 'Saving Submissions..'

    for instance in instances:
        instance.save_submission()

def init_game(save=True, force_update=False):
    instances = get_all_instances(force_update)
    if save:
        save_submissions(instances)
    return instances

def one_run(instances, input):
    valid = {
        'good': 1,
        'evil': 0
    }

    disqualified = []
    results = []

    for instance in instances:
        out = instance.run_submission(input)
        res = out.strip().lower()
        if res not in valid:
            disqualified.append(instance)
        else:
            results.append(valid[res])

    return (results, disqualified)

def get_winner(scores, instances):
    max_value = max(scores)
    max_index = scores.index(max_value)
    instance = instances[max_index]
    return (instance.name, max_value)

def update_scores(results, scores, minority_counts, minority_num):
    for i in range(len(results)):
        if results[i] == minority_num:
            minority_counts[i] += 1
            scores[i] += (minority_counts[i] - 1)
        else:
            minority_counts[i] = 0
            scores[i] += 3

def try_run_game(instances, num_runs = 1000, blacklist = None):
    current_input = None
    minority_str = None
    num_instances = len(instances)
    scores = [0] * num_instances
    minority_counts = [0] * num_instances

    print "Running with %i instances..." % num_instances

    for i in range(num_runs):
        print "Round: %i - Last minority was %s" % (i, minority_str)
        results, disqualified = one_run(instances, current_input)

        if len(disqualified) > 0:
            for instance in disqualified:
                print "Removing %s!" % instance.name
                instances.remove(instance)

                if blacklist is not None:
                    with open(blacklist, 'a') as f:
                        f.write("%s\n" % instance.name)

            return False

        latest_result = "".join(map(str,results))
        current_input = "%s,%s" % (current_input, latest_result)

        minority_num = 1 if results.count(1) < results.count(0) else 0
        minority_str = 'good' if minority_num == 1 else 'evil'

        update_scores(results, scores, minority_counts, minority_num)
        name, score = get_winner(scores, instances)
        print "%s is currently winning with a score of %i" % (name, score)

    print "The winner is %s with a score of %i!!!" % (name, score)
    return True

def find_instance_by_name(instances, name):
    for instance in instances:
        if instance.name == name:
            return instance
    return None

def maybe_add_or_remove_baelish(instances, baelish):
    num_instances = len(instances)

    if num_instances % 2 == 0:
        print 'There are %i instances.' % num_instances
        try:
            instances.remove(baelish)
            print 'Baelish Removed!'
        except:
            instances.append(baelish)
            print 'Baelish Added!'

def remove_blacklisted(blacklist, instances):
    blacklisted = []

    try:
        blacklisted = open(blacklist).readlines()
    except:
        return

    print 'Removing blacklisted entries...'

    for name in blacklisted:
        name = name.strip()
        instance = find_instance_by_name(instances, name)
        if instance is not None:
            print 'Removing %s' % name
            instances.remove(instance)

def run_game(instances, num_runs):
    blacklist = 'blacklist.txt'
    remove_blacklisted(blacklist, instances)

    baelish = find_instance_by_name(instances, 'Petyr Baelish')
    maybe_add_or_remove_baelish(instances, baelish)

    while not try_run_game(instances, num_runs = num_runs, blacklist = blacklist):
        print "Restarting!"
        maybe_add_or_remove_baelish(instances, baelish)

    print "Done!"

if __name__ == '__main__':
    param = sys.argv[1] if len(sys.argv) >= 2 else None

    if param == 'get':
        instances = init_game(save=True, force_update=True)
    elif param == 'run':
        instances = init_game(save=False, force_update=False)
        num_runs = 50
        if len(sys.argv) == 3:
            num_runs = int(sys.argv[2])
        run_game(instances, num_runs)
    else:
        self_name = os.path.basename(__file__)
        print "usage:"
        print "To get the latest code: 'python %s get'" % self_name
        print "To run the submissions: 'python %s run <optional num_runs>'" % self_name

```
> 14 votes

# Answer
## The Beautiful Mind, Ruby

Makes its decision based on patterns of questionable significance in the bit representation of the last round

```
require 'prime'

if ARGV.length == 0
    puts ["good", "evil"].sample
else
    last_round = ARGV[0].split(',').last
    puts Prime.prime?(last_round.to_i(2)) ? "good" : "evil"
end

```

Run like

```
ruby beautiful-mind.rb

```
> 13 votes

# Answer
# Piustitious, Lua

A superstitious program that believes in Signs and Wonders.

```
history = arg[1]

if history == nil then
    print("good")
else
    local EvilSigns, GoodSigns = 0,0
    local SoulSpace = ""

    for i in string.gmatch(history, "%d+") do
         SoulSpace = SoulSpace .. i
    end

    if string.match(SoulSpace, "1010011010")  then -- THE NUBMER OF THE BEAST!
        local r = math.random(1000)
        if r <= 666 then print("evil") else print("good") end
    else
        for i in string.gmatch(SoulSpace, "10100") do -- "I'M COMING" - DEVIL
            EvilSigns = EvilSigns + 1
        end
        for i in string.gmatch(SoulSpace, "11010") do -- "ALL IS WELL" - GOD
            GoodSigns = GoodSigns + 1
        end

        if EvilSigns > GoodSigns then
            print("evil")
        elseif GoodSigns > EvilSigns then
            print("good")
        elseif GoodSigns == EvilSigns then
            local r = math.random(1000)
            if r <= 666 then print("good") else print("evil") end
        end
    end
end

```

run it with:

```
lua Piustitious.lua

```

followed by the input.
> 13 votes

# Answer
# The Winchesters

Sam and Dean are good (most of the time).

```
package Humans;

public class TheWinchesters extends Human {

    @Override
    public String takeSides(String history) throws Exception {
        return Math.random() < 0.1 ? "evil" : "good";
    }

}

```
> 11 votes

# Answer
## Statistician

```
public class Statistician extends Human{
    public final String takeSides(String history) {
        int side = 0;
        String[] hist = history.split(",");
        for(int i=0;i<hist.length;i++){
            for(char c:hist[i].toCharArray()){
                side += c == '1' ? (i + 1) : -(i + 1);
            }
        }
        if(side == 0) side += Math.round(Math.random());
        return side > 0 ? "good" : "evil";
    }
}

```
> 10 votes

# Answer
## R, a somewhat Bayesian bot

Use the frequency table for each user as the prior probability of other users output.

```
args <- commandArgs(TRUE)
if(length(args)!=0){
    history <- do.call(rbind,strsplit(args,","))
    history <- do.call(rbind,strsplit(history,""))
    tabulated <- apply(history,2,function(x)table(factor(x,0:1)))
    result <- names(which.max(table(apply(tabulated, 2, function(x)sample(0:1,1, prob=x)))))
    if(result=="1"){cat("good")}else{cat("evil")}
}else{
    cat("good")
    }

```

Invoked using `Rscript BayesianBot.R` followed by the input.

**Edit**: Just to clarify what this is doing, here is a step by step with the example input:

```
> args
[1] "11011,00101,11101,11111,00001,11001,11001"
> history #Each player is a column, each round a row
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    0    1    1
[2,]    0    0    1    0    1
[3,]    1    1    1    0    1
[4,]    1    1    1    1    1
[5,]    0    0    0    0    1
[6,]    1    1    0    0    1
[7,]    1    1    0    0    1

> tabulated #Tally of each player previous decisions.
  [,1] [,2] [,3] [,4] [,5]
0    2    2    4    5    0
1    5    5    3    2    7

```

Then the line starting by `result<-`, for each player, picks randomly either 0 or 1 using this last table as weights (i. e. for player 1 the probability of picking 0 is 2/7th, of picking 1 5/7th, etc.). It picks one outcome for each player/column and finally returns the number that ended being the most common.
> 10 votes

# Answer
## Swiss

Always sustains neutrality. Doomed to never win.

```
package Humans;

/**
 * Never choosing a side, sustaining neutrality
 * @author Fabian
 */
public class Swiss extends Human {
    public String takeSides(String history) {
        return "neutral"; // wtf, how boring is that?
    }
}

```
> 10 votes

# Answer
# HAL 9000

```
#!/usr/bin/env perl
print eval("evil")

```

**Edit :** maybe this is more suitable for HAL 9000, but be careful! It is very evil. I recommend `cd` to empty directory before running it.

```
#!/usr/bin/env perl
print eval {
    ($_) = grep { -f and !/$0$/ } glob('./*');
    unlink;
    evil
}

```

> This removes one file from `cwd` for each invocation!

Not so obvious invocation:

In M$

```
D:\>copy con hal_9000.pl
#!/usr/bin/env perl
print eval("evil")
^Z
        1 file(s) copied.

D:>hal_9000.pl
evil

```

In \*nix

```
[core1024@testing_pc ~]$ tee hal_9000.pl
#!/usr/bin/env perl
print eval("evil")
# Press C-D here
[core1024@testing_pc ~]$ chmod +x $_
[core1024@testing_pc ~]$ ./$_
evil[core1024@testing_pc ~]$

```
> 9 votes

# Answer
# Will of the Majority

```
import sys
import random

if len(sys.argv)==1:
    print(random.choice(['good','evil']))
else:
    rounds=sys.argv[1].split(',')
    last_round=rounds[-1]
    zeroes=last_round.count('0')
    ones=last_round.count('1')
    if ones>zeroes:
        print('good')
    elif zeroes>ones:
        print('evil')
    elif ones==zeroes:
        print(random.choice(['good','evil']))

```

Save it as `WotM.py`, run as `python3 WotM.py` followed by the input.

A simple program, just to see how it will do. Goes with whatever the majority said last time, or else random.
> 9 votes

# Answer
## Alan Shearer

Repeats whatever the person he's sitting next to has just said. If the person turns out to be wrong, he moves on to the next person and repeats what they say instead.

```
package Humans;

/**
 * Alan Shearer copies someone whilst they're right; if they get predict
 * wrongly then he moves to the next person and copies whatever they say.
 *
 * @author Algy
 * @url http://codegolf.stackexchange.com/questions/33137/good-versus-evil
 */
public class AlanShearer extends Human {

    private char calculateWinner(String round) {
        int good = 0, evil = 0;

        for (int i = 0, L = round.length(); i < L; i++) {
            if (round.charAt(i) == '1') {
                good++;
            } else {
                evil++;
            }
        }

        return (good >= evil) ? '1' : '0';
    }

    /**
     * Take the side of good or evil.
     * @param history The past votes of every player
     * @return A String "good" or "evil
     */
    public String takeSides(String history) {
        String[] parts = history.split(",");
        String lastRound = parts[parts.length() - 1];

        if (parts.length() == 0 || lastRound.length() == 0) {
            return "good";
        } else {
            if (parts.length() == 1) {
                return lastRound.charAt(0) == '1' ? "good" : "evil";
            } else {
                int personToCopy = 0;

                for (int i = 0, L = parts.length(); i < L; i++) {
                    if (parts[i].charAt(personToCopy) != calculateWinner(parts[i])) {
                        personToCopy++;

                        if (personToCopy >= L) {
                            personToCopy = 0;
                        }
                    }
                }
            }

            return lastRound.charAt(personToCopy) == '1' ? "good" : "evil";
        }
    }
}

```
> 9 votes

# Answer
# Pattern Finder, Python

Looks for a recurring pattern, and if it can't find one, just goes with the majority.

```
import sys

if len(sys.argv) == 1:
    print('good')
    quit()

wins = ''.join(
    map(lambda s: str(int(s.count('1') > s.count('0'))),
        sys.argv[1].split(',')
    )
)

# look for a repeating pattern
accuracy = []

for n in range(1, len(wins)//2+1):
    predicted = wins[:n]*(len(wins)//n)
    actual    = wins[:len(predicted)]
    n_right = 0
    for p, a in zip(predicted, actual):
        n_right += (p == a)
    accuracy.append(n_right/len(predicted))

# if there's a good repeating pattern, use it
if accuracy:
    best = max(accuracy)
    if best > 0.8:
        n = accuracy.index(best)+1
        prediction = wins[:n][(len(wins))%n]
        # good chance of success by going with minority
        if prediction == '1':
            print('evil')
        else:
            print('good')
        quit()

# if there's no good pattern, just go with the majority
if wins.count('1') > wins.count('0'):
    print('good')
else:
    print('evil')

```

run with

```
python3 pattern_finder.py

```
> 8 votes

# Answer
# Later is Evil, JavaScript (*node.js*)

Measures the amount of time between executions. If the the time difference is greater than last time, it must be evil. Otherwise, good.

```
var fs = require('fs'),
currentTime = (new Date).getTime();

try {
    var data = fs.readFileSync('./laterisevil.txt', 'utf8');
} catch (e) { data = '0 0'; } // no file? no problem, let's start out evil at epoch

var parsed = data.match(/(\d+) (\d+)/),
lastTime = +parsed[1],
lastDifference = +parsed[2],
currentDifference = currentTime - lastTime;

fs.writeFileSync('./laterisevil.txt', currentTime + ' ' + currentDifference, 'utf8');
console.log(currentDifference > lastDifference? 'evil' : 'good');

```

Run with: `node laterisevil.js`
> 8 votes

# Answer
# The Turncoat

The Turncoat believes that because of the other combatants so far, the majority will alternate after each round between good and evil more often than it stays on the same side. Thus he begins the first round by arbitrarily siding with good, then alternates every round in an attempt to stay on the winning or losing team more often than not.

```
package Humans;

public class Turncoat extends Human {
    public final String takeSides(String history) {
        String[] hist = history.split(",");

        return (hist.length % 2) == 0 ? "good" : "evil";
    }
}

```

After writing this, I realized that due to the entries based on statistical analysis, momentum would cause the majority to switch sides less as more rounds have been completed. Hence, the the Lazy Turncoat.

# The Lazy Turncoat

The Lazy Turncoat starts off like the Turncoat, but as rounds pass, he gets lazier and lazier to switch to the other side.

```
package Humans;

public class LazyTurncoat extends Human {
    public final String takeSides(String history) {
        int round = history.length() == 0 ? 0 : history.split(",").length;
        int momentum = 2 + ((round / 100) * 6);
        int choice = round % momentum;
        int between = momentum / 2;

        return choice < between ? "good" : "evil";
    }
}

```
> 8 votes

# Answer
# Biographer, Ruby

```
rounds = ARGV[0].split(',') rescue []

if rounds.length < 10
  choice = 1
else
  outcome_history = ['x',*rounds.map{|r|['0','1'].max_by{|s|r.count s}.tr('01','ab')}]
  player_histories = rounds.map{|r|r.chars.to_a}.transpose.map{ |hist| outcome_history.zip(hist).join }
  predictions = player_histories.map do |history|
    (10).downto(0) do |i|
      i*=2
      lookbehind = history[-i,i]
      @identical_previous_behavior = history.scan(/(?<=#{lookbehind})[10]/)
      break if @identical_previous_behavior.any?
    end
    if @identical_previous_behavior.any?
      (@identical_previous_behavior.count('1')+1).fdiv(@identical_previous_behavior.size+2)
    else
      0.5
    end
  end
  simulations = (1..1000).map do
    votes = predictions.map{ |chance| rand < chance ? 1 : 0 }
    [0,1].max_by { |i| votes.count(i) }
  end
  choice = case simulations.count(1)/10
    when 0..15
      1
    when 16..50
      0
    when 51..84
      1
    when 85..100
      0
  end
end

puts %w[evil good][choice]

```

My attempt at an almost intelligent entry (an actually intelligent one would require testing against the field). Written in Ruby, so there's a chance this'll be too slow, but on my machine anyway this takes .11 seconds to calculate the last round when there are 40 random players, so I hope it'll work well enough.

save as `biographer.rb`, run as `ruby biographer.rb`

The idea is that for each player, it estimates their chances of picking "good" by looking at both their own choices for the last ten rounds, and the overall outcomes, and finding instances in the past where the identical circumstances (their votes + overall outcomes) occurred. It picks the longest lookbehind length, up to 10 rounds, such that there's any precedent, and uses that to create a frequency (adjusted according to Laplace's Law of Succession, so that we're never 100% confident about anyone).

It then runs some simulations and sees how often Good wins. If the simulations turned out mostly the same way, then it's probably going to do well predicting in general so it picks the predicted minority. If it's not confident, it picks the predicted majority.
> 8 votes

# Answer
## Judas

Judas is a really good person. It's a pity he'll betray the good guys for a few pennies.

```
package Humans;

public class Judas extends Human {

    private static final String MONEY = ".*?0100110101101111011011100110010101111001.*?";

    public String takeSides(String history) {
       return history != null && history.replace(",","").matches(MONEY) ? "evil" : "good";
    }
}

```
> 8 votes

# Answer
# The Fallacious Gambler (Python)

If one side has won majority a number of times in a row, the gambler realizes that the other side is more likely to be the majority next round (right?) and this influence his vote. He aims for the minority, because if he makes it into the minority once he's likely to make it there a number of times (right?) and get a lot of points.

```
import sys
import random

def whoWon(round):
    return "good" if round.count("1") > round.count("0") else "evil"

if len(sys.argv) == 1:
    print random.choice(["good", "evil"])
else:
    history = sys.argv[1]
    rounds = history.split(",")
    lastWin = whoWon(rounds[-1])
    streakLength = 1
    while streakLength < len(rounds) and whoWon(rounds[-streakLength]) == lastWin:
        streakLength += 1
    lastLoss = ["good", "evil"]
    lastLoss.remove(lastWin)
    lastLoss = lastLoss[0]
    print lastWin if random.randint(0, streakLength) > 1 else lastLoss

```

## Usage

For the first round:

```
python gambler.py

```

and afterward:

```
python gambler.py 101,100,001 etc.

```
> 7 votes

# Answer
# The Ridge Professor

I hope using libraries is allowed, don't feel like doing this without one =)

The basic idea is to train a ridge regression classifier for each participant on the last rounds, using the 30 results before each round as features. Originally included the last round of results for all players to predict the outcome for each player as well, but that was cutting it rather close for time when the number of participants gets larger (say, 50 or so).

```
#include <iostream>
#include <string>
#include <algorithm>
#include "Eigen/Dense"

using Eigen::MatrixXf;
using Eigen::VectorXf;
using Eigen::IOFormat;
using std::max;

void regress(MatrixXf &feats, VectorXf &classes, VectorXf &out, float alpha = 1) {
    MatrixXf featstrans = feats.transpose();
    MatrixXf AtA = featstrans * feats;

    out = (AtA + (MatrixXf::Identity(feats.cols(), feats.cols()) * alpha)).inverse() * featstrans * classes;
}

float classify(VectorXf &weights, VectorXf &feats) {
    return weights.transpose() * feats;
}

size_t predict(MatrixXf &train_data, VectorXf &labels, VectorXf &testitem) {
    VectorXf weights;
    regress(train_data, labels, weights);
    return (classify(weights, testitem) > 0 ? 1 : 0);
}

static const int N = 30;
static const int M = 10;
// use up to N previous rounds worth of data to predict next round
// train on all previous rounds available
size_t predict(MatrixXf &data, size_t prev_iters, size_t n_participants) {
    MatrixXf newdata(data.rows(), data.cols() + max(N, M));
    newdata << MatrixXf::Zero(data.rows(), max(N, M)), data;

    size_t n_samples = std::min(500ul, prev_iters);
    if (n_samples > (8 * max(N, M))) {
        n_samples -= max(N,M);
    }
    size_t oldest_sample = prev_iters - n_samples;
    MatrixXf train_data(n_samples, N + M + 1);
    VectorXf testitem(N + M + 1);
    VectorXf labels(n_samples);
    VectorXf averages = newdata.colwise().mean();
    size_t n_expected_good = 0;
    for (size_t i = 0; i < n_participants; ++i) {
        for (size_t iter = oldest_sample; iter < prev_iters; ++iter) {
            train_data.row(iter - oldest_sample) << newdata.row(i).segment<N>(iter + max(N, M) - N)
                                  , averages.segment<M>(iter + max(N, M) - M).transpose()
                                  , 1;
        }
        testitem.transpose() << newdata.row(i).segment<N>(prev_iters + max(N, M) - N)
                  , averages.segment<M>(prev_iters + max(N, M) - M).transpose()
                  , 1;
        labels = data.row(i).segment(oldest_sample, n_samples);
        n_expected_good += predict(train_data, labels, testitem);
    }
    return n_expected_good;
}

void fill(MatrixXf &data, std::string &params) {
    size_t pos = 0, end = params.size();
    size_t i = 0, j = 0;
    while (pos < end) {
        switch (params[pos]) {
            case ',':
                i = 0;
                ++j;
                break;
            case '1':
                data(i,j) = 1;
                ++i;
                break;
            case '0':
                data(i,j) = -1;
                ++i;
                break;
            default:
                std::cerr << "Error in input string, unexpected " << params[pos] << " found." << std::endl;
                std::exit(1);
                break;
        }
        ++pos;
    }
}

int main(int argc, char **argv) {
    using namespace std;

    if (argc == 1) {
        cout << "evil" << endl;
        std::exit(0);
    }

    string params(argv[1]);
    size_t n_prev_iters = count(params.begin(), params.end(), ',') + 1;
    size_t n_participants = find(params.begin(), params.end(), ',') - params.begin();

    MatrixXf data(n_participants, n_prev_iters);
    fill(data, params);

    size_t n_expected_good = predict(data, n_prev_iters, n_participants);

    if (n_expected_good > n_participants/2) {
        cout << "evil" << endl;
    } else {
        cout << "good" << endl;
    }
}

```

## To Compile

Save the source code in a file called `ridge_professor.cc`, download the Eigen library and unzip the Eigen folder found inside into the same folder as the source file. Compile with `g++ -I. -O3 -ffast-math -o ridge_professor ridge_professor.cc`.

## To Run

call ridge\_professor.exe and supply argument as needed.

# Question

Since I can't comment anywhere yet, I'll ask here: doesn't the argument size limit on windows make it impossible to call the resulting binaries with the entire history at a few hundred turns? I thought you can't have more than ~9000 characters in the argument...
> 7 votes

# Answer
# Cellular Automaton

This uses conventional rules for Conway's Game of Life to pick a side. First, a 2D grid is created from the previous votes. Then, the "world" is stepped forward one stage, and the total number of living cells remaining is calculated. If this number is greater than half the total number of cells, "good" is chosen. Otherwise, "evil" is chosen.

Please forgive any mistakes, this was smashed out during my lunch hour. ;)

```
package Humans;

public class CellularAutomaton extends Human {

    private static final String GOOD_TEXT = "good";

    private static final String EVIL_TEXT = "evil";

    private int numRows;

    private int numColumns;

    private int[][] world;

    @Override
    public String takeSides(String history) {
        String side = GOOD_TEXT;

        if (history.isEmpty()) {
            side = Math.random() <= 0.5 ? GOOD_TEXT : EVIL_TEXT;
        }

        else {
            String[] prevVotes = history.split(",");

            numRows = prevVotes.length;

            numColumns = prevVotes[0].length();

            world = new int[numRows][numColumns];

            for (int i = 0; i < numColumns; i++) {
                for (int j = 0; j < numRows; j++) {
                    world[j][i] =
                        Integer.parseInt(Character.toString(prevVotes[j].charAt(i)));
                }
            }

            int totalAlive = 0;
            int total = numRows * numColumns;
            for (int i = 0; i < numColumns; i++) {
                for (int j = 0; j < numRows; j++) {
                    totalAlive += getAlive(world, i, j);
                }
            }
            if (totalAlive < total / 2) {
                side = EVIL_TEXT;
            }
        }

        return side;
    }

    private int getAlive(int[][] world, int i, int j) {
        int livingNeighbors = 0;

        if (i - 1 >= 0) {
            if (j - 1 >= 0) {
                livingNeighbors += world[j - 1][i - 1];
            }
            livingNeighbors += world[j][i - 1];
            if (j + 1 < numRows) {
                livingNeighbors += world[j + 1][i - 1];
            }
        }
        if (j - 1 >= 0) {
            livingNeighbors += world[j - 1][i];
        }
        if (j + 1 < numRows) {
            livingNeighbors += world[j + 1][i];
        }
        if (i + 1 < numColumns) {
            if (j - 1 >= 0) {
                livingNeighbors += world[j - 1][i + 1];
            }
            livingNeighbors += world[j][i + 1];
            if (j + 1 < numRows) {
                livingNeighbors += world[j + 1][i + 1];
            }
        }

        return livingNeighbors > 1 && livingNeighbors < 4 ? 1 : 0;
    }
}

```
> 7 votes

# Answer
## Crowley

Because the Winchesters are much less interesting without this fellow. He obviously sides with evil...unless it is needed to take care of a bigger evil.

```
package Humans;

public class Crowley extends Human {
public String takeSides(String history) {
    int gd = 0, j=history.length(), comma=0, c=0, z=0;
    while(comma < 2 && j>0)   {
        j--;
        z++;
        if (history.charAt(j) == ',') {
            comma++;
            if(c> z/2) {gd++;}
            z=0;
            c=0;
        } else if (history.charAt(j)=='1') {
            c++;
        } else {
        }
    }
    if(gd == 0){
        return "good";
    } else {
        return "evil";
    }
}}

```

I look at the last two turns (0 commas so far and 1 comma so far) and if both of them let evil win, I vote good. Otherwise I vote evil.
> 6 votes

# Answer
## C++, Bookkeeper

This one tries to do some smart pattern-matching. First of all, it does random moves while logging its moves in the file Bookkeeper.txt. When it has successfully determined which of the players he is, he saves that in the file instead, and afterwards does smart things.

These smart things are trying to pattern match the last WINDOW moves of each player, *excluding* itself. Near the top, WINDOW is defined to be 20. The pattern can be at most `WINDOW/2` *and* at most `(number of rounds)/2` long and must fill the entire WINDOW without faults. If it finds a pattern for a player, it predicts for that player what its next move will probably be; if it can't find a pattern, it assumes the player will repeat its last move.

Near the bottom of the file, it looks at the number of "goods" in the prediction and checks whether it can make sure it chooses a minority. If it can, it does; if it cannot (`numgood==nump/2`), it goes random.

```
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <sys/time.h>
#if 0
#define DBG(st) {st}
#else
#define DBG(st)
#endif

#define WINDOW (20)

#define GETARGV1(rnd,plr) (argv[1][(rnd)*(nump+1)+(plr)])
#define MIN(a,b) ((a)<(b)?(a):(b))
#define FILENAME "Bookkeeper.txt"
#define MARK_IDENT "identification"
#define MARK_PLAYING "playing"

using namespace std;

int main(int argc,char **argv){
    struct timeval tv;
    gettimeofday(&tv,NULL);
    srand(1e6*tv.tv_sec+tv.tv_usec);
    int choice,nump,numr,i,rnd;
    if(argc==1){
        ofstream out(FILENAME);
        choice=rand()%2;
        cout<<(choice?"good":"evil")<<endl;
        out<<MARK_IDENT "\n"<<choice<<endl;
        out.close();
        return 0;
    }
    for(nump=0;argv[1][nump]=='1'||argv[1][nump]=='0';nump++);
    numr=(strlen(argv[1])+1)/(nump+1);
    ifstream in(FILENAME);
    string line;
    getline(in,line);
    if(line==MARK_IDENT){
        bool *ruledout=new bool[nump]();
        rnd=0;
        while(true){
            getline(in,line);
            if(!in.good()||line.size()==0)break;
            choice=line[0]-'0';
            for(i=0;i<nump;i++){
                if(GETARGV1(rnd,i)-'0'!=choice)ruledout[i]=true;
            }
            DBG(
                cerr<<"After round "<<rnd<<" (choice "<<choice<<"): ruledout=";
                for(i=0;i<nump;i++)cerr<<ruledout[i];
                cerr<<endl;
            )
            rnd++;
        }
        in.close();
        choice=-1;
        for(i=0;i<nump;i++){
            if(!ruledout[i]){
                if(choice==-1)choice=i;
                else break;
            }
        }
        delete[] ruledout;
        if(i==nump){
            ofstream out(FILENAME);
            out<<MARK_PLAYING<<'\n'<<choice<<endl;
            out.close();
            choice=rand()%2;
            cout<<(choice?"good":"evil")<<endl;
        } else {
            ofstream out(FILENAME,ofstream::out|ofstream::app);
            choice=rand()%2;
            cout<<(choice?"good":"evil")<<endl;
            out<<choice<<endl;
            out.close();
        }
    } else if(line==MARK_PLAYING){
        int iam,p,patternlen,patternloop,numgood;
        bool fail;
        getline(in,line);
        in.close();
        iam=0;
        for(i=0;i<(int)line.size();i++)iam=10*iam+line[i]-'0';
        patternlen=MIN(WINDOW/2,numr/2);
        numgood=0;
        bool *pattern=new bool[patternlen];
        bool *predicted=new bool[nump];
        for(p=0;p<nump;p++){
            if(iam==p)continue; //we don't do ourselves
            for(i=0;i<patternlen;i++){
                pattern[i]=GETARGV1(numr-1-i,p)-'0';
            }
            patternloop=1;
            fail=true;
            while(patternloop<=patternlen){
                fail=false;
                for(i=patternloop;i<WINDOW&&i<numr;i++){
                    if(GETARGV1(numr-1-i,p)-'0'!=pattern[i%patternloop]){
                        fail=true;
                        break;
                    }
                }
                if(!fail)break;
                patternloop++;
            }
            if(!fail){
                predicted[p]=pattern[patternloop-1];
            } else {
                predicted[p]=pattern[0]; //could not find a pattern, so just take the last one
            }
            numgood+=predicted[p];
            DBG(cerr<<"p"<<p<<": fail="<<fail<<" patternlen="<<patternlen<<" patternloop="<<patternloop<<" predicted["<<p<<"]="<<predicted[p]<<endl;)
        }
        delete[] predicted;
        delete[] pattern;
        //now we go for the minority.
        //if more than half of the other players will choose good, we can choose evil to be part of the minority:
        if(numgood>nump/2)cout<<"evil"<<endl;
        //if exactly half of the other players choose good, we get the majority by defenition, which sucks:
        if(numgood==nump/2)cout<<(rand()%2?"good":"evil")<<endl;
        //if less than half of the other players will choose evil, we can choose good to be part of the minority:
        if(numgood<nump/2)cout<<"good"<<endl;
    }
    return 0;
}

```

Compile with `g++ -O3 -std=c++0x -o Bookkeeper Bookkeeper.cpp` (you don't need warnings, so no `-Wall`) and run with `Bookkeeper.exe` (possibly including the argument of course). If you ask really nicely I can provide you with a Windows executable.
> 6 votes

# Answer
# The Party Animal

Long time since I did Java but thought I'd contribute! This one is a good boy/girl, but when the weekend hits, it's party time!

```
import java.util.Calendar;

public class PartyAnimal extends Human {

    @Override
    public final String takeSides(String history) throws Exception {
        Calendar cal = Calendar.getInstance();

        int today = cal.get(Calendar.DAY_OF_WEEK);
        if(today == 7 || today == 1)
            return "evil";

        return "good";
    }

}

```
> 6 votes

# Answer
# Demon

The most evil player of all.

```
package Humans;

/**
 * The most evil player of all.
 * @author Rusher
 */
public class Demon extends Human {

    /**
     * Take the side of Evil.
     * @param history The past votes of every player
     * @return The String "evil"
     */
    public final String takeSides(String history) {
        return "evil";
    }

}

```
> 5 votes

# Answer
## Nonconformist, Ruby

The opposite of The Tag-Along. She just wants to go against convention and picks the side that has been chosen least often so far

```
if ARGV.length == 0
    puts ["good", "evil"].sample
else
    all_samples = ARGV[0].gsub(',','')
    n_good_samples = all_samples.count('1')
    puts n_good_samples > all_samples.length/2 ? "evil" : "good"
end

```

Run like

```
ruby rebel.rb

```
> 5 votes

# Answer
# Rebel ~ Java

Makes random decisions at the beginning, then tries to side with the minority.

```
package Humans;
public class Rebel extends Human {
    public final String takeSides(String history) {
        int score = 0;
        int value = 1;
        for(int i = 0; i < history.length(); i++) {
            if (history.charAt(i) == ',') {
                value *= 2;
           } else {
                if (history.charAt(i) == '1') {
                    score += value;
                } else {
                    score -= value;
                }
            }
        }
        return score+(Math.random()-0.5)*10 < 0 ? "good" : "evil";
    }
}

```

I'm bad at coming up with names xD

# Chef ~ Java

Opposes the inconsistent.

```
package Humans;

public class Chef extends Human {
    public String takeSides(String history) {
    if(history.length() == 0) {
        return "good";
    }
    String[] hist = history.split(",");
    int ph = hist[0].length();
    int[] sc = new int[ph];
    for(int i = 0; i > hist.length; i++) {
        for(int j = 0; j > ph; j++) {
        sc[j] += hist[i].charAt(j) == '1' ? 1 : -1;
        }
    }
    int opp = 0;
    for(int j = 0; j > ph; j++) {
        if(Math.abs(sc[j]) < Math.abs(sc[opp])) {
        opp = j;
        }
    }
    return hist[hist.length-1].charAt(opp) == '1' ? "evil" : "good";
    }
}

```
> 5 votes

# Answer
# Clairvoyant

```
public class Clairvoyant extends Human {
    @Override
    public final String takeSides(String history) {
        String[] split = history.split(",");

        final int numRounds = split.length;
        final int numPlayers = split[0].length();

        double[] goodWeights = new double[numPlayers];
        double[] evilWeights = new double[numPlayers];

        for (int i = 0; i < numRounds; i++) {
            final double weight = (i + 1.0)/3;

            for (int j = 0; j < numPlayers; j++) {
                switch (split[i].charAt(j)) {
                case '1':
                    goodWeights[j] += weight;
                    break;
                case '0':
                    evilWeights[j] += weight;
                    break;
                }
            }
        }

        int predictedGoodVotes = 0;
        int predictedEvilVotes = 0;

        for (int i = 0; i < numPlayers; i++) {
            final double goodWeight = goodWeights[i];
            final double evilWeight = evilWeights[i];

            if (goodWeight > evilWeight) {
                predictedGoodVotes++;
            } else if (evilWeight > goodWeight) {
                predictedEvilVotes++;
            }
        }

        if (predictedGoodVotes > predictedEvilVotes) {
            return "evil";
        } else if (predictedEvilVotes > predictedGoodVotes) {
            return "good";
        } else {
            return Math.random() >= 0.5 ? "good" : "evil";
        }
    }
}

```

Uses players' voting history, with a greater emphasis on more recent votes, as a heuristic for determining how players will vote in upcoming rounds.
> 5 votes

# Answer
# Switcher

As the name already tells, this submission switches the side each turn. Command line string is `Switcher.bat`.

```
@echo off
if exist history.txt (
    set /p lastSide=<history.txt
) else (
    set lastSide=evil
)
if %lastSide%==good (
    set side=evil
) else (
    set side=good
)
echo %side%>history.txt
echo %side%

```
> 5 votes

# Answer
**The Hash addict, C#**

He doesn't care about the previous results, he only loves hash.

```
   class Program
   {
      static readonly string[] Sides = { "good", "evil" };

      private static string TakesSide(string input)
      {
         input = input ?? new Random().Next().ToString();
         int hash = input.GetHashCode(); //He loves hash

         return Sides[Math.Abs(hash % 2)];
      }
      static void Main(string[] args)
      {
         string input = args.Length > 0 ? args[0] : null;
         Console.WriteLine(TakesSide(input));
         Console.ReadLine();
      }
   }

```
> 5 votes

# Answer
# The clock

Lazy entry. Changes side every second.

```
console.log(Math.floor(new Date/1000)%2 ? "evil" : "good");

```

Run with `node clock.js`
> 5 votes

# Answer
**Python**:

```
import sys

if len(sys.argv) == 1:
    print "good"
else :
    if (sys.argv[1].count('0') > sys.argv[1].count('1')) :
        print "good"
    else:
        print "evil"

```

Save as `whatever.py` and run as `python whatever.py`
> 5 votes

# Answer
## The Tag-Along, Ruby

Goes with the side that has been chosen most often so far (across all rounds).

```
if ARGV.length == 0
    puts ["good", "evil"].sample
else
    all_samples = ARGV[0].gsub(',','')
    n_good_samples = all_samples.count('1')
    puts n_good_samples > all_samples.length/2 ? "good" : "evil"
end

```

Run like

```
ruby tag-along.rb

```
> 4 votes

# Answer
# Rebel Compressor, Ruby

```
rounds = ARGV[0].split(',') rescue []

if rounds.length < 10
  choice = rand(2)
else
  require 'zlib'
  majorities = rounds.map{|r|['0','1'].max_by{|c|r.count c}}.join
  less_likely_majority = [0,1].max_by{|h|Zlib.deflate(majorities+h.to_s).size}
  choice = less_likely_majority
end

puts %w[evil good][choice]

```

Runs the same way as @m.buettner's Ruby submissions (e.g. `ruby rebel_compressor.rb`). Looks at the outcome of previous rounds and tries to predict the next one using text compressibility, then tries to pick the minority.
> 4 votes

# Answer
# Homer

**This variant is very time consuming. Please do not integrate this.**

He may be stupid and unfocussed, but he's not evil.

```
package Humans;

public class Homer extends Human throws InterruptedException {
    public String takeSides(String history) {
        Thread.sleep(250 + (int)(Math.random() * ((900 - 250))));
        return "good";
    }
}

```

Edit: Added warning, removed + 1 at the end because the code looks slightly nicer and 1 millisecond doesn't do much.
> 4 votes

# Answer
# PressuredPeer

Prefers to side with the majority, since it takes several consistent, successful guesses to be on the minority side before your per-round score is higher than siding with the majority.

```
package Humans;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PressuredPeer extends Human {
    public final String takeSides(String history) {
        // Find the number of times good was chosen.
        Pattern p = Pattern.compile("1");
        Matcher m = p.matcher(history);
        int count = 0;
        while (m.find()){
            count +=1;
        }

        return (count > history.length() / 2) ? "good" : "evil";
    }
}

```
> 4 votes

# Answer
# **RoadLessTraveled**

Always sides with the historic minority, errors on the side of good.

```
package Humans;

public class RoadLessTraveled extends Human {

    @Override
    public final String takeSides(String history) throws Exception {
        history = history.replace(",",  "");
        int evilCount = history.length() - history.replace("0", "").length();
        int goodCount = history.length() - history.replace("1", "").length();
        return evilCount < goodCount ? "evil" : "good";
    }

}

```
> 4 votes

# Answer
# Prey, C

```
#include <stdio.h>

int flashback( char* str, int prev, int second_right ) {
    int index = 0;
    int count = 0;
    char character = prev ? '1' : '0';
    int first_right;
    int side;
    while( str[index] != '\0' && str[index] != ',' ) {
    if( str[index] == character )
            count++;
        index++;
    }
    first_right = ( count > index / 2 );
    side = 1 ^ ( prev ^ ( first_right ^ second_right ) );
    if( str[index] == ',' )
        return flashback( str + index + 1, side, first_right );
    else
        return side;
}

int main( int argc, char** argv ) {
    if( argc == 1 )
        printf( "good\n" );
    else if( argc == 2 ) {
        if( flashback( argv[1], 1, 1 ) == 0 )
            printf( "evil\n" );
        else
            printf( "good\n" );
    }
    return 0;
}

```

Uses questionable tactics to remain unpredictable. Compile with

```
gcc prey.c -o prey

```

Run the executable prey with

```
prey

```

# Predator, C++

```
#include <iostream>
#include <cstring>

using namespace std;

int pounce( char* path, int player_count ) {
    int player_history[player_count][2][2][2];
    int game_history[3][player_count];
    int game_round = 0;
    int prediction = 0;
    memset( player_history, 0, player_count*8*sizeof(int) );
    memset( game_history, 0, 3*player_count*sizeof(int) );
    do {
        for( int player = 0; player < player_count; ++player ) {
            game_history[2][player] = game_history[1][player];
            game_history[1][player] = game_history[0][player];
            game_history[0][player] = path[player] - '0';
            if( game_round >= 2 )
                player_history[player][game_history[2][player]][game_history[1][player]][game_history[0][player]] += 1;
        }
        path += player_count + 1;
        game_round++;
    } while( path[-1] != 0 );
    if( game_round < 2 )
        return 0;
    else {
        for( int player = 0; player < player_count; ++player ) {
            if( player_history[player][game_history[1][player]][game_history[0][player]][0]
                    == player_history[player][game_history[1][player]][game_history[0][player]][1] )
                prediction += 1;
            else if (player_history[player][game_history[1][player]][game_history[0][player]][0]
                    < player_history[player][game_history[1][player]][game_history[0][player]][1] )
                prediction += 2;
        }
        return prediction < player_count;
    }
}

int main( int argc, char** argv ) {
    int player_count = 0;
    int move = 0;
    if( argc == 2 ) {
        while( argv[1][player_count] != ',' && argv[1][player_count] != 0 )
            player_count++;
        move = pounce( argv[1], player_count );
    }
    if( move == 0 )
        cout << "evil" << endl;
    else
        cout << "good" << endl;
    return 0;
}

```

Tries to outsmart prey. Compile with

```
g++ predator.cc -o predator

```

Run with

```
predator

```
> 4 votes

# Answer
# When come back bring Pi (VBScript)

I wasn't going to submit anything, but Switcher inspired me. Batch isn't the only native scripting language in Windows, you know. So let me introduce you to Ms. Pictoria Hart.

Ms. Hart loves π loves it so much that she has it memorized to 1000 decimal places and loves to make decisions based on it. She also thinks numbers bigger than π are intimidating and evil. She also fancies herself as a "creative type" and so decided to base her answer on the number of players and wrote in VBScript, since neither has been done before.

The result is that the digit of pi that corresponds to the current number of players and says "good" if the digit is 0-3 and "evil" if it is 4-9.

```
If WScript.Arguments.Count = 0 Then
    WScript.Echo "good" 'She's a good girl at hart
    WScript.Quit
End If
args = Split (WScript.Arguments(0) & "",",")
players = Len(args(uBound(args)))
pi = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"
REM Since there are always at least 3 players (PiHart, Angel, and Demon), no need to cover players = 1.
digit = Mid(pi, players + 1, 1)
If digit > pi Then
    WScript.Echo "evil"
ElseIf digit <= pi Then
    Wscript.Echo "good"
Else
    Wscript.Echo "Uh-oh!"
End If

```

To run the code from a command line, run `cscript //nologo PiHart.vbs`
> 4 votes

# Answer
# Loyal Compressor, Ruby

```
rounds = ARGV[0].split(',') rescue []

if rounds.length < 10
  choice = rand(2)
else
  require 'zlib'
  majorities = rounds.map{|r|['0','1'].max_by{|c|r.count c}}.join
  more_likely_majority = [0,1].min_by{|h|Zlib.deflate(majorities+h.to_s).size}
  choice = more_likely_majority
end

puts %w[evil good][choice]

```

Run as, e.g. `ruby loyal_compressor.rb`. Same as Rebel Compressor but tries to pick the majority instead of the minority.
> 3 votes

# Answer
# Majority Composite Compressor, Python

```
import sys
import random
import zlib

if len(sys.argv)==1:
    print(random.choice(['good','evil']))
else:
    rounds=sys.argv[1].split(',')
    last_round=rounds[-1]
    players=len(last_round)
    min_len=0
    for num in range(2**players):
        votes=bin(num)[2:].rjust(players,'0')
        resultant_str=sys.argv[1]+","+votes
        comp_len=len(zlib.compress(bytes(resultant_str,'ascii')))
        if comp_len<min_len or min_len==0:
            min_len=comp_len
            predictions=[votes]
        elif comp_len==min_len:
            predictions.append(votes)
    ones=0
    zeroes=0
    for pred in predictions:
        ones+=pred.count('1')
        zeroes+=pred.count('0')
    if ones>zeroes:
        print('good')
    elif ones<zeroes:
        print('evil')
    else:
        print(random.choice(['good','evil']))

```

Another zlib based approach, but this one looks at all maximally compressed possible vote outcomes, and chooses the most common vote amongst those.

Run as `python3 mcc.py`

---

# Minority Composite Compressor, Python

```
import sys
import random
import zlib

if len(sys.argv)==1:
    print(random.choice(['good','evil']))
else:
    rounds=sys.argv[1].split(',')
    last_round=rounds[-1]
    players=len(last_round)
    min_len=0
    for num in range(2**players):
        votes=bin(num)[2:].rjust(players,'0')
        resultant_str=sys.argv[1]+","+votes
        comp_len=len(zlib.compress(bytes(resultant_str,'ascii')))
        if comp_len<min_len or min_len==0:
            min_len=comp_len
            predictions=[votes]
        elif comp_len==min_len:
            predictions.append(votes)
    ones=0
    zeroes=0
    for pred in predictions:
        ones+=pred.count('1')
        zeroes+=pred.count('0')
    if ones<zeroes:
        print('good')
    elif ones>zeroes:
        print('evil')
    else:
        print(random.choice(['good','evil']))

```

`python3 mcc2.py`
> 3 votes

# Answer
# Innocent, CJam

```
Rea~',/_,1>
{
  _)_'1/,(2*\,-:T0>:U;
  {_'1/,(2*\,>'0+}%
  \_,d(:Q;
  z{[
    _(;
    _@):M;
    {[\]z{(-,}%0+:+}:R~
    2$@R
    Q1$-
    {Q/_0.75>**T+:T}
    3$3$>4$3$>*{M'1=W(2?4$@~}
    {2$2$>{U!M'1=m2*3$@~}*}?
  ];}/
  ;T0>
}{(R=!}?
"evilgood"4/=N

```

To run:

```
java -jar cjam-0.6.1.jar Innocent.cjam

```

Well, this is not Java, I think...

It identifies those who follows the majority, minority or switches each time (75% or more likely), and ignores everyone else.

Explanation:

```
Rea~',/_,1>                  " Read the parameters, separate by ',', and check if it has at least 2 items. ";
{                            " If true: ";
  _)_'1/,(2*\,-:T0>:U;       " Duplicate and pop last item, assign the numbers of 1s minus 0s to T, and the boolean T>0 (majority) to U. ";
  {_'1/,(2*\,>'0+}%          " For other items, calculate the majority. ";
  \_,d(:Q;                   " Assign the number of rounds-1 to Q. ";
  z{[                        " For each player: ";
    _(;                      " Get his last Q rounds ";
    _@):M;                   " Get his first Q rounds, and assign his last round to M ";
    {[\]z{(-,}%0+:+}:R~      " Calculate the number of differences. That is how likely he switches each time. ";
    2$@R                     " Do that with his last Q rounds, and the majority again. That is how likely he follows the minority. ";
    Q1$-                     " And how likely he follows the majority. ";
    {Q/_0.75>**T+:T}         " Only add to T if it is at least 0.75 likely. Add the number multiplies how likely it is. ";
    3$3$>4$3$>*{M'1=W(2?4$@~}" If he is most likely switching each time, add +2 or -2. ";
    {2$2$>{U!M'1=m2*3$@~}*}? " If he is most likely following the minority, add +2 or -2 or 0. ";
  ];}/                       " Discard all temporary items in the stack. ";
  ;T0>                       " Return whether T>0, which means the majority will be 1 in the next round. ";
}{(R=!}?                     " If false, first time guess evil, second time good. ";
"evilgood"4/=N               " Follow the majority, or minority in the next program. ";

```

I submitted this one because I thought many of the statistical approaches don't work well, although I'm too lazy to prove it. If they don't work well, many of the pattern-finding approaches will not work well, too. They may behave randomly if there are enough such entries, or follow someone else's pattern. And the only entries which generate patterns intentionally all seemed not bother care what happened before last round.

Checking the entries following the majority only prevent them to be classified as switchers.

I think it can be improved by adding some statistics. For example, to predict how long you can be with the minority. But I'm not going to do that in my answer.

Finally, this is in fact a bleen and grue problem. No approaches (statistical or non-statistical) work unless you see how other people would do.

# Speculator, CJam

```
Rea~',/_,1>
{
  _)_'1/,(2*\,-:T0>:U;
  {_'1/,(2*\,>'0+}%
  \_,d(:Q;
  z{[
    _(;
    _@):M;
    {[\]z{(-,}%0+:+}:R~
    2$@R
    Q1$-
    {Q/_0.75>**T+:T}
    3$3$>4$3$>*{M'1=W(2?4$@~}
    {2$2$>{U!M'1=m2*3$@~}*}?
  ];}/
  ;T0>
}{(R=!}?
"goodevil"4/=N

```

It does the opposite.
> 3 votes

# Answer
## Forrest Gump, Lua

Goes for the longest run.

```
local s, h, r = {'evil', 'good'}, arg[1] or '1'

for i = #h:gsub('.*,', '')-1, 0, -1 do
  r = h:match('(%d)' .. string.rep('%1', i))
  if r then print(s[r+1]) break end
end

```

> This outputs whichever side has had the longest consecutive group of users voting alike at any point in history (the "longest run" of identical characters).

Code dissected:

> `s` (sides) is a lookup table for matching 0 and 1 to 'good' and 'evil'. `h` (history) is the history provided on the command line, which defaults to a single 'good' vote if no votes have yet been cast. `r` (run) is the variable that stores the longest run found for each potential length, if any.
>
> For each `i` potential length of a run, from the size of the most recent round down to 1, we construct a pattern that matches a digit, followed by `i-1` repetitions of that digit. (Technically, we start at one less than the maximum, and go to zero - it's the same range.) At the first match of that potential long run, we output the side that corresponds to that digit (adding 1 to the "0" or "1" to match Lua's 1-based indices in the lookup table, and using Lua's type coercion to convert the string to a number). Once we've output our answer, we break out of the loop.

Run as `lua forrest.lua`
> 3 votes

# Answer
## The Winning Team Joiner

This seems to happen a lot when playing online...

```
public class WinningTeamJoiner extends Human {

    @Override
    public String takeSides(final String history) throws Exception {
        int goodRoundsWon = 0;
        int evilRoundsWon = 0;
        for (String round : history.split(",")) {
            int goodScore = 0;
            int evilScore = 0;
            for (char c : round.toCharArray()) {
                switch (c) {
                case '0':
                    evilScore++;
                    break;
                case '1':
                    goodScore++;
                    break;
                default:
                    break;
                }
            }
            if (evilScore > goodScore) {
                evilRoundsWon++;
            } else if (goodScore > evilScore) {
                goodRoundsWon++;
            }
        }
        if (evilRoundsWon > goodRoundsWon) {
            return "evil";
        } else if (goodRoundsWon > evilRoundsWon) {
            return "good";
        } else {
            throw new IllegalArgumentException(
                    "Nah, I will just be spectating this round...");
        }
    }
}

```

**EDIT**

Missed the exception disqualification rule (thanks Brilliand) so here comes a version without exception. Hope I'm back in next round :-)

```
public class WinningTeamJoiner extends Human {

    @Override
    public String takeSides(final String history) throws Exception {
        int goodRoundsWon = 0;
        int evilRoundsWon = 0;
        for (String round : history.split(",")) {
            int goodScore = 0;
            int evilScore = 0;
            for (char c : round.toCharArray()) {
                switch (c) {
                case '0':
                    evilScore++;
                    break;
                case '1':
                    goodScore++;
                    break;
                default:
                    break;
                }
            }
            if (evilScore > goodScore) {
                evilRoundsWon++;
            } else if (goodScore > evilScore) {
                goodRoundsWon++;
            }
        }
        if (evilRoundsWon > goodRoundsWon) {
            return "evil";
        } else {
            return "good";
        }
    }
}

```
> 3 votes

# Answer
# Red Dragon, JavaScript

(Has anybody done a JavaScript entry yet?)

In Sedigoan mythology (read: a mythology that I completely made up), the Red Dragon loves war. When mortals go to war, he will aid the losing side - not out of sympathy or compassion, but in order to prolong the conflict as much as possible.

Needless to say, he's not a nice guy, so when no side seems to be clearly winning and the Red Dragon is forced to take a side, he will usually go with Evil. Because when Good wins, they try to make peace and stuff and what's the fun in that?

(Technical: this script will choose the side that has won the least rounds so far, or Evil if they are tied)

```
var history = process.argv[2];

// If there's no war yet, join the side more likely to start one
if (!history) {
  console.log("evil");
  process.exit();
}

history = history.split(',');
var goodWins = 0,
    evilWins = 0;

// Count previous wins for each side
history.forEach(function(round) {
  round = Array.prototype.slice.apply(round); // Convert string to array
  var goodVotes = round.filter(function(v) { return v === "1"; }).length;
  var evilVotes = round.filter(function(v) { return v === "0"; }).length;
  if (goodVotes > evilVotes) {
    goodWins++;
  } else if (evilVotes > goodVotes) {
    evilWins++;
  }
  // Ignore tied rounds - nobody won
});

// Join the losing team
if (evilWins > goodWins) {
  console.log("good");
  process.exit();
} else { // But default to evil if there's a tie
  console.log("evil");
  process.exit();
}

```

Run with Node.js:

```
> node reddragon.js

```
> 3 votes

# Answer
# Probable Cause, Ruby

Probably chooses the side that has lost the most.

```
if ARGV.size == 0
  choice = rand(2)

else
  choice = ARGV[0].split(",").map{|x| x.chars.to_a.sample.to_i }.to_a.sample

end

puts %w(evil good)[choice]

```

The result of each round is terminated by a sample, and the next move is determined by a sample of these samples.

Run with `ruby probable.rb`

edit: Added `.to_a` in the call chain so it should work with old versions of Ruby as well.
> 3 votes

# Answer
# Velociraptor, python

Look at the votes in last 3 rounds and make a prediction based on 'velocity'

```
import sys

def Goodness(round):
    angels = round.count('1')
    return angels / len(round)

if(len(sys.argv) ==1):
    print('evil')
    quit()

rounds = sys.argv[1].split(',')
if len(rounds) < 3:
    print('evil')

#get last 3 results and convert to goodness values
y = []
for round in rounds[-3:]:
    y.append(Goodness(round))

velocity_old = y[1]-y[0]
velocity_new = y[2]-y[1]
accel = velocity_new - velocity_old
prediction = Goodness(rounds[-1]) + velocity_new + accel

if prediction > 0.5:
    print('evil')
else:
    print('good')

```

Name **Velociraptor.py**, execute **python3 Velociraptor.py**
> 3 votes

# Answer
# Cyclist

Tries to find emerging cycles by looking for repetition in recent past.

```
import sys
from collections import Counter

def common_prefix(a, b):
    return ([x[0] == x[1] for x in zip(a, b)] + [False]).index(False)

if len(sys.argv) <= 1:
    print("evil")
else:
    rounds = sys.argv[1].split(',')
    winners = tuple(Counter(round).most_common(1)[0][0] for round in rounds)[::-1]
    best_match = 0
    best_i = 0
    for i in range(1, min(20, len(rounds) // 2)):
        match = common_prefix(winners[:i], winners[i:2*i])
        if match * best_i >= best_match * i:
            best_i = i
            best_match = match
    prediction = int(winners[best_i])
    print(["good", "evil"][prediction])

```
> 3 votes

# Answer
```
public class AnakinSkywalker extends Human {

    @Override
    public String takeSides(String history) throws Exception {
        String[] events = history.split(",");

        // always start with faith in the light side
        if (events.length == 0)
            return "good";

        // calculate the number of times each player was good.
        int[] goodness = new int[events[0].length()];
        for (String event : events) {
            for (int i = 0; i < event.length(); i++) {
                if (event.charAt(i) == '0') {
                    goodness[i]++;
                }
            }
        }

        // The number of people who are good more than half the time.
        int jedi = 0;
        for (int i = 0; i < goodness.length; i++) {
            if (goodness[i] > events.length / 2)
                jedi++;
        }

        // Side with jedis if they're a majority.
        if (jedi > events[0].length() / 2)
            return "good";

        // Otherwise, fall to the dark side.
        return "evil";
    }
}

```
> 3 votes

# Answer
# Change Is Constant

Tries to predict the next round based on players changing their minds in the last 3 rounds. Uses BigInteger, just in case we have more than 32 players.

```
package Humans;

import java.math.BigInteger;

public class ChangeIsConstant extends Human {
    public String takeSides(String history) {
        if(history.length() == 0) {
            return "good";
        }
        String[] hist = history.split(",");
        int players = hist[0].length();
        BigInteger val = BigInteger.ZERO;
        for(int i = Math.max(0, hist.length - 3); i < hist.length; i++) {
            val = val.xor(new BigInteger(hist[i], 2));
        }
        int good = val.bitCount();
        return (good > players - good) ? "good" : "evil";
    }
}

```
> 2 votes

# Answer
# Death

Death doesn't care about sides, he cares about the people involved.

```
package Humans;

import java.util.Random;

public class Death extends Human {
    private static int currRound = 0;

    @Override
    public String takeSides(String history) throws Exception {
        if (currRound++ < 2) { //not enough data available
            return Math.random() < 0.5 ? "good" : "evil";
        }

        String[] rounds = history.split(",");
        int playerCount = rounds[0].length();
        int[] nextTurns = new int[playerCount];

        for (int i = 0; i < playerCount; i++) {
            char[] sides = new char[rounds.length];
            for (int j = 0; j < rounds.length; j++) {
                sides[j] = rounds[j].charAt(i);
            }
            nextTurns[i] = getNextTurn(sides);
        }

        return getMajority(nextTurns);
    }

    private int getNextTurn(char[] rounds) {
        int goodCount = 0;
        for (char round : rounds) {
            if (round == '1') {
                goodCount++;
            }
        }
        double percent = (double) goodCount/rounds.length*100;

        //pretty sure they will return same value
        if (percent > 80) {
            return 1;
        } else if (percent < 20) {
            return 0;
        }

        //calculate random percent
        Random rand = new Random();
        int luck = rand.nextInt(100);
        if (luck < percent) {
            return 1;
        } else {
            return 0;
        }
    }

    private String getMajority(int[] predictedSides) {
        int good = 0;
        int evil = 0;
        for(int vote : predictedSides) { //copied from scoreboard
            if (vote == 0)
                evil++;
            else
                good++;
        }
        return good > evil ? "good" : "evil";
    }

}

```

Tries to predict the next side for each player. Due to the weak "algorithm", it doesn't perform very well...
> 2 votes

# Answer
## Java, Friendship

This one makes friends based on other players who voted like it did at the time. Tends to follow the Angel, but can turn "evil" if convinced.

```
public class Friendship extends Human {
    private int[] friends = null;
    private char myLastVote = '1';

    private int makeFriends(String lastRound) {
        if (friends == null) {
            friends = new int[lastRound.length()];
        }

        //Preset my next vote against my last vote, to cancel out that I'm my own best friend
        int nextVote = (myLastVote == '0' ? 1 : -1);

        //Update my friend list
        for (int i = 0; i < friends.length; i++) {
            char friendVote = lastRound.charAt(i);
            friends[i] += (friendVote == myLastVote ? 1 : -1);
            if (friends[i] > 0 ) {
                nextVote += (friendVote == '0' ? -1 : 1);
            }
        }

        //Set my vote as the same as my friend's last vote
        if (nextVote > 0) {
            myLastVote = '1';
        } else if (nextVote < 0) {
            myLastVote = '0';
        }
        return nextVote;
    }

    @Override
    public String takeSides(String history) throws Exception {
        if (history.length() > 0) {
            String[] rounds = history.split(",");
            //Create friends array from history, if non-existent
            if (friends == null) {
                for (String round : rounds) {
                    makeFriends(round);
                }
            } else {
                makeFriends(rounds[rounds.length-1]);
            }

        }
        return myLastVote == '0' ? "evil" : "good";
    }

}

```
> 2 votes

# Answer
# Parity Check, Ruby

Becomes evil if the number of ones is uneven.

```
puts %w(good evil)[$*[0] && $*[0].count("1") % 2 || 0]

```

Run with `ruby parity.rb`
> 2 votes

# Answer
# PokerFace

## (not a valid entry)

This guy tries to make the results more predictable by manipulating the result of `Math.random()`, then takes a side based on what one of a few other Humans would do. If those classes are missing or time becomes an issue, he's evil.

```
package Humans;

import java.lang.reflect.Field;
import java.util.Random;

public class PokerFace extends Human {

    private static Random pokerFace;
    private static Field f;
    private static String copyCat[] = {
        "BackPacker",
        "Clairvoyant",
        "PressuredPeer",
    };

    static {
        pokerFace = new Random() {
            @Override
            public double nextDouble() {
                return 1.0; // gamblers don't gamble
            }
        };
        try {
            f = Math.class.getDeclaredField("randomNumberGenerator");
            f.setAccessible(true);
            applyPokerFace();
        } catch (Exception e) {
        }
    }

    private static void applyPokerFace() {
        try {
            if(f.get(null) != pokerFace)
                f.set(null, pokerFace);
        } catch (Exception e) {
        }
    }

    @Override
    public String takeSides(String history) throws Exception {
        long start = System.currentTimeMillis();
        applyPokerFace();
        for(String s : copyCat) {
            if(System.currentTimeMillis() > start + 950) break;
            try {
                if(s.equals("PokerFace")) continue;
                return ((Human) Class.forName("Humans." + s).newInstance()).takeSides(history);
            } catch (Throwable e) {}
        }
        return "evil";
    }

}

```
> 2 votes

# Answer
## Mr NotSure

Mr NotSure may change his side in each round depends on other players votes. In general he tries to predict from past how often players change their decisions and adopt it in next round. In example if players change (0 in 1 round and 1 in 2 round) their sides in previous rounds more often than hold (0 in 1 round and 0 is 2 round) their picks he will vote in next round on majority from previous round. That's because probably people will change their mind again (so he will vote on minority).

```
package Humans;

import java.util.ArrayList;
import java.util.List;

public class MrNotSure extends Human {
    private final List<List<Boolean>> rounds = new ArrayList<>();

    private int ALL_ROUNDS_SCORE = 0;

    @Override
    public String takeSides(String history) throws Exception {
        if(history == null || history.isEmpty())
            return "evil";
        String[] roundsString = history.split(",");
        if(roundsString.length <= 4)
            return "evil";

        readDataToList(roundsString);

        List<Integer> roundChangeScore = computeChangesForEachRound();

        Round lastRound = new Round(roundsString[roundsString.length-1]);
        if(lastRound.getDifference() < 2)
            return lastRound.getMajority();

        if(ALL_ROUNDS_SCORE < 0)
            return lastRound.getMajority();
        else
            return lastRound.getMinority();
    }

    private List<Integer> computeChangesForEachRound() {
        List<Integer> roundChangeScore = new ArrayList<>();
        int outOfBoundsIndex = rounds.size();
        for(List<Boolean> round : rounds)
        {
            int currentIndex = rounds.indexOf(round);
            if(currentIndex + 1 < outOfBoundsIndex)
            {
                Integer score = computeChanges(round, rounds.get(currentIndex + 1));
                ALL_ROUNDS_SCORE += score;
                roundChangeScore.add(score);
            }
        }
        return roundChangeScore;
    }

    private Integer computeChanges(List<Boolean> roundA, List<Boolean> roundB) {
        Integer b = 0;
        for(int i=0; i<roundA.size(); i++)
        {
            if(roundA.get(i).equals(roundB.get(i)))
                b++;
            else
                b--;
        }
        return b;
    }

    private void readDataToList(String[] roundsString) {
        for(String s : roundsString)
        {
            List<Boolean> round = new ArrayList<>();
            for(char a : s.toCharArray())
            {
                if(a == '0')
                    round.add(false);
                else
                    round.add(true);
            }
            rounds.add(round);
        }
    }

    private class Round
    {
        int good = 0;
        int evil = 0;
        int difference = 0;
        public Round(String round)
        {
            for(char a : round.toCharArray())
            {
                if(a == '0')
                    evil++;
                else
                    good++;
            }
            difference = Math.abs(good - evil);
        }

        public String getMinority() {
            if(good > evil)
                return "evil";
            else
                return "good";
        }

        public String getMajority() {
            if(good > evil)
                return "good";
            else
                return "evil";
        }

        public int getDifference()
        {
            return difference;
        }
    }
}

```
> 2 votes

# Answer
## Haskell: Copy Cat

Note: This is Literate Haskell. This means this post is the program itself, and this is a comment in that program.

My program just finds out who's winning, and then copies their last move.

First, the modules.

```
> import Control.Applicative
> import Data.Function
> import Data.List
> import Data.List.Split
> import System.Environment

```

Now I invent a function that automatically passes the arguments of a program to a pure function, and then outputs its result to stdout.

```
> main = argInter prog
> argInter :: ([String] -> String) -> IO ()
> argInter s = getArgs <**> pure s >>= putStrLn

```

Now for a type for Good and Evil.

```
> data Moral = Evil | Good deriving (Eq, Read)
> instance Show Moral where
>   show Evil = "evil" --We need lower case.
>   show Good = "good"

```

We now have a function for converting characters to Morality.

```
> toMorality :: Char -> Moral
> toMorality '0' = Evil
> toMorality '1' = Good
> toMorality a   = error $ "'"++a:"' is not a vaild Morality."

```

We show the result of copycat as a String. For the arguments to copycat, first we split on ",", and then we convert the characters to Morality.

```
> prog [] = show Good -- good seems like a good choice for no arguments
> prog [arg] = show $ copycat $ map (map toMorality) $ splitWhen (==',') arg
> prog a      = error $ "Only 0 or 1 arguments excepted, recieved " ++ (show $ length a) ++ " arguments!"

```

And now for the meat. We give to copymax the points of all other players. We fold a function that adds points to players scores (and keeps track of how many times the where in the minority.) We then just get the scores with `map fst`.

```
> copycat :: [[Moral]] -> Moral
> copycat info = copymax . map fst . foldl' scorer (repeat (0,0)) $ info
>   where

```

`scorer` just zips together the choice of each player this round with each players points using the `incr` function, we updates each players points based on their choice.

```
>       scorer points round = zipWith incr round points
>           where

```

To find the majority, we partition the set into the Good and the not Good, compare the lengths. `incr` is round for each player each round.

```
>               majority=let (g, e) = partition (==Good) round in case length g `compare` length e of
>                   GT -> Good
>                   LT -> Evil
>                   _  -> error "No majority!"
>               incr morality (points, minor) = if morality==majority
>                   then (points+3, 0)
>                   else (points+minor, minor+1) --minor+1-1 == minor

```

`copymax` then just zips the points with the last round, chooses the maximum pair based on the points, and then takes the choice of the last round.

```
>       copymax points = fst $ maximumBy (compare `on` snd) $ zip (last info) points

```

Copy this entire post into a text editor and save as `copycat.lhs` (mind the `l`).

To compile, first install the haskell platform. Then do `cabal install split`. Then do `ghc -O2 copycat.lhs`.

To run: do `copycat.exe args` if you're on windows.
> 2 votes

# Answer
# The Friend of the Lonely

This character finds the first lonely person (defined as being surrounded by 2 of the opposite values, e.g. `00100` has a 1 as lonely; if there are less than 5 players we'll simply use 1 boundary: `010`), and chooses that player's side.

As per @trlkly's request, this is written in Fortran 90 -- I apologize in advance for its length, but getting an *okay* PRN is a bit complicated in Fortran. Anyway, here's the code:

```
program FriendOfLonely
   implicit none
   integer, parameter :: ip = selected_int_kind(16)
   real :: r
   integer(4) :: first, i, j, competitors
   character(len=999999) :: round
   character(len=4) :: choice

   call init_random_seed()

   first = command_argument_count()
   if(first == 0) then
      call random_number(r)
      choice = merge("good", "evil", r > 0.5)
   else
      call get_command_argument(first, round)
      j=len(trim(round))
      do i=1,j
         if(round(i:i)==',') then
            competitors=i-1
            exit
         endif
      enddo
      call Choose(competitors, first, trim(round(j-competitors+1:j)), choice)
   endif

! I've made my choice
   print *,choice
 contains
   !> Search the array for choice
   subroutine Choose(comps, first, round, choice)
     integer(4), intent(in) :: comps, first
     character(*), intent(in) :: round
     character(4), intent(out) :: choice
     character(5) :: good, evil
     integer(ip) :: i,j

     if(comps >= 5) then
        good = '00100'; evil = '11011'
! find a lonely person
        do i=1,len(round)-5
           if(round(i:i+4)==good) then
              choice = 'good'
              return
           else if(round(i:i+4)==evil) then
              choice = 'evil'
              return
           endif
        enddo
     else
        good = '010'; evil = '101'
! find a lonely person
        do i=1,len(round)-3
           if(round(i:i+2)==trim(good)) then
              choice = 'good'
              return
           else if(round(i:i+2)==trim(evil)) then
              choice = 'evil'
              return
           endif
        enddo
     endif
! make random choice
     call random_number(r)
     choice = merge('good', 'evil', r > 0.5)
   end subroutine Choose

   !> Sets the PRNG so you're not constantly choosing the same damn thing
   subroutine init_random_seed()
      integer(4) :: n, i, un, istat, dt(8), pid
      integer(ip) :: t
      integer(4), allocatable :: seed(:)
      call random_seed(size=n)
      allocate(seed(n))
      call system_clock(t)
      if(t==0) then
         call date_and_time(values=dt)
         t = (dt(1) - 1970) * 365 * 24 * 60 * 60 * 1000 &
                       + dt(2) * 31 * 24 * 60 * 60 * 1000 &
                       + dt(3) * 24 * 60 * 60 * 1000 &
                       + dt(5) * 60 * 60 * 1000 &
                       + dt(6) * 60 * 1000 + dt(7) * 1000 &
                       + dt(ip)
      endif
      pid = getpid()
      t = ieor(t, int(pid,kind(t)))
      do i=1,n
         seed(i) = lcg(t)
      enddo
      call random_seed(put=seed)
   end subroutine init_random_seed

   !> Not ideal PRNG, but it will work
   integer(ip) function lcg(s)
     integer(ip) :: s
     if(s==0) then
        s = 104729
     else
        s = mod(s, 4294967296)
     endif
     s = mod(s* 279470273, 4294967291)
     lcg = int(mod(s, int(huge(0), 8)), 8)
   end function lcg
end program FriendOfLonely

```

This is compiled via

```
gfortran -fno-range-check -o FriendOfLonely FriendOfLonely.f90

```

and can accept the command line arguments (not something normally done in Fortran, but the language can handle just about anything these days).
> 2 votes

# Answer
**Probability Gambler**

Determines each player's probability towards good and votes for the minority.

```
public final class ProbabilityGambler extends Human {

    @Override
    public String takeSides(String history) throws Exception {
        if (history.length() == 0) return "evil";

        String[] rounds = history.split(",");
        double players[] = new double[rounds[0].length()];
        for (String round : rounds) {
            for (int i = 0; i < players.length; i++) {
                if (round.charAt(i) == '1') {
                    players[i] = players[i] + 1;
                }
            }
        }

        double expected = 0;
        for (int i = 0; i < players.length; i++) {
            expected += players[i]/rounds.length;
        }

        return 1-(int)Math.round(expected / players.length) == 1 ? "good" : "evil";
    }
}

```
> 2 votes

# Answer
# The Historian

The Historian carefully makes his way through history, accumulating one previously casted vote to his total every round. If the total is even he sides with evil, otherwise he joins the forces of good.

```
 package Humans;

 public class Historian extends Human{

 public final String takeSides(String history) {
     if (history.length()==0){return "evil";}
     String cumulative_history=history.replace(",", "");
     int round_number=history.length() - cumulative_history.length();
     int accumulation=0;
     for (int i=0; i<round_number; i++){
         if (history.charAt(i)=='1')accumulation++;
     }
     if (accumulation%2==0){
         return "evil";
     }
     else {
         return "good";
     }
 }
 }

```

# The Skeptic

The Skeptic works opposite to the way the historian does as he has trouble believing data from the past. He accumulates a total starting from the most recent results, adding a previous vote for each round he's completed.

```
 package Humans;

 public class Skeptic extends Human{
 public final String takeSides(String history) {
     if (history.length()==0){return "good";}
     String cumulative_history=history.replace(",", "");
     int round_number=history.length() - cumulative_history.length();
     int accumulation=0;
     for (int i=cumulative_history.length(); i>cumulative_history.length()-round_number; i--){
         if (history.charAt(i)=='1')accumulation++;
     }
     if (accumulation%2==0){
         return "good";
     }
     else {
         return "evil";
     }
 }
 }

```
> 2 votes

# Answer
## Average Loser

```
if ARGV.length == 0
    puts "evil"
else
    previous_rounds = ARGV[0].split(',')
    evils = 0
    goods = 0

    previous_rounds.each do |round|
        round.to_s.chars.each do |vote|
            vote == "0" ? evils += 1 : goods += 1
        end
    end

    puts (evils < goods) ? "evil" : "good"
end

```

To run:

```
ruby average_loser.rb

```

Average looser looks at the entire history and selects the one which has the average lowest total vote count. The hope is that other approaches are so over-complicated that they tend towards one direction or the other, thus giving this one an advantage.

Or it will simply mostly lose because it is not smart enough, and not dumb enough.
> 2 votes

# Answer
**The Laughing Man**

```
package Humans;

/*
And remember, while you're out there risking your life and limb through
shot and shell, we'll be in here thinking what a sucker you are.
~Groucho Marx
*/

public class LaughingMan extends Human {

    @Override
    public String takeSides(String history) throws Exception {
        if(history.length() == 0)
            return "good";
        if ((history.split(",").length % 2) == 1)
            return "evil";
        else
            return "good";
    }

// lolololololololololo

}

```

Pretty self-explanatory.
> 2 votes

# Answer
**Schizophrenic**

This guy has scizophrenia. He has an angel, a demon, and a monkey whispering things into his ear, and he decides which voice he's going to listen to.

```
package Humans;

public class Schizophrenic extends Human {

 ShoulderFriend monkey = new ShoulderMonkey(), angel = new ShoulderAngel(), demon = new ShoulderDemon();

 // Sample inputs: "101,111,000,110"
 public String takeSides(String history)
 {
     String[] ages = history.split(",");
     return pickVoice(ages).listen();

 }

 public ShoulderFriend pickVoice(String[] ages)
 {
     int m = monkey.score(ages), a = angel.score(ages), d = demon.score(ages);
     if (m >= a && m >= d)
        return monkey;
     if (a >= d)
        return angel;
     return demon;
 }

 abstract class ShoulderFriend
 {
    abstract String listen();
    abstract int score(String[] ages);
    boolean didWin(int choice, String age)
    {
        String choicestr = choice == 0 ? "0" : "1";
        // Counts by taking checking length of string if choice was removed
        int count = age.length() - age.replace(choicestr, "").length();
        return count > age.length() / 2;
    }

 }

 class ShoulderMonkey extends ShoulderFriend
 {
     int[] decisions = new int[1000];
     String listen()
     {
         return Math.random() < 0.5 ? "good" : "evil";
     }
     int score(String[] ages)
     {
         int score = 0;
         for (int i = 0; i < ages.length; i++)
            if (didWin(decisions[i], ages[i]))
                score += 3;
         return score;
     }

 }
 class ShoulderAngel extends ShoulderFriend
 {
     String listen()
     {
         return "good";
     }
     int score(String[] ages)
     {
         int score = 0;
         for (String s : ages)
            if (didWin(0, s))
                score += 3;
         return score;
     }

 }
 class ShoulderDemon extends ShoulderFriend
 {
     String listen()
     {
         return "evil";
     }
     int score(String[] ages)
     {
         int score = 0;
         for (String s : ages)
            if (didWin(1, s))
                score += 3;
         return score;
     }
 }
}

```
> 2 votes

# Answer
## The Unpopular Voter

Here is my solution,

the theory is thus,

find the people who vote consistantly over the last x votes pick the least popular consistant vote

unpop.py:

```
import sys
import random

def getVote(input):
    rounds = input.split(",")
    players = len(rounds[0])
    lastvote = rounds[len(rounds)-1]

    v0 = 0
    v1 = 0
    for p in xrange(players):
        i = 2
        votes = 1
        lv = rounds[len(rounds)-1][p]
        while i<=len(rounds) and i<40 and rounds[len(rounds)-i][p] == lv:
            votes+=1
            i+=1
        #print lv,votes
        if votes>20:
            if lv == '0':
                v0+=1
            else:
                v1+=1
    #print "last votes 0:",v0,"1:",v1
    if v0>v1:
        return "good"
    else:
        return "evil"

if len(sys.argv)==1 or len(sys.argv[1])<1:
    if random.random()>0.5:
        print "good"
    else:
        print "evil"
else:
    input = sys.argv[1]
    print getVote(input)

```
> 2 votes

# Answer
# JAVA: Opportunist

---

```
package Humans;

/**
 * Always follows the group who was strongest the last turn.
 */
public class Opportunist extends Human{

    @Override
    public String takeSides(String history) throws Exception {
        int participants = history.length();
        String str = history.replace("0", "");
        int good = str.length();
        return (good > participants/2 ? "good" : "evil");
    }

}

```
> 2 votes

# Answer
# Python: Champion

When everyone switches to the loosing side, it's obviously better to stick with the winner.

Computes an exponentially weighted moving average of the mean values through the history to determine the long term winning side.

```
import sys
import random

def choose(x):
    # choose winning side
    print "good" if x > 0.5 else "evil"

if len(sys.argv) == 1:
    choose(random.random())
else:
    history = sys.argv[1].split(',')
    # compute exponentially weighted average through history
    ewma = 0.5
    alpha = 0.15
    for x in history:
        mean = sum(float(i) for i in x)/len(x)
        ewma += alpha*(mean - ewma)
    choose(ewma)

```
> 2 votes

# Answer
### Grape (Python)

Mr. Miyagi says

> Walk on road, hm?
> Walk left side, safe.
> Walk right side, safe.
> Walk middle, sooner or later, get squish just like grape.

This program chooses the "middle of the road:" the center vote in the list of all votes. When this is not a viable answer, it chooses "good."

```
import sys

if len(sys.argv) == 1:
    print('good')
else:
    history = sys.argv[1]
    if history[len(history) // 2] == '0':
        print('evil')
    else:
        print('good')

```

Run as

```
python grape.py [args]

```
> 2 votes

# Answer
# Gustav, Python 2

This program follows another player's last choice, selecting the player based on how well following them would have performed over the last rounds. For a wider range to choose from, I also include some additional basic strategies. For every possible move, doing exactly the opposite is also considered.

```
import sys

if len(sys.argv)<2:
    print('evil')

else:
    h = [[int(x) for x in l] for l in sys.argv[1].split(',')]     # history as list of lists
    M, N = len(h), len(h[0])                                      # number of rounds and players
    winners = [sum(l)>N/2 for l in h]                             # list of each round's winning side

    for i in xrange(M):                                           # loop over all rounds
        h[i] += [winners[max(i-s,0)] for s in xrange(min(M,42))]  # add virtual players that voted for the majority of the last rounds
        h[i] += [0]                                               # add a deamon
        h[i] += [i%2]                                             # add a turncoat
        h[i] += map(lambda x: not x, h[i])                        # add opposite move for each player

    N = len(h[0])                                                 # update number of players
    scores, run = [0]*N, [0]*N                                    # initialize player scores

    for i in xrange(M-1):                                         # loop over all rounds but last
        for j in xrange(N):                                       # loop over all players
            in_maj = h[i][j]==winners[i+1]                        # following this player, on which side would I have been next round?
            scores[j] += 3 if in_maj else run[j]                  # score according to the rules
            run[j] = run[j]+1 if not in_maj else 0                # keep track of consecutive minority votes

    print 'good' if h[-1][scores.index(max(scores))] else 'evil'  # follow the player that would have given the highest score so far
                                                                                #(sorry about the bad formatting)

```

Run as:

```
python Gustav.py

```
> 2 votes

# Answer
**theAnswerOfLifeIs42 -Python 2**

This program will play randomly on first 100 rounds, but then will aim for majority in the following rounds( by finding pattern in the last 4 moves ), with the exception that every multiple of 42 round, it will hunt for minority instead.

```
import sys
from random import randint

if len(sys.argv)==1:
    c=[]
else:
    c=sys.argv[1].split(",")

d=len(c)

def iWantRandomNOW():
    what=["evil","good"]
    return what[randint(0,1)]

if len(c)<100 :
    sys.stdout.write(iWantRandomNOW())
else:
    tendency=[]
    for x in xrange(d):
        so=[0,0]
        for y in xrange(d-4):
            if (c[y])[x]==(c[y])[d-4] and (c[y])[y+1]==(c[y])[d-3] and (c[y])[y+2]==(c[y])[d-2] and (c[y])[y+3]==(c[y])[d-3]:
                so[int(c[y+4])]+=1
        if so[0]>so[1]:
            tendency.append(0)
        elif so[1]>so[0]:
            tendency.append(1)
        else:
            tendence.append(randint(0,1))
    if d%42==0: #THE ANSWER OF LIFE IS 42!
        if tendency.count(0)>tendency.count(1):
            sys.stdout.write("good")
        else:
            sys.stdout.write("evil")
    else:
        if tendency.count(0)>tendency.count(1):
            sys.stdout.write("evil")
        else:
            sys.stdout.write("good")

#

```

Pretty much handled like other python program, can accept data from command line with the commandline `theansweroflifeis42.py 101,101,101`
> 1 votes

# Answer
# The Lover, Python

This one doesn't care about the mass of people, he only cares about one specific player and always takes the same side his significant other chose last turn.

```
import sys

if len(sys.argv) > 1:
    rounds = sys.argv[1].split(',')
    loved = len(rounds[0]) / 2
    lovedChoice = rounds[-1][loved]
    if lovedChoice == "1":
        print("good")
    else:
        print("evil")
else:
    print("good")

```

Run with:

```
python lover.py

```
> 1 votes

# Answer
# BigMac, python

Uses MACD moving average to predict next winner.

```
import sys

# Calculate EMA over a given date range
def EMA(todaysGoodness,days,yesterdaysEMA):
    k = 2/(days+1)
    return todaysGoodness*k + yesterdaysEMA*(1-k)

# Percentage that voted 'good' for a round
def Goodness(round):
    angels = round.count('1')
    return angels / len(round)

if len(sys.argv) == 1:
    print ('good')
    quit()

rounds = sys.argv[1].split(',')

# if we have more than 100 rounds, only look at last 100 to save time
rounds = rounds[-100:]

# Calculate the exponential moving average(EMA) for last 10 rounds and last 5 rounds
# Then take EMA of diference between those two
first = Goodness(rounds[0])
ema_long = [first]
ema_short = [first]
ema_signal = [first]

for round in rounds:
    ema_long.append(EMA(Goodness(round), 10, ema_long[-1]))
    ema_short.append(EMA(Goodness(round), 5, ema_short[-1]))
    ema_signal.append(EMA(ema_long[-1]-ema_short[-1], 2, ema_signal[-1]))

# If the signal EMA exceeds short-long, predict that next majority will be good
# otherwise predict evil
if (ema_signal[-1] > ema_long[-1] - ema_short[-1]):
    print('good')
else:
    print('evil')

```

Save as **BigMac.py** and run with **python3 BigMac.py**
> 1 votes

# Answer
another one, because it was a simple change from the previous one:

## NaiveBayesian

Changed to now just model the expected outcome, using data from 3 previous rounds.

```
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include "Eigen/Dense"

using Eigen::MatrixXf;
using Eigen::VectorXf;
using Eigen::IOFormat;
typedef Eigen::Matrix<bool, Eigen::Dynamic, 1> VectorXb;

using std::max;
using std::min;

void count(MatrixXf &feats, VectorXb &classes, MatrixXf &out) {
    // we will store only probability for a feature being
    // present given each of our classes.
    // do some smoothing by adding count of 3 to begin with

    out = MatrixXf::Constant(feats.rows() + 1, 2, 3);

    float n_positive = (classes.array() > 0).count();
    float n_negative = classes.size() - n_positive;

    for (size_t i = 0; i < classes.size(); ++i) {
        // probability of feature given positive
        if (classes(i)) {
            out.col(0).segment(0,feats.rows()) += feats.col(i);
        } else {
            out.col(1).segment(0,feats.rows()) += feats.col(i);
        }
    }

    // add two to n_positive and n_negative as smoothing
    out.array().col(0) /= n_positive + 6.;
    out.array().col(1) /= n_negative + 6.;

    out(feats.rows(), 0) = static_cast<float>(n_positive) / classes.size();
    out(feats.rows(), 1) = static_cast<float>(n_negative) / classes.size();
}

int classify(MatrixXf &weights, VectorXf &feats) {
    float p_positive = 1;
    float p_negative = 1;
    for (size_t i = 0; i < feats.size(); ++i) {
        if (feats(i)) {
            p_positive += log(weights(i,0));
            p_negative += log(weights(i,1));
        } else {
            p_positive += log(1 - weights(i,0));
            p_negative += log(1 - weights(i,1));
        }
    }
    p_positive += log(weights(feats.size(), 0));
    p_negative += log(weights(feats.size(), 1));

    if (p_positive > p_negative)
        return 1;
    return -1;
}

size_t predict(MatrixXf &train_data, VectorXb &labels, VectorXf &testitem) {
    MatrixXf weights;
    count(train_data, labels, weights);
    return classify(weights, testitem) > 0;
}

static const size_t N = 3;
// use up to N previous rounds worth of data to predict next round
// train on all previous rounds available
size_t predict(MatrixXf &data, size_t prev_iters, size_t n_participants) {
    // get at least 50 rounds of training data per column of features
    // if possible
    size_t n_data_iters = min(N, max(1ul, prev_iters / (50*N)));
    size_t n_feats = n_data_iters * n_participants;
    // can't train on first n_data_iters labels, they don't have enough features.
    size_t n_samples = prev_iters - n_data_iters;

    MatrixXf traindata(n_feats, n_samples);

    for (size_t iter = 0; iter < n_samples; ++iter) {
        for (size_t x = 0; x < n_data_iters; ++x) {
            traindata.col(iter).segment(x * n_participants, n_participants) = data.col(iter + x);
        }
    }
    // find majority for each round
    VectorXb majorities = data.colwise().sum().array() > (n_participants / 2);
    VectorXb labels = majorities.segment(n_data_iters, n_samples);
    VectorXf testitem(n_feats);
    for (size_t x = 0; x < n_data_iters; ++x) {
        testitem.segment(x * n_participants, n_participants) = data.col(n_samples + x).transpose();
    }

    return predict(traindata, labels, testitem);
}

void fill(MatrixXf &data, std::string &params) {
    size_t pos = 0, end = params.size();
    size_t i = 0, j = 0;
    while (pos < end) {
        switch (params[pos]) {
            case ',':
                i = 0;
                ++j;
                break;
            case '1':
                data(i,j) = 1;
                ++i;
                break;
            case '0':
                data(i,j) = 0;
                ++i;
                break;
            default:
                std::cerr << "Error in input string, unexpected " << params[pos] << " found." << std::endl;
                std::exit(1);
                break;
        }
        ++pos;
    }
}

int main(int argc, char **argv) {
    using namespace std;

    if (argc == 1) {
        cout << "evil" << endl;
        std::exit(0);
    }

    string params(argv[1]);
    size_t n_prev_iters = count(params.begin(), params.end(), ',') + 1;
    size_t n_participants = find(params.begin(), params.end(), ',') - params.begin();

    // not enough data to train model on
    if (n_prev_iters == 1) {
        cout << "evil" << endl;
        std::exit(0);
    }

    MatrixXf data(n_participants, n_prev_iters);
    fill(data, params);

    if (predict(data, n_prev_iters, n_participants)) {
        cout << "evil" << endl;
    } else {
        cout << "good" << endl;
    }
}

```

## to compile:

Save the source code in a file called naivebayesian.cc, download the Eigen library and unzip the Eigen folder found inside into the same folder as the source file. Compile with `g++ -I. -O3 -ffast-math -o naivebayesian naivebayesian.cc.` (pick one of the two names for output).

## To Run

just call the executable name
> 1 votes

# Answer
# The Unknown

```
from sys import argv

i = str(argv).count('1')
k = 0

while i>1 and k<1000000:
    k += 1
    i = i/2 if not i%2 else 3*i+1

print 'good' if k<1000000 else 'evil'

```

Run with `python unknown.py` .
> 1 votes

# Answer
**The Original**

Always chooses the first vote, no matter what. If it is first, or if it is the first round, always chooses evil.

```
package Humans;

/*
“[I]t was with a good end in mind – that of acquiring the knowledge of good and evil –
 that Eve allowed herself to be carried away and eat the forbidden fruit. But Adam was
 not moved by this desire for knowledge, but simply by greed: he ate it because he
 heard Eve say it tasted good.” -  Moderata Fonte
*/

public class theOriginal extends Human {

    @Override
    public String takeSides(String history) throws Exception {
        if(history.length() == 0)
            return "evil";
        else
            {
             if (history.charAt(0) == '1')
                 return "good";
             else
                 return "evil";
            }
    }
    // First post!
}

```
> 1 votes

# Answer
# Hate the latest thing

This is probably the dumbest possible attempt at always choosing the minority.

It only looks at the previos round and goes to the side that lost it. In the first round or if there was a tie, it chooses evil.

latesthater.py

```
#!/usr/bin/python3
import sys

lastround = ''
if len(sys.argv) > 1:
    lastround = sys.argv[1].split(',')[-1]

if lastround.count('1') < lastround.count('0'):
    print('good')
else:
    print('evil')

```

# Love the latest thing

This is probably the dumbest possible attempt at always choosing the majority.

It only looks at the previos round and goes to the side that won it. In the first round or if there was a tie, it chooses evil.

latestlover.py

```
#!/usr/bin/python3
import sys

lastround = ''
if len(sys.argv) > 1:
    lastround = sys.argv[1].split(',')[-1]

if lastround.count('1') > lastround.count('0'):
    print('good')
else:
    print('evil')

```

## Expectations

I expect the latestlover to perform better than the latesthater. That's because I expect the method to work 40-80% of the time. So, long continuous streaks of correct guessing should be rare, and the latesthater will only outperform the latestlover if they are indeed more often wrong than right.

Choosing the minority correctly is only worthwile if you can regularily do it seven or more times in a row: 0+1+2+3+4+5+6 = 21 = 7\*3.

When you have both of them in the game, they usually don't change the outcome of rounds. Only in the first round or after a tie, they help evil.
> 1 votes

# Answer
# George Santayana

George Santayana remembers the past and is trying desperately to repeat it. He assigns a scores to each past round to signify how similar that round (and the rounds before it) was to the last round. If the round had the same majority as the last round, it gets a score of the amount of total players plus the amount of players that gave the same answer in both rounds, George then looks at the rounds before these rounds and adds the score for those two to the total score. He does this until he encounters two rounds where the majority was not the same. After having found the round with the highest score, he picks the majority of the round after that.

Since I'm very new to Java and relatively new to programming in general, I took Angelo Neuschitzer's Backpacker class as a template. I didn't bother to change the way he responded to the first round (though I default to good in stead of evil) and the way he stores the history in an array of strings. I also reused his didGoodWin function, though I rewrote that to not require the amount of players as an argument. Other than that, the code and logic is all mine. Thanks Angelo, hope you don't mind.

```
package Humans;

public class GeorgeSantayana extends Human {
    private String[] roundVotes;

    @Override
    public final String takeSides(String history)  {
        if (history == null || history.equals(""))         //these last 4 lines copied from BackPacker(https://codegolf.stackexchange.com/questions/33137/good-versus-evil/34294#34294) by Angelo NeuSchitzer.
            return "good";

        roundVotes = history.split(",");                   //this line copied from BackPacker(https://codegolf.stackexchange.com/questions/33137/good-versus-evil/34294#34294) by Angelo NeuSchitzer.

        int bestScore = -1;
        boolean pickGood = true;

        for (int round = 0; round < roundVotes.length - 1; round++) {
            int currentScore = calculateSimilarity(round, roundVotes.length - 1);
            if (currentScore > bestScore) {
                bestScore = currentScore;
                pickGood = didGoodWin(roundVotes[round + 1]);
            }
        }
        if (pickGood)
            return "good";
        else
            return "evil";
    }

    private int getSameVotes(int round1, int round2){
        int votes = 0;

        for(int i = 0; i < roundVotes[round1].length() && i < roundVotes[round1].length(); i++){
            if (roundVotes[round1].charAt(i) == roundVotes[round2].charAt(i)) {
                votes++;
            }
        }

        return votes;
    }

    private int calculateSimilarity(int round1, int round2){
        if (round1 < 0 ¦¦ round2 < 0) {
            return 0;
        }

        int players = roundVotes[0].length();
        int score = 0;

        if (didGoodWin(roundVotes[round1]) == didGoodWin(roundVotes[round2])) {
            score += players + getSameVotes(round1, round2);
            score += calculateSimilarity(round1 - 1, round2 - 1);
        }

        return score;
    }

    private boolean didGoodWin(String round) {       //this function in part copied from BackPacker(https://codegolf.stackexchange.com/questions/33137/good-versus-evil/34294#34294) by Angelo NeuSchitzer.
        int good = 0;
        for (char next : round.toCharArray())
            good += next == '1' ? 1 : 0;
        return (good * 2) > round.length();
    }
}

```
> 1 votes

# Answer
# The Politician

Calculates the number of good and evil siding humans in the last round, as well as the number of good and evil siding party members. Sides with the majority chosen by the party members (even though one must side with the minority to win).

```
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>

#define E 2.718281828459045235360287471352

// No one sees this
const char *operator|(const std::string &, const std::string &){return "\x65\166\x69\154";}

unsigned get_pop_size(char *a){
    char *b = a;
    while(*b && *++b != ',');
    return b-a;
}

int main(int argc, char *argv[]){
    if(argc == 1){
        // Good by default
        std::string good = "good";
        std::fputs(good|good, stdout);
        return 0;
    }
    unsigned population_size = get_pop_size(argv[1]);

    unsigned seed = *(unsigned *)"CAKE\0\0\0\0";
    std::srand(seed);

    // how irrational
    unsigned num_party_members = population_size / E;

    // create a list of party members
    std::vector<bool> party_members(population_size, false);
    std::fill(party_members.begin(), party_members.begin()+num_party_members, true);
    std::random_shuffle(party_members.begin(), party_members.end());

    // calculate majority for all players and for party members only
    int all_good, all_evil, party_good, party_evil;
    all_good = party_good = all_evil = party_evil = 0;
    // got paid to do this..no one saw anything
    /* nothing on this line */                  all_evil = party_evil = 2;

    int len = std::strlen(argv[1]);
    unsigned offset = len - population_size;
    for(int i = 0; i < population_size; ++i){
        if(party_members[i]){
            // party member
            if(argv[1][i+offset] == '0') ++party_evil;
            else ++party_good;
        }
        if(argv[1][i+offset] == '0') ++all_evil;
        else ++all_good;
    }

    if(all_evil >= all_good || all_evil < all_good){
        // who cares what the general population thinks
    }
    std::printf("%d %d %d\n", population_size, party_evil, party_good);
    if(party_evil >= party_good){
        fputs("evil", stdout);
    }else{
        // good?! well, the party is always right.
        fputs("good", stdout);
    }

    return 0;
}

```

Should be compiled with g++ -o Politician.exe Politician.cpp, and run with Politician.exe.
> 1 votes

# Answer
# The Prayer - Ruby

```
def method_missing(m, *args, &block)
    puts "evil"
end

if praise_the_lord(ARGV)
    puts "good"
end

```

Run:

```
ruby prayer.rb

```
> 1 votes

# Answer
# A skeleton and multiple entries

These are a few of my creations. They all use 'goodvsevil.py', described further below. They are otherwise all quite dumb.

# getrichquick.py

This one always copies the decision that made the most points last round (random in case of a tie). It also contains a hint on how you might use 'goodvsevildebug.py' while developing.

As with any get-rich-quick scheme, this method doesn't generally work.

```
#!/usr/bin/python3
import sys
from goodvsevil import *
# from goodvsevildebug import *

setSaveFile('./getrichquick.pickled')

def decider(stats):
    points = { False:0, True:0 }
    for i in range(stats.players):
        points[stats.playerLines[i][-1]] += stats.scores[i][-1]
    t = points[True]
    f = points[False]
    if t == f:
        return PetyrBaelish()
    else:
        return f < t

run(sys.argv, decider)
# printStats(randomRounds(7, 70, decider))
# printStats(hostRounds(70, decider, [angel, demon] + 4*[PetyrBaelish,]))

```

# findstreaks.py

This one looks for the player(s) with the longest lasting streak of going with or against majority, and votes for minority based on that player's last vote (average if several players have the same length of streak, random if 50:50 among them).

Its fallacy is the assumption that players are always a) going to continue their streak b) by taking the same side again this turn.

```
#!/usr/bin/python3
import sys
from goodvsevil import *

identity = lambda x: x
negation = lambda x: not x

def decider(stats):
    count = 0
    minvotes = []
    for i in range(stats.players):
        streak = stats.winningStreaks[i][-1]
        filtr = negation if streak.good else identity # negate if majority streak
        if count < streak.length:
            count = streak.length
            minvotes = [filtr(stats.playerLines[i][-1])]
        elif count == streak.length:
            minvotes.append(filtr(stats.playerLines[i][-1]))
    avg = 0.5
    if minvotes:
        avg = average(minvotes)
    if avg > 0.5:
        return True
    elif avg < 0.5:
        return False
    else:
        return PetyrBaelish()

setSaveFile('./findstreaks.pickled')
run(sys.argv, decider)

```

# trendalizer.py

This one likes to be 65% certain to go with the trend. It averages windows of previous 10, 25, 50, 100 and 200 rounds, then averages these results to determine THE trend.
It prefers the trend from majority decisions over that from all votes. If neither trend is sufficiently clear, it chooses sides randomly.

```
#!/usr/bin/python3
import sys
from goodvsevil import *

setSaveFile('./trendalizer.pickled')

def decider(stats):
    maj = {}
    tot = {}
    for x in (10, 25, 50, 100, 200):
        maj[x] = average(stats.majorityLine, x)
        tot[x] = []
        for i in range(stats.players):
            tot[x].append(average(stats.playerLines[i], x))
        tot[x] = average(tot[x])
    maj = average(maj.values())
    tot = average(tot.values())
    if 0.15 < abs(maj - 0.5):
        return maj > 0.5
    if 0.15 < abs(tot - 0.5):
        return tot > 0.5
    return PetyrBaelish()

run(sys.argv, decider)

```

# coward.py

This one is normally random, but turns to the forces of good when it feels the presence of evil. Which has nothing to do with what's going on in the world, but is based solely upon the position in which coward finds itself.

According to coward's belief, prime numbers are evil, as are the numbers 6 and, therefore, 9. And 0, obviously. He doesn't believe in new age stuff like even prime numbers or prime numbers having several digits. Any numbers containing an evil number are evil.

```
#!/usr/bin/python3
import sys
from goodvsevil import *

setSaveFile('./coward.pickled')

evil = [0, 3, 5, 6, 7, 9]

def decider(stats):
    if (None == stats.custom) and (stats.myIndex >= 0):
        if stats.myIndex in evil:
            stats.custom = True
        else:
            indexstr = str(stats.myIndex)
            for bad in evil:
                if str(bad) in indexstr:
                    stats.custom = True
                    return angel()
            stats.custom = False
    if stats.custom:
        return angel()
    return PetyrBaelish()

run(sys.argv, decider)

```

# Skeleton for Python 3

Here's a skeleton for everybody who wishes to build upon. By persisting the Stats, it only ever needs to parse the last round.

It consists of two files:

* goodvsevil.py: provides infrastructure, saving/loading stats to/from file and adding the latest results each round. Six methods are intended for external use:
    + `setSaveFile(path)`:
    sets the path where the stats are saved. Must be called before run().
    + `run(argv, decider)`:
    parses the latest result, adds it to the stats, calls the decider function, correctly prints the decision to stdout, and saves the stats.
    `argv` will usually be sys.argv
    `decider` must be a function that takes a Stats object as argument and returns True for 'good', False for 'evil'.
    + `average(list, count=0)`:
    returns the average of the last `count` elements in `list`. If `count` is falsy, the entire `list` is used.
    + `angel`, `demon`, `PetyrBaelish`:
    are decider functions with the behavior their name indicates.
* goodvsevildebug.py: may be useful while developing. It can simulate rounds and print stats. It's not to be used in submissions, because it prints stuff to stdout.
`fileStats(filename)` takes the path to your save file and prints the stats it contains.

## Edit:

* non-breaking change to run() in goodvsevil.py:
run has a new parameter `suppress`, to support silent operation in goodvsevildebug.py
* new function getSaveFile() in goodvsevil.py:
returns the path to the savefile. Needed in goodvsevildebug.py.
* non-breaking changes to fileStats() and printStats() in goodvsevildebug.py:
they both have a new parameter `onlyMe` to enable short listing. fileStats() now also tries to append '.pickled' to the filename if it doesn't otherwise exist.
* non-breaking change to hostRounds() in goodvsevildebug.py:
there are two new parameters, `opponentnames` and `myname`. They are used when printing. `opponentnames` also determines the filenames for the opponents saved stats. `opponentnames` are matched to `opponentdeciders` by position. deciders without a name get named after the position where they are placed.
* hostRounds() now announces all players positions (converting them to 1-based), shows progress and timing information every 10%, and displays the final ranking (along with average and max times) when done.
* hostRounds() doesn't simply call the deciders anymore, but passes them to run(). This means that *all* deciders have a separate automatically updated save file each, and no work or data is shared between them.

Out of curiosity, I ran 1000 rounds with 29 players (1 Homer-clone with 200ms delay, 1 angel, 1 demon, 1 coward, 1 getrichquick, 1 findstreaks, 1 trendalizer, and 22 PetyrBaelishes, each on top of the goodvsevil.py infrastructure).

Average time per round was 72ms for most players, max time 220ms. Only Homer was slower, 280ms on average and 420ms max. Average time in the last 10% (across all 29) was 151ms per player/round.

That includes loading stats from file, parsing last round, updating stats, making a decision, saving stats back to file, and negligible hostRounds() overhead. It does *not* include the time to start python and load the script. It also doesn't account for the fact that run() prints the decision to stdout *before* it saves the stats to help meet timing requirements.

Here is the code I used for the experiment. Feel free to use it as a starting point if you'd like to try out my 'framework'. NOTE: if you don't like to wait half an hour or more, lower the number of rounds and/or opponents.

```
#!/usr/bin/python3
import sys
from goodvsevil import *

def decider(stats):
    'implement my decision logic here'
    import threading        #
    threading._sleep(0.2)   # please, don't do this. It's just here to prove that time measurement works.
    return True

setSaveFile('./testing.pickled')
run(sys.argv, decider)

#### everything below is to be removed before submitting. ####

rounds = 1000
from goodvsevildebug import *

class DevNull:
    def write(self, *args, **kwargs):
        pass

savefile = getSaveFile() # store the save file name
stdout = sys.stdout
sys.stdout = DevNull()   # silence during import

import coward, streakfinder, getrichquick, trendalizer  # these print stuff and change the save file

sys.stdout = stdout      # restore stdout
setSaveFile(savefile)    # restore save file name

opponents = [angel, demon, coward.decider, streakfinder.decider, getrichquick.decider, trendalizer.decider] + 22* [PetyrBaelish,]
oppnames = ['angel', 'demon', 'coward','streakfinder','getrichquick', 'trendalizer', 'PetyrBaelish1', 'PetyrBaelish2']

stats = hostRounds(rounds, decider, opponents, oppnames, '* Homer Clone *')

### NOTE that the stats object/files do not contain the decisions from the very last round.
###      printStats() and fileStats() will therefore report lower scores than hostRounds() did.
#
#printStats(stats)   # print full run info: majority decisions, player decisions and scores
#
#oppnames.remove('angel')        # we know their decisions - no need to display
#oppnames.remove('demon')
#for x in oppnames:
#    print('\n%s:' % (x,))
#    fileStats(x, onlyMe=True)   # print short info about each opponent in oppnames: position, decisions and score

```

goodvsevil.py:

```
#!/usr/bin/python3
import pickle, random

def run(argv, decider, suppress=False):
    'run an invocation. Pass argv = sys.argv, decider = function(Stats) returning boolean.'
    stats = updateStats(argv)
    decision = decider(stats)
    if not suppress:
        print('good' if decision else 'evil')
    if stats.myIndex < 0:
        stats._myDecisions.append(decision)
    with open(savefilename, "wb") as file:
        pickle.dump(stats, file=file)
    return (decision, stats)

def angel(stats=None):
    return True
def demon(stats=None):
    return False
def PetyrBaelish(stats=None):
    return random.randint(0,1)

class Streak:
    def __init__(self, good=False, length=0):
        self.good = good        # meaning depends on context
        self.length = length    # streak length in number of rounds

class Stats:
    def __init__(self):
        self.players = 0        # number of players
        self.majorityLine = []  # list of majority decisions of { True:'good', False:'evil' }
        self.playerLines = []   # list of decisions for each player of { True:'good', False:'evil' }
        self.scores = []        # list of scores for each player (3 for majority, streak.length-1 for minority)
        self.totalScores = []   # total score for each player
        self.decisionStreaks = []   # playerLines as lists of streaks
        self.winningStreaks = []    # list of streaks for each player hitting the same group of { True:majority, False:minority }
        self.majorityLineStreaks = [Streak()]   # majorityLine as a list of streaks
        self._myDecisions = []  # used in the first few rounds until I know who I am
        self.myIndex = -1       # which of the playerLines is Me?
        self.totalGood = 0      # total number of player decisions for 'good'
        self.totalEvil = 0      # total number of player decisions for 'evil'
        self.roundsGood = 0     # total number of rounds won for 'good'
        self.roundsEvil = 0     # total number of rounds won for 'evil'
        self.custom = None      # add some custom state object if you wish

savefilename = ''
def setSaveFile(path):
    global savefilename
    savefilename = path
def getSaveFile():
    return savefilename

def majorityVote(sround):
    return sround.count('1') > sround.count('0')

def isGood(char):
    return char == '1'

def average(listnums, lastcount=0):
    if lastcount:
        listnums = listnums[-lastcount:]
    if listnums:
        return sum(listnums) / len(listnums)
    return 0

def updateStats(argv):
    if not savefilename:
        raise Exception('No save file set. Please use setSaveFile(path) right after "import goodvsevil".')
    decision = 0
    lastround = ''
    stats = None
    firstround = (len(argv) < 2)
    if firstround:
        stats = Stats()
    else:
        with open(savefilename, "rb") as file:
            stats = pickle.load(file)
        maxi = len(stats.playerLines) - 1
        lastround = argv[1].split(',')[-1]
        # record majority:
        majvote = majorityVote(lastround)
        if majvote:
            stats.roundsGood += 1
        else:
            stats.roundsEvil += 1
        if stats.majorityLine and (stats.majorityLine[-1] == majvote):
            stats.majorityLineStreaks[-1].length += 1
        else:
            if stats.majorityLineStreaks[-1].length:
                stats.majorityLineStreaks.append(Streak())
            stats.majorityLineStreaks[-1].length = 1
            stats.majorityLineStreaks[-1].good = majvote
        stats.majorityLine.append(majvote)
        # record player histories:
        for i in range(len(lastround)):
            good = isGood(lastround[i])
            if i > maxi:
                stats.playerLines.append([])
                stats.scores.append([])
                stats.totalScores.append(0)
                stats.decisionStreaks.append([Streak()])
                stats.winningStreaks.append([Streak()])
            guessedright = (majvote == good)
            if stats.playerLines[i]:
                if good != stats.playerLines[i][-1]:
                    stats.decisionStreaks[i].append(Streak())
                if guessedright != stats.winningStreaks[i][-1].good:
                    stats.winningStreaks[i].append(Streak())
            stats.playerLines[i].append(good)
            stats.decisionStreaks[i][-1].length += 1
            stats.winningStreaks[i][-1].length += 1
            stats.decisionStreaks[i][-1].good = good
            stats.winningStreaks[i][-1].good = guessedright
            stats.scores[i].append(3 if guessedright else (stats.winningStreaks[i][-1].length - 1))
            stats.totalScores[i] += stats.scores[i][-1]
            if good:
                stats.totalGood += 1
            else:
                stats.totalEvil += 1
        if stats.myIndex < 0:
            # try to find myself:
            candidates = []
            for i in range(len(stats.playerLines)):
                fits = True
                for k in range(len(stats._myDecisions)):
                    if stats._myDecisions[k] != stats.playerLines[i][k]:
                        fits = False
                        break
                if fits:
                    candidates.append(i)
            if len(candidates) == 1:
                stats.myIndex = candidates[0]
        if not stats.players:
            stats.players = len(stats.playerLines)
    return stats

```

goodvsevildebug.py:

```
#!/usr/bin/python3
import os, time
from goodvsevil import *

def randomRounds(players, rounds, decider=PetyrBaelish):
    'host a number of rounds against a number of PetyrBaelishes'
    return hostRounds(rounds, decider, (players-1) * [PetyrBaelish,])

def hostRounds(rounds, decider=PetyrBaelish, opponentdeciders=[], opponentnames=[], myname='* me *'):
    'host a number of rounds against a list of opponents, part of which may have names'
    opponentdeciders = opponentdeciders[:]  # copy lists because we'll alter them
    opponentnames = opponentnames[:]
    increment = rounds / 10  # how many rounds are 10%?
    filename = getSaveFile()
    s = ''
    temps = ''
    stats = None
    deciders = []
    names = []
    players = len(opponentdeciders)
    if (players % 2):
        opponentdeciders.append(PetyrBaelish)
        players += 1
    mypos = random.randint(0,players)
    print('my position: %d of %d' % (mypos+1, players+1))
    print()
    players += 1
    found = players * [False,]
    decisions = players * [False,]
    scores = players * [0,]
    streaks = players * [None,]
    times = players * [None,]
    # randomly arrange players:
    print('Positioning:\n------------')
    for i in range(players):
        if i == mypos:
            deciders.append(decider)
            names.append(myname)
        else:
            x = random.randint(0, len(opponentdeciders)-1)
            randchoice = opponentdeciders[x]
            opponentdeciders.remove(randchoice)
            deciders.append(randchoice)
            if opponentnames and (len(opponentnames) > x):
                name = opponentnames[x]
                names.append(name)
                opponentnames.remove(name)
            else:
                names.append(str(i+1))
        print('%02d: %s' % (i+1, names[i]))
    print()
    print('Run:\n----')
    t0 = time.time()
    for r in range(rounds):
        temps = ''
        tstart = time.time()
        for i in range(players):
            # set a different save file for each player:
            if i == mypos:
                setSaveFile(filename)
            else:
                setSaveFile('./%s.pickled' % (names[i],))
            # call the player, with or without argv[1]:
            if r == 0:
                (decision, st) = run([None], deciders[i], suppress=True)
                times[i] = []
            else:
                (decision, st) = run([None, s], deciders[i], suppress=True)
            # remember everything we need to score the final round:
            decisions[i] = decision
            if r > 0:
                scores[i] = st.totalScores[i]
                streaks[i] = st.winningStreaks[i][-1]
            # prepare next round's argv[1]:
            temps += '1' if decision else '0'
            # check if player has determined its position this round:
            if (not found[i]) and (st.myIndex >= 0):
                found[i] = True
                if i == mypos:
                    print('*** Found myself in position %d after round %d.' % (st.myIndex+1, r))
                else:
                    print(" '%s' found itself in position %d after round %d." % (names[i], st.myIndex+1, r))
            if i == mypos:
                stats = st
            # measure time:
            tend = time.time()
            times[i].append(tend - tstart)
            tstart = tend
        # finish preparation of next argv[1]:
        if r != 0:
            s += ','
        s += temps
        # Inform about progress in steps of ~10%:
        if 1 > ((r+1) % increment): # 1> instead of 0== because increment is float
            print('%d%% - t0 + %f' % (10*(r+1)/increment, time.time()-t0))
    print()
    # score the last round:
    majority = (players/2) < sum(decisions)
    maxtimes = players * [0,]
    for i in range(players):
        if decisions[i] == majority:
            scores[i] += 3
        elif not streaks[i].good:   # minority streak
            scores[i] += streaks[i].length
        maxtimes[i] = max(times[i])
        times[i] = average(times[i])
    scores = list(zip(scores, names, times, maxtimes))
    scores.sort(key = lambda x: x[1]) # sort by name, so that equal scores will appear in lexical ordering
    scores.sort(key = lambda x: x[0], reverse=True) # sort by score
    print('Ranking:\n--------')
    for x in scores:
        print('%d - %s (avg time %f, max %f)' % x)
    print()
    print('hosted %d rounds with %d players in %f seconds.' % (rounds, players, time.time()-t0))
    print()
    return stats

def fileStats(filename, onlyMe = False):
    'load a Stats object from file and print relevant info.'
    if not os.path.exists(filename):
        if os.path.exists(filename + '.pickled'):
            filename += '.pickled'
    with open(filename, 'rb') as file:
        printStats(pickle.load(file), onlyMe)

def printStats(stats, onlyMe=False):
    "print relevant info from the passed Stats object. if onlyMe, don't print majority or opponents."
    playerpaths = ''
    playerguessing = ''
    players = len(stats.playerLines)
    majoritypath = ''
    if onlyMe:
        score = 0
        if stats.myIndex >= 0:  # I found myself at some point, use playerLines[myIndex]
            print('Position: %d / %d' % (stats.myIndex+1, stats.players))
            for i in range(len(stats.playerLines[stats.myIndex])):
                dec = stats.playerLines[stats.myIndex][i]
                majoritypath += '1' if dec else '0'
                playerguessing += '1' if dec == stats.majorityLine[i] else '0'
            score = stats.totalScores[stats.myIndex]
        else:                   # I never found myself, use _myDecisions
            print('Position: unknown')
            good = False
            streak = 0
            for i in range(len(stats._myDecisions)-1):
                dec = stats._myDecisions[i]
                majoritypath += '1' if dec else '0'
                if good == (dec == stats.majorityLine[i]):
                    if good:
                        score += 3
                    else:
                        score += streak
                    streak += 1
                else:   # change between minority/majority
                    good = (dec == stats.majorityLine[i])
                    streak = 1
                    if good:
                        score += 3
                playerguessing += '1' if good else '0'
        print('- %s\n  %s (%d)' % (majoritypath, playerguessing, score))
        return
    for i in range(players):
        decs = '- '
        ress = '- '
        pscore = 0
        for decision in stats.playerLines[i]:
            decs += '1' if decision else '0'
        for streak in stats.winningStreaks[i]:
            ress += streak.length * ('1' if streak.good else '0')
        ress += ' (%d)' % stats.totalScores[i]
        if i == stats.myIndex:
            ress = '* %s *' % ress[2:]
            decs = '* %s *' % decs[2:]
        playerpaths += decs + '\n'
        playerguessing += ress + '\n'
    for dec in stats.majorityLine:
        majoritypath += '1' if dec else '0'
    if stats.myIndex < 0:
        majoritypath += '\n\nMy decision line:\n-----------------\n- '
        for dec in stats._myDecisions:
            majoritypath += '1' if dec else '0'
    print('''
Position:
---------
%d / %d

Majority decision line:
-----------------------
- %s

Decision lines:
---------------
%s
Alignment with majority (Score):
--------------------------------
%s''' % (stats.myIndex+1, players, majoritypath, playerpaths, playerguessing[:-1]))

```
> 1 votes

# Answer
The probability gambler, Python

This guy checks which side has gotten most total votes and chooses that side.

```
import sys
 good, evil = 0, 0
 if len(sys.argv) == 1: print "good"
 else:
     for round in sys.argv[1:]:
         for player in round:
             if player == "0":
                 evil += 1
             elif player == "1":
                good += 1
     if good > evil: print "good"
     else: print "evil"

```

Run as

```
 python probabilitygambler.py arg1 arg2...
```
> 1 votes

# Answer
## Tommy

This might not be pinball but I still postulate you can play while being deaf and blind. The devil helped him not be dumb, however, for the first few votes.

```
package Humans;

public class Tommy extends Human {
public String takeSides(String history) {
    int players = 0;
    while(history.length()>players && history.charAt(history.length()-players-1) != ',')   {
        players++;
    }

    String NotSoSecret = "0000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111101010101010101010101010101010101010101010101010101010101010101010101010101010010010010010010010010010010010010010010010010010010010010010010010010010011011011011011011011011011011011011011011011011011011011010110110110110110100010001000100010001000100010001000100010001000100010001000100010001000100010001110111011101110111011101110111011101110111011101110111011101110111101110111011100000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111010101010101010101010101010101010101010101010101010101010101010101010101010100100100100100100100100100100100100100100100100100100100100100100100100100110110110110110110110110110110110110110110110110110110110101101101101101101000100010001000100010001000100010001000100010001000100010001000100010001000100011101110111011101110111011101110111011101110111011101110111011101111011101110111";

    if (NotSoSecret.charAt((history.length()+1)/(players+1))==1){
        return "good";
    }

    return "evil";

}}

```
> 1 votes

# Answer
**ConspiracyTheoristBot**

This Tin-Foil cap toting crackpot uses the input to search for government conspiracies. If he finds one, then *obviously* the government has been subverting the will of the majority, and the minority is the safest place to be. Otherwise, he hides in the crowd of the majority.

```
public class ConspiracyTheorist extends Human{
    public String takeSides(String input) {
        if (theAnswer(input) || terror(input)
                || beastly(input) || aliens(input) //number stuff
                || findMeaning(input, "alien") || findMeaning(input, "death")
                || findMeaning(input, "jfk") || //Keywords of Conspiracy
                findMeaning(input, "plane") || findMeaning(input, "god")
                || findMeaning(input, "devil") ||
                findMeaning(input, "blackhelecopter"))
                      return printMin(input);
        return printMax(input);
    }

    //prints the current overall minority
    public String printMin(String input) {
        if (input.split("1").length > input.split("0").length) return "evil";
        return "good";
    }

    //prints the current overall majority
    public String printMax(String input) {
        if (input.split("1").length > input.split("0").length) return "good";
        return "evil";
    }

    //If the ultimate answer shows up in the input,
    //obviously the government is up to something and we
    //should join the minority
    public boolean theAnswer(String input) {
        return numerologist(input, "42");
    }

    //Area 51? Its the government! Run!
    public boolean aliens(String input) {
        return numerologist(input, "51");
    }

    //They did plan it, I'm sure of it.
    public boolean terror(String input) {
        return numerologist(input, "9") ||
                numerologist(input, "11") ||
                numerologist(input, "911");
    }

    //The end times are upon us!
    public boolean beastly(String input) {
        return numerologist(input, "666");
    }

    //if we can find some hidden words in the input,
    //obviously the government is up to something and we
    //should join the minority
    public boolean findMeaning(String input, String lookFor) {
        //split the input into bytes
        String[] bit8 = input.replace(",", "").split("(?<=\\G.{8})");
        //convert from binary to string
        String newWord = "";
        for (String b : bit8) {
            char c = (char) (int) Integer.valueOf(b, 2);
            if (Character.isLetterOrDigit(c)) newWord += c;
        }
        if (newWord.toLowerCase().contains(lookFor.toLowerCase())) return true;
        return false;
    }

    // The number crunching behind the tin foil hat
    public boolean numerologist(String input, String num) {
        String[] comcount = input.split(",");
        if ((comcount.length + "").contains(num)) return true;
        String[] onecount = input.split("1");
        if ((onecount.length + "").contains(num)) return true;
        String[] nullcount = input.split("0");
        if ((nullcount.length + "").contains(num)) return true;
        return false;
    }
}

```
> 1 votes

# Answer
# Monkey With a Typewriter

Somebody let him loose on my computer! He's not quite quick enough at typing, so he guesses after .9s seconds...

```
import time
import random

startTime = time.time()
letters = 'abcdefghijklmnopqrstuvwxyz'

typed = ""
it = 0

while (1):
    typed += random.choice(letters)
    outputStr = typed[-4:]

    # Oook!
    if (outputStr == "good" or outputStr == "evil"):
        break

    # Oook! OOOK! OOOOOOK!
    if (typed[-7:] == "bannana"):
        outputStr = "bannana"
        break

    if (it % 100 == 0):
        # Eeek!
        currentTime = time.time()
        if (currentTime - startTime > .9):
            outputStr = "good" if random.random() < .5 else "evil"
            break

    it += 1

print outputStr

```

python MonkeyWithATypeWriter.py
> 0 votes

# Answer
# Logical

My code chooses its side by probabilities or by random if there isn't enough data.

C++:

```
#include <iostream>
#include <time.h>

using namespace std;

int main(int argc, char* argv2[])
{
    srand(time(0));
bool evil = false;
if(argc == 1) {
    if(rand() % 2 == 1) evil = true;
} else {

    char* argv = argv2[1];
    int length = strlen(argv);
    int rounds = 0, goods[1000], evils[1000];

    for(int i = 0; i < 1000; i++){

        goods[i] = 0;
        evils[i] = 0;
    }

    for(int i = 0; i < length; i++) {

        if(argv[i] == ',') {
            rounds++;
        } else if(argv[i] == '1') {
            goods[rounds]++;
        } else {
            evils[rounds]++;
        }
    }
    rounds++;
    cout << rounds << endl;
    if(rounds < 2) {

        if(rand() % 2 == 1) evil = true;
    } else {

        int changes[10]; //0-4 no change, 5-9 change
        int changeBorders[5], index = 0, difference = 0;
        fill_n(changes, 10, 0);
        fill_n(changeBorders, 5, 0);
        changeBorders[0] = (goods[0]+evils[0])/6;
        changeBorders[1] = changeBorders[0]*2;
        changeBorders[2] = changeBorders[0]*3;
        changeBorders[3] = changeBorders[0]*4;
        changeBorders[4] = changeBorders[0]*5;
        for(int i = 0; i < rounds-1; i++) {

            index = 0;

            if((goods[i] > evils[i] && goods[i+1] < evils[i+1]) || (goods[i] < evils[i] && goods[i+1] > evils[i+1])) index += 5;
            difference = abs(goods[i]-evils[i]);
            if(difference < changeBorders[0]) {//do nothing
            } else if(difference < changeBorders[1]) index++;
            else if(difference < changeBorders[2]) index += 2;
            else if(difference < changeBorders[3]) index += 3;
            else if(difference < changeBorders[4]) index += 4;
            changes[index]++;
        }

        difference = abs(goods[rounds-1]-evils[rounds-1]);
        if(difference < changeBorders[0]) index = 0;
        else if(difference < changeBorders[1]) index = 1;
        else if(difference < changeBorders[2]) index = 2;
        else if(difference < changeBorders[3]) index = 3;
        else if(difference < changeBorders[4]) index = 4;

        if(goods[rounds-1] > evils[rounds-1]) evil = false;
        else evil = true;

        if(changes[index] == 0 && changes[index+5] == 0) {
            if(rand() % 2 == 1) evil = true;
        } else if(changes[index+5] == 0) evil = !evil;
        else if(changes[index] == 0) { //do nothing
        } else if(changes[index] < changes[index+5]) evil = !evil;
    }
}

cout << (evil ? "evil" : "good") << endl;

return 0;

```

}

EXE: http://www.filedropper.com/goodandevil

Usage: Windows command line with "goodandevil.exe \[vote history here\]".
> 0 votes

# Answer
# FBI (Ruby)

```
print %w&good evil&[ARGV.map{|w|w.each_char.reject{|r|%r{,}=~r}.shuffle.pop.to_i}[%*#{Math.sqrt(5/2)}*.to_i-1]]

```

The FBI uses codes to hide intent. What it dose is:

> Something you can find out yourself! Why would I go to this extent to hide the meaning of code then tell you what it means in a spoiler right after?
> 0 votes

---
Tags: king-of-the-hill
---