El bien contra el mal

112

Resultados - 19 de julio de 2014

¡El actual Rey de la Colina es Mercenario por el usuario Fabigler ! ¡Sigue enviando entradas y sácalo de su trono!

Haga clic aquí para ver el marcador.

Se incluyeron los programas presentados el 19 de julio de 2014 o antes. Todas las demás presentaciones se incluirán en futuros ensayos. Los nuevos resultados deben publicarse alrededor del 9 de agosto, de modo que tenga mucho tiempo.


Ilustración dibujada por hermano Ilustrado por Chris Rainbolt, mi hermano y un recién graduado de Savannah College of Art and Design

Introducción

Los ángeles y los demonios luchan y, como siempre, usan la tierra como campo de batalla. Los humanos están atrapados en el medio y se ven obligados a tomar partido. Una fuerza neutral desconocida recompensa a aquellos que constantemente luchan por el bando perdedor.

El juego

En cada prueba, se emparejará pseudoaleatoriamente y luego se barajará con entre 20 y 30 envíos más. Cada prueba constará de 1000 rondas. Cada ronda, se le pasará una entrada y se espera que produzca salida. Su salida será registrada y calificada. Este proceso se repetirá 1000 veces.

Entrada

Recibirá un único argumento que representa los votos pasados ​​de cada jugador. Las rondas están delimitadas por comas. A 0representa a un jugador que se puso del lado de Evil en esa ronda. A 1representa a un jugador que se puso del lado del Bien. Dentro de una prueba, los jugadores siempre estarán en el mismo orden. Se incluirá su propio voto, pero no se identificará explícitamente. Por ejemplo:

101,100,100

En este ejemplo, se han completado tres rondas y tres jugadores están compitiendo. El jugador uno siempre se puso del lado del bien. El jugador dos siempre se puso del lado del Mal. El jugador tres cambió de Bueno en la ronda 1 al Mal en las rondas 2 y 3. Uno de esos jugadores fuiste tú.

Salida

Envíos de Java

  • Devuelve la cadena goodsi quieres ponerte del lado de Good.
  • Devuelve la cadena evilsi quieres ponerte del lado de Evil.

Envíos no Java

  • Envíe la cadena gooda stdout si desea ponerse del lado de Good.
  • Salida de la cadena evila stdout si desea ponerse del lado de Evil.

Si su programa genera o devuelve algo más, genera una excepción, no se compila o tarda más de un segundo en generar algo en esta máquina exacta , entonces será descalificado.

Puntuación

Los puntajes se publicarán en una hoja de cálculo de documentos de Google para una fácil visualización tan pronto como pueda compilar todas las entradas actuales. No se preocupe, ¡seguiré ejecutando pruebas durante el tiempo que ustedes sigan enviando programas!

  • Recibe 3 puntos por ponerse del lado de la mayoría durante una ronda.
  • Usted recibe n - 1 puntos por ponerse del lado de la minoría durante una ronda, donde n es el número de veces consecutivas que se puso del lado de la minoría.

Su puntaje será la mediana de 5 ensayos. Cada prueba consta de 1000 rondas.

Entregables

Envíos no Java

Debe enviar un título único, un programa y una cadena de línea de comandos de Windows que ejecutará su programa. Recuerde que se puede agregar un argumento a esa cadena. Por ejemplo:

  • python Angel.py
    • Tenga en cuenta que este no tiene argumentos. Esta es la primera ronda! Prepárate para esto.
  • python Angel.py 11011,00101,11101,11111,00001,11001,11001

Envíos de Java

Debe enviar un título único y una clase Java que amplíe la clase humana abstracta escrita a continuación.

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

Pruebas

Si desea probar su propia presentación, siga las instrucciones aquí .

Notas adicionales

Puede enviar tantas presentaciones diferentes como desee. Las presentaciones que parecen estar coludiendo serán descalificadas. El autor de este desafío será el único juez en ese asunto.

Se creará una nueva instancia de su programa o clase Java cada vez que se solicite. Puede conservar la información escribiendo en un archivo. No puede modificar la estructura o el comportamiento de nada, excepto su propia clase.

Los jugadores serán barajados antes de que comience la prueba. Demon y Angel participarán en cada prueba. Si el número de jugadores es par, Petyr Baelish también se unirá. Demon lucha por Evil, Angel for Good y Petyr Baelish elige un lado pseudoaleatorio.

Perno de lluvia
fuente
2
Comentarios depurados, ya que eran obsoletos y a petición de OP. Notifíqueme cualquier comentario que deba ser recuperado.
Pomo de la puerta
77
Woah, OP cambia su nombre de usuario. Ok, entonces, ¿cuándo se mostrará el resultado?
justhalf
66
@ Rainbolt ¡Este debe ser un trabajo increíble, ejecutar este desafío! La razón de esta cantidad de atención es la simplicidad del protocolo y las reglas, lo que lo hace accesible al tiempo que permite entradas simples y funcionales . TL; DR: ¡Tu desafío es demasiado bueno! : D
tomsmeding
3
@dgel Publicaré los datos brutos, superiores, inferiores, promedios y tal vez un gráfico de líneas para que podamos ver quién fue mejor a medida que avanzó la competencia.
Rainbolt
66
Uno de los pods terminó con 10 entradas que votaron de la misma manera cada vez. En consecuencia, dos usuarios terminaron con puntajes perfectos o "una ronda por debajo de perfectos" de alrededor de 450,000. Las mismas entradas obtuvieron alrededor de 1900 en otros ensayos. El puntaje promedio es cercano a 2000. Debido al desequilibrio extremo en los resultados, decidí que un número más significativo sería una mediana. Edité el desafío para que después de 5 pruebas, el ganador sea la presentación con la mediana más alta. Si alguien piensa que pasar de la media a la mediana es injusto o de lo contrario es una mala elección, comente.
Rainbolt

Respuestas:

11

El mercenario

Siempre se alinea con el que pagó más dinero la última ronda.

Teniendo en cuenta que las buenas personas ganan estadísticamente más.

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";
        }
    }
}
fabigler
fuente
2
Esta es la segunda publicación que dice algo sobre el dinero. ¿Me estoy perdiendo una referencia o algo?
Rainbolt
Es cierto, pero este tipo es un bastardo aún más malvado. Abandonando a sus amigos cada turno, solo por dinero.
fabigler
A su declaración de switch le faltaba una declaración de devolución para el caso predeterminado, lo que hace que no se compile. Agregué uno al azar.
Rainbolt
44
¡Felicidades, rey de la colina! No entiendo cómo gana esta entrada. ¿Le importa agregar una explicación, ahora que tiene una recompensa de 300 reputación asociada?
Rainbolt
44
Posiblemente un error, o entendí mal los comentarios y la descripción, pero el Mercenario en realidad no hace lo que estaba destinado a hacer. Excepto por la primera ronda aleatoria, siempre estará del lado del mal a menos que menos de 1/6 de las personas votaron por el mal en la ronda anterior.
jaybz
39

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

Simplemente va con la minoría de la última ronda, solo porque todo lo demás es convencional.

Corre como

ruby hipster.rb
Martin Ender
fuente
30

Petyr Baelish

Nunca se sabe de qué lado está Petyr Baelish.

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

Esta entrada solo se incluirá si el número de jugadores es par. Esto asegura que siempre habrá una mayoría.

Perno de lluvia
fuente
28
Del lado de Petyr Baelish, obviamente.
Cthulhu
2
@Kevin Siempre vence a la mayoría de los bots. Suele tener un puntaje de 27.
cjfaure
3
@Kevin Esta entrada fue presentada por el autor del desafío. No estaba destinado a hacerlo bien. Existe para asegurarse de que siempre habrá una mayoría, porque con un número par de jugadores, podría haber un empate.
Rainbolt
44
¿Por qué Dios, por qué este tiene más votos? Simplemente no es justo .
tomsmeding
3
@tomsmeding No. Es una cita de Game of Thrones lol.
Rainbolt
29

C ++, el metacientífico

Este hace esencialmente lo mismo que The Scientist, pero no opera en rondas en su conjunto sino en jugadores individuales. Intenta asignar una ola (o una función constante) a cada jugador por separado y predice su movimiento en la siguiente ronda. A partir de la predicción redonda resultante, The Meta Scientist elige el lado que parece tener una mayoría.

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

Si desea activar las declaraciones de depuración, cambie la lectura de la línea #if 0 a #if 1.

Compile con g++ -O3 -std=c++0x -o MetaScientist MetaScientist.cpp(no necesita advertencias, así que no -Wall) y ejecute con MetaScientist.exe(posiblemente incluyendo el argumento, por supuesto). Si preguntas muy bien, puedo proporcionarte un ejecutable de Windows.

EDITAR: Al parecer, la versión anterior se quedó sin tiempo alrededor de 600 rondas en el juego. Esto no debería hacer eso. Su consumo de tiempo está controlado por la #define WINDOW (...)línea, más es más lento pero mira más atrás.

tomsmeding
fuente
2
Humildemente te sugiero que intentes elegir el bando perdedor. Si puede adivinar correctamente de manera consistente, obtendrá más de 3 puntos por ronda.
Kevin
1
@Kevin Eso es cierto, pero pensé que podría adivinar el lado equivocado con bastante rapidez, y debes adivinar correctamente el lado perdedor más de siete veces seguidas para obtener una mejora sobre siempre tener la mayoría correcta. Aunque podría cambiarlo.
tomsmeding
1
@Kevin Además, primero me gustaría ver cómo funcionan (Científico y Metacientífico) cuando Rusher nos consigue un marcador este fin de semana, como lo indicó en los comentarios al OP. Rusher, lo siento, pero soy demasiado vago para compilar todas las cosas ... :)
tomsmeding
3
¡Sin preocupaciones! Probablemente no sea seguro ejecutar estos de todos modos. Solo déjame fastidiar mi máquina con el código escrito por 50 extraños en Internet.
Rainbolt
1
@Kevin ¡Pero eso es MUCHO ! Puedo, de hecho, pero no me gusta. Veré cómo les va.
tomsmeding
26

Ángel

El jugador más puro de todos.

Programa

print "good"

Mando

python Angel.py
Perno de lluvia
fuente
22
Python es un buen lenguaje. Parece natural que el Ángel lo use.
jpmc26
23
¿Puedo recordar a la gente que un Python es una serpiente? Una serpiente
Sr. Lister el
3
@MrLister ¿Puedo recordarle que Lucifer fue un gran ángel antes de que Dios lo echara del cielo?
Zibbobz
1
@Zibbobz Sí ... lástima que se hayan caído. Podrían haber logrado tanto juntos.
Sr. Lister
24

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

En el Libro 7, The Atlantis Complex , Artemis Fowl contrajo una enfermedad psicológica (llamada Atlantis complex) que lo obligó a hacer todo en múltiplos de 5 (hablar, acciones, etc.). Cuando no pudo hacerlo en un múltiplo de 5, entró en pánico. Básicamente hago eso: ver si el bien o el mal (sesgo intencional) es divisible por 5, si ninguno lo es, entonces me asusto y veo cuál fue mayor y corro con eso o me asusto aún más y elijo al azar.

Kyle Kanos
fuente
44
Cuando leí Artemis Fowl en la secundaria, solo existían dos libros. Es agradable ver que ahora hay siete, y que Disney está convirtiendo en una película.
Rainbolt
1
En realidad hay 8 libros.
Kyle Kanos
77
Cuantos más, mejor (a menos que esté leyendo La rueda del tiempo)
Rainbolt
1
Y te olvidaste break;en tu switch.
johnchen902
1
@ johnchen902, @ Manu: No tengo mucha experiencia en Java (uso Fortran90 + y solo veo Java aquí), de ahí mis errores. Los arreglaré cuando llegue a la oficina en una hora.
Kyle Kanos
19

Disparnumerofóbico

Los números impares son aterradores.

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";
    }
}
seudónimo117
fuente
17
El comentario me hizo reír / resoplar.
phyrfox
17

Linus, Ruby

Busca confundir a los analistas rompiendo siempre el patrón .

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

Guardar como linus.rby correr conruby linus.rb

histocrat
fuente
16

El mochilero

Determina a un jugador que ha elegido la minoría correspondiente más y elige su último voto.

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

La multitudSeguidor

Determina a un jugador que ha elegido la mayoría coincidente y elige su último voto.

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;
    }
}
Angelo Fuchs
fuente
Programa muy limpio!
Rainbolt
Vaya, creo que puedo haber copiado tu programa en un idioma diferente.
PyRulez
@Rusher Actualicé el código y me gustaría agregar esto como dos entradas, una con goWithMajority = truey otra donde está false. ¿Está bien, o necesito agregar un segundo BackPacker para esto?
Angelo Fuchs
@AngeloNeuschitzer Edité esta publicación. De esta manera, no olvidaré agregar ambas presentaciones. Le sugiero que cambie el nombre realmente poco creativo que le di, y tal vez agregue una descripción a ambos si lo desea.
Rainbolt
1
@Rainbolt Me gusta más tu FrontPacker, en realidad. Lol'd
tomsmeding
15

Adivino

Esto sigue siendo un trabajo en progreso. Aún no lo he probado. Solo quería ver si el OP cree que rompe las reglas o no.

La idea es simular la siguiente ronda ejecutando a todos los demás participantes varias veces para obtener una probabilidad del resultado y actuar en consecuencia.

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

}
Andris
fuente
Si su bot ejecuta todos los otros bots cada turno antes de responder, ¿no tomará más de 1s para responder?
plannapus
@plannapus Supongo que la suposición con este bot es que todos los demás se equivocarán por precaución y evitarán cualquier cosa cerca de 1 segundo de espera. Estoy pensando que puede valer la pena enviar e ingresar que consiste en una espera de 0.9 segundos, antes de regresar "bueno", solo para meterse con él. En realidad, SBoss me ha ganado: D
scragar
Yahhh! Entonces tendría que poner en la lista negra ese bot en mi código. Eso sería frustrante ... También con diferentes entradas en diferentes entornos como Python o Perl, la carga repetida del intérprete podría ser suficiente para llevar este código por encima del límite de tiempo.
Andris
16
Si alguien más hace lo mismo que esto, obtienes un bucle infinito.
Brilliand
44
La presentación expiró. Adjunté un generador de perfiles, y pasé casi medio segundo llamando a algunas presentaciones. Sin embargo, al menos funciona, así que felicidades por eso.
Rainbolt
15

C ++, el científico

Éste intenta, con el historial de lo que la mayoría eligió por ronda wave( majority()da la opción de la mayoría en una ronda), ajustar una onda a los datos, de longitud de onda 2*periody fase phase. Por lo tanto, dado 0,1,1,1,0,1,0,1,1,1,0,0,0,1,0que selecciona period=3, phase=5( maxat=={3,5}): sus puntajes se vuelven 9 3 11 5 5 3 5 7 9 7 7 7 7 7 7. Se repite en todos los períodos posibles y si, para ese período, el puntaje es más alto que el máximo actual, almacena{period,phase} para lo que ocurrió.

Luego extrapola la onda encontrada a la siguiente ronda y toma la mayoría pronosticada.

#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 con g++ -O3 -std=c++0x -o Scientist Scientist.cpp(no necesita advertencias, así que no -Wall) y ejecute conScientist.exe(posiblemente incluyendo el argumento, por supuesto). Si preguntas muy bien, puedo proporcionarte un ejecutable de Windows.

Ah, y no te atrevas a jugar con el formato de entrada. Hará cosas extrañas de lo contrario.

EDITAR: Al parecer, la versión anterior se quedó sin tiempo alrededor de 600 rondas en el juego. Esto no debería hacer eso. Su consumo de tiempo está controlado por la #define WINDOW (...)línea, más es más lento pero mira más atrás.

tomsmeding
fuente
8
Descargar ejecutables escritos por más de sesenta extraños en Internet parece una mala idea.
Rainbolt
@Rusher Estoy totalmente de acuerdo. Si quiere problemas, ese es el primer paso en la guía "para tontos". Sin embargo, mi oferta se mantiene :)
tomsmeding
2
Tengo este para compilar (y competir) bien.
Rainbolt
14

Code Runner

Entonces, para hacer las cosas interesantes, creé un script para descargar automáticamente el código de cada respuesta publicada, compilarlo si es necesario y luego ejecutar todas las soluciones de acuerdo con las reglas. De esta manera, las personas pueden verificar cómo les va. Simplemente guarde este script en run_all.py (requiere BeautifulSoup) y luego:

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

Unas pocas cosas:

  1. Si desea agregar soporte para más idiomas o, alternativamente, eliminar el soporte para algunos, consulte def submission_type(lang).
  2. Ampliar el script debería ser bastante fácil, incluso para los idiomas que requieren compilación (ver CPPSubmission). El tipo de idioma se toma de la etiqueta del metacódigo < !-- language: lang-java -- >, así que asegúrese de agregarlo si desea que se ejecute su código (Elimine los espacios adicionales antes y después de <>). ACTUALIZACIÓN : ahora hay una inferencia extremadamente básica para tratar de detectar el idioma si no está definido.
  3. Si su código no se ejecuta o no termina dentro del tiempo asignado, se agregará blacklist.texty se eliminará de las futuras pruebas automáticamente. Si corrige su código, simplemente elimine su entrada de la lista negra y vuelva a ejecutarla get,

Idiomas admitidos actualmente:

 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
}

Sin más preámbulos:

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
Qué mundo
fuente
¿Por qué no hay lenguaje Fortran ?
Kyle Kanos
@KyleKanos: agregué soporte para ello, actualizaré el código en breve.
WhatAWorld
¡Hurra! Yo (más o menos) trabajé duro en mi presentación de Fortran y Rusher no puede hacer que funcione, así que me gustaría que alguien lo haga :)
Kyle Kanos
1
@Rusher: Estoy de acuerdo con PeterTaylor en este: el resaltado de sintaxis como la única edición sugerida debe ser rechazada. Las ediciones deben usarse para correcciones sustanciales , no cosas menores.
Kyle Kanos
1
Te mereces el representante para esto, pero dado que esto no es exactamente una respuesta a la pregunta (y probablemente podría beneficiarse de que la comunidad agregue cosas para otros idiomas), creo que técnicamente debería ser un wiki de la comunidad.
Martin Ender
13

La mente hermosa, rubí

Toma su decisión basándose en patrones de importancia cuestionable en la representación de bits de la última ronda

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

Corre como

ruby beautiful-mind.rb
Martin Ender
fuente
13

Piusticioso, Lua

Un programa supersticioso que cree en signos y maravillas.

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

ejecutarlo con:

lua Piustitious.lua

seguido de la entrada.

AndoDaan
fuente
11

Los winchesters

Sam y Dean son buenos (la mayoría de las veces).

package Humans;

public class TheWinchesters extends Human {

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

}
CommonGuy
fuente
¿Estás seguro de cuál 9:1es la proporción correcta? ¿Quizás deberíamos hacer un poco de minería de datos y obtener una relación más precisa?
recursion.ninja
1
@awashburn Empecé a ver Supernatural hace 2 meses (ahora atascado en la temporada 9) y me 9:1parece bien;)
CommonGuy
10

Estadístico

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";
    }
}
Inmerecido
fuente
55
Esa segunda última línea es increíble
cjfaure el
55
@Undeserved en lugar de Math.ceil(Math.random()-Math.random())usted también puede hacer solo Math.round(Math.random()).
tomsmeding
10

R, un bot algo bayesiano

Use la tabla de frecuencias para cada usuario como la probabilidad previa de la salida de otros usuarios.

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

Se invoca usando Rscript BayesianBot.Rseguido de la entrada.

Editar : solo para aclarar lo que está haciendo, aquí hay un paso a paso con la entrada de ejemplo:

> 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

Luego, la línea que comienza por result<-, para cada jugador, elige aleatoriamente 0 o 1 usando esta última tabla como pesos (es decir, para el jugador 1, la probabilidad de elegir 0 es 2/7, de elegir 1 5/7, etc.). Elige un resultado para cada jugador / columna y finalmente devuelve el número que terminó siendo el más común.

plannapus
fuente
10

suizo

Siempre mantiene la neutralidad. Condenado a nunca ganar.

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?
    }
}
fabigler
fuente
¡No escribí esto!
Rainbolt
Esa es la ironía. La neutralidad nunca gana
fabigler
2
@Rusher ah lo tengo ahora: D
fabigler
1
Ni siquiera se compila: falta un punto y coma.
Paŭlo Ebermann
9

HAL 9000

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

Editar: tal vez esto sea más adecuado para HAL 9000, ¡pero tenga cuidado! Es muy malvado Recomiendo cdvaciar el directorio antes de ejecutarlo.

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

¡Esto elimina un archivo de cwdcada invocación!

Invocación no tan obvia:

En M $

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

D:>hal_9000.pl
evil

En * 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 ~]$
core1024
fuente
Debe proporcionar un comando que pueda usarse para ejecutar su programa. Consulte la sección "Entregables" del desafío para obtener más información.
Rainbolt
@Rusher Done;)
core1024
9

Voluntad de la mayoría

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']))

Guárdelo como WotM.py, ejecute como python3 WotM.pyseguido por la entrada.

Un programa simple, solo para ver cómo funcionará. Va con lo que la mayoría dijo la última vez, o al azar.

isaacg
fuente
Debe proporcionar un comando que pueda usarse para ejecutar su programa. Consulte la sección "Entregables" del desafío para obtener más información.
Rainbolt
Maldita sea, eso hace que el mío sea un duplicado. : D Cambió la mía a minoría.
Martin Ender
@Rusher Agregó el comando. ¿Eso que estabas buscando?
isaacg
@isaacg ¡Perfecto!
Rainbolt
1
Calculé la clasificación promedio de los puntajes en el marcador, y esta entrada gana con esa medida.
Brilliand
9

Alan Shearer

Repite cualquier cosa que la persona con la que está sentado acaba de decir. Si la persona resulta estar equivocada, pasa a la siguiente persona y repite lo que dice en su lugar.

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";
        }
    }
}
Algy Taylor
fuente
Hace referencia a una variable llamada lastRoundincluso antes de declararla. Además, agregó paréntesis a todos sus, String.lengthpero no es una función. ¿Puedes hacer que tu envío llegue a un punto donde se compile?
Rainbolt
@Rusher - hecho :)
Algy Taylor
@Algy: lastRound.lengthtodavía se accede (en el primer if) antes de lastRounddeclararse (en ese if if else). Intente compilar (y tal vez ejecutar) su código antes de enviarlo aquí.
Paŭlo Ebermann
@ PaŭloEbermann - disculpas, no estoy en un entorno en el que pueda ejecutarlo - sin embargo, se hizo una enmienda
Algy Taylor
Ahora está haciendo referencia a una variable llamada "personToCopy" cuando está fuera de alcance. Simplemente lo moví dentro del bloque else para que se compilara, pero no sé si eso es lo que querías.
Rainbolt
8

Más tarde es Evil, JavaScript ( node.js )

Mide la cantidad de tiempo entre ejecuciones. Si la diferencia horaria es mayor que la última vez, debe ser malvada. De lo contrario, bien.

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');

Corre con: node laterisevil.js

nderscore
fuente
8

Buscador de patrones, Python

Busca un patrón recurrente, y si no puede encontrar uno, simplemente va con la mayoría.

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')

corre con

python3 pattern_finder.py
CesioVida Chaqueta
fuente
1
Me encanta este código, cuando lo ejecuto, siempre obtiene 3000 pts, de alguna manera.
Realdeo
8

El chaquetón

El Turncoat cree que debido a los otros combatientes hasta ahora, la mayoría alternará después de cada ronda entre el bien y el mal con más frecuencia de lo que se queda del mismo lado. Por lo tanto, comienza la primera ronda alineándose arbitrariamente con el bien, luego alterna cada ronda en un intento de permanecer en el equipo ganador o perdedor la mayoría de las veces.

package Humans;

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

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

Después de escribir esto, me di cuenta de que debido a las entradas basadas en el análisis estadístico, el impulso haría que la mayoría cambiara de lado menos a medida que se completaran más rondas. Por lo tanto, el Lazy Turncoat.

The Lazy Turncoat

El Lazy Turncoat comienza como el Turncoat, pero a medida que pasan las rondas, se vuelve más y más perezoso para cambiar al otro lado.

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";
    }
}
jaybz
fuente
2
¡El Lazy Turncoat es genial!
Angelo Fuchs
Incluyo ambos si no te importa.
Rainbolt
Adelante. Tengo curiosidad por ver cómo les irá a ambos, particularmente frente a los que compilan estadísticas de votación.
jaybz
@Rainbolt Acabo de notar un error estúpido con el Turncoat. Sin embargo, no es necesario corregirlo. Todavía funciona, pero no del todo como se esperaba, e incluso si no es demasiado tarde para arreglarlo, arreglarlo solo hará que se comporte exactamente como una de las entradas más nuevas de todos modos. Siéntase libre de incluir / excluir si lo desea.
jaybz
8

Biógrafo, rubí

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]

Mi intento de una entrada casi inteligente (una realmente inteligente requeriría pruebas contra el campo). Escrito en Ruby, por lo que existe la posibilidad de que esto sea demasiado lento, pero en mi máquina de todos modos esto toma .11 segundos para calcular la última ronda cuando hay 40 jugadores aleatorios, así que espero que funcione lo suficientemente bien.

guardar como biographer.rb, ejecutar comoruby biographer.rb

La idea es que, para cada jugador, calcule sus posibilidades de elegir "bueno" al observar sus propias elecciones para las últimas diez rondas y los resultados generales, y encontrar instancias en el pasado donde las circunstancias idénticas (sus votos + total resultados) ocurridos. Elige la longitud de mirada más larga, hasta 10 rondas, de modo que haya algún precedente, y la usa para crear una frecuencia (ajustada de acuerdo con la Ley de Sucesión de Laplace, para que nunca tengamos el 100% de confianza en nadie).

Luego ejecuta algunas simulaciones y ve con qué frecuencia Good gana. Si las simulaciones resultaron principalmente de la misma manera, entonces probablemente va a hacer una buena predicción en general, por lo que elige a la minoría pronosticada. Si no tiene confianza, elige la mayoría prevista.

histocrat
fuente
8

Judas

Judas es una muy buena persona. Es una pena que traicione a los buenos por unos centavos.

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";
    }
}
William Barbosa
fuente
1
Esto solamente siempre vota mal si hay suficientes participantes, es posible que desee quitar el ,cabo de history, más aún cuando Rusher va a dividir el juego en grupo.
Angelo Fuchs
No sabía que iba a dividir el juego en grupos. En realidad, esperé a que esta pregunta tuviera suficientes presentaciones antes de publicar mi respuesta debido al tamaño de la cadena. Gracias por hacérmelo saber.
William Barbosa
Si sabe cómo pasar un argumento de 60000 caracteres a un proceso en Windows, avíseme. De lo contrario, ¡perdón por estropear tu entrada y gracias por arreglarlo! No esperaba recibir tantas presentaciones.
Rainbolt
7

El jugador fallazgo (Python)

Si un lado ha ganado mayoría varias veces seguidas, el jugador se da cuenta de que es más probable que el otro lado sea la mayoría en la próxima ronda (¿verdad?) Y esto influye en su voto. Apunta a la minoría, porque si se convierte en minoría una vez, es probable que llegue allí varias veces (¿verdad?) Y obtenga muchos puntos.

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  

Uso

Para la primera ronda:

python gambler.py

y luego:

python gambler.py 101,100,001 etc.
comando
fuente
44
Me gusta cómo pareces seguro sobre tu código, ¿verdad? : P
IEatBagels
7

Autómata celular

Esto usa reglas convencionales para Conway's Game of Life para elegir un bando. Primero, se crea una cuadrícula 2D a partir de los votos anteriores. Luego, el "mundo" avanza una etapa y se calcula el número total de células vivas restantes. Si este número es mayor que la mitad del número total de celdas, se elige "bueno". De lo contrario, se elige "mal".

Perdone cualquier error, esto se rompió durante la hora del almuerzo. ;)

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;
    }
}
Teoría de grafos
fuente
1
Eliminé la línea de impresión del código para probar. Las entradas de Java solo necesitan devolver el bien o el mal, no imprimirlo.
Rainbolt
7

The Ridge Professor

Espero que el uso de bibliotecas esté permitido, no tenga ganas de hacerlo sin one =)

La idea básica es entrenar un clasificador de regresión de cresta para cada participante en las últimas rondas, utilizando los 30 resultados antes de cada ronda como características. Originalmente incluía la última ronda de resultados para todos los jugadores para predecir el resultado para cada jugador también, pero eso fue bastante corto para cuando el número de participantes aumenta (por ejemplo, 50 más o menos).

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

Compilar

Guarde el código fuente en un archivo llamado ridge_professor.cc, descargue la biblioteca Eigen y descomprima la carpeta Eigen que se encuentra dentro de la misma carpeta que el archivo fuente. Compilar cong++ -I. -O3 -ffast-math -o ridge_professor ridge_professor.cc .

Correr

llame a ridge_professor.exe y proporcione el argumento según sea necesario.

Pregunta

Como todavía no puedo comentar en ninguna parte, preguntaré aquí: ¿el límite de tamaño del argumento en Windows no hace posible llamar a los binarios resultantes con el historial completo a unos pocos cientos de vueltas? Pensé que no puedes tener más de ~ 9000 caracteres en la discusión ...

dgel
fuente
Gracias por llamar mi atención sobre esto . Encontraré alguna forma de hacerlo funcionar si ya no funciona bien en Java. Si Java no puede hacerlo, la investigación me dice que C ++ puede, y aprovecharé la oportunidad para volver a aprender C ++. Volveré en breve con los resultados de la prueba.
Rainbolt
Como resultado, Java no está sujeto a las limitaciones del símbolo del sistema. Parece que solo los comandos mayores de 32k causan un problema. Aquí está mi prueba (la escribí yo mismo): docs.google.com/document/d/… . Nuevamente, realmente aprecio que mencione esto antes de que comiencen las pruebas mañana.
Rainbolt
@Rusher Ya hay 57 bots y planeas que cada carrera esté compuesta por 1000 rondas. Eso haría que tu cadena tenga 57k caracteres (por lo tanto,> 32k), ¿no?
plannapus
1
@Rusher Creo que puede ser mejor extender la línea de tiempo una semana más y pedirles a los participantes que cambien sus programas para leer stdin en lugar de usar una cadena de argumento. Sería trivial para la mayoría de los programas cambiar
dgel
@dgel La línea de tiempo para el desafío es infinitamente larga, pero no quiero cambiar las reglas de manera que todos tengan que reescribir su respuesta. Estoy bastante seguro de que la regla que agregué anoche solo arruinará una sola presentación, y planeo ayudar a esa persona si alguna vez consigue que su programa llegue a un punto en el que se compile.
Rainbolt
6

Crowley

Porque los Winchesters son mucho menos interesantes sin este tipo. Obviamente se pone del lado del mal ... a menos que sea necesario para cuidar un mal mayor.

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

Miro los últimos dos turnos (0 comas hasta ahora y 1 coma hasta ahora) y si ambos dejan que gane el mal, yo voto bien. De lo contrario, voto el mal.

kaine
fuente
¿Lo entiendo bien? Te fijas en el último turno y si menos del 50% son votos "buenos", ¿estás del lado de "buenos" y si no mal? (Por curiosidad: ¿Prefieres nombres de variables crípticas o es un accidente?)
Angelo Fuchs
1
@AngeloNeuschitzer Miro los dos últimos turnos (0 comas hasta ahora y 1 coma hasta ahora) y si ambos dejan que gane el mal, votaré bien. De lo contrario, voto el mal. Prefiero nombres de variables que son cortos para escribir si el código es lo suficientemente corto, el propósito del código no se confundirá. No soy un programador profesional y esta fue la primera vez que programé en Java o algo por lo que alguien más vio el código en 6.5 años. Escribí esto para refrescar mi memoria. (TLDR no son crípticos para mí y soy el único al que generalmente codifico).
kaine
Para mayor claridad ... Crowley comenzó como humano, así que fue intencional que comience bien ... Aunque no esperaba que se mantuviera bien durante todas las rondas ... maldición
kaine