Buono contro il male


112

Risultati - 19 luglio 2014

L'attuale King of the Hill è Mercenary dall'utente Fabigler ! Continua a inviare iscrizioni e buttalo giù dal suo trono!

Fai clic qui per visualizzare il quadro di valutazione.

Sono stati inclusi i programmi presentati entro il 19 luglio 2014 o prima. Tutte le altre osservazioni saranno incluse nelle prove future. I nuovi risultati dovrebbero essere pubblicati intorno al 9 agosto, in modo da avere un sacco di tempo.


Illustrazione disegnata dal fratello Illustrato da Chris Rainbolt, mio ​​fratello e un neolaureato al Savannah College of Art and Design

introduzione

Gli angeli e i demoni stanno combattendo e, come al solito, usano la terra come campo di battaglia. Gli umani sono bloccati nel mezzo e sono costretti a schierarsi. Una forza neutrale sconosciuta premia coloro che combattono costantemente per la parte perdente.

Il gioco

Ad ogni prova, verrai accoppiato pseudo-casualmente e poi mischiato tra 20 e 30 altri invii. Ogni prova sarà composta da 1000 colpi. Ad ogni round, verrà passato un input e ci si aspetta che produca output. L'output verrà registrato e valutato. Questo processo verrà ripetuto 1000 volte.

Ingresso

Riceverai un singolo argomento che rappresenta i voti passati di ciascun giocatore. I round sono delimitati da virgola. A 0rappresenta un giocatore che si è schierato con il Male in quel round. A 1rappresenta un giocatore che si è schierato con il Bene. All'interno di una prova, i giocatori saranno sempre nello stesso ordine. Il tuo voto verrà incluso, ma non identificato in modo esplicito. Per esempio:

101.100.100

In questo esempio, tre round sono stati completati e tre giocatori sono in competizione. Il giocatore si è sempre schierato dalla parte del Bene. Il giocatore due si è sempre schierato con il male. Il giocatore tre è passato da Buono nel round 1 a Male nei round 2 e 3. Uno di quei giocatori eri tu.

Produzione

Sottomissioni Java

  • Restituisci la stringa goodse vuoi schierarti con Buono.
  • Restituisci la stringa evilse vuoi schierarti con il Male.

Sottomissioni non Java

  • Emette la stringa good a stdout se vuoi schierarti con Buono.
  • Invia la stringa evila stdout se vuoi schierarti con Evil.

Se il tuo programma genera o restituisce qualcos'altro, genera un'eccezione, non viene compilato o impiega più di un secondo a produrre qualcosa su questa macchina esatta , verrà squalificato.

punteggio

I punteggi verranno pubblicati in un foglio di calcolo di Google Documenti per una facile visualizzazione non appena riesco a compilare tutte le voci correnti. Non preoccuparti, continuerò a provare fino a quando continuerai a inviare programmi!

  • Ricevi 3 punti per schierarti con la maggioranza durante un round.
  • Ricevi n - 1 punti per schierarti con la minoranza durante un round, dove n è il numero di volte consecutive che ti sei schierato con la minoranza.

Il tuo punteggio sarà la mediana di 5 prove. Ogni prova è composta da 1000 colpi.

Prodotti finali

Sottomissioni non Java

È necessario inviare un titolo univoco, un programma e una stringa della riga di comando di Windows che eseguirà il programma. Ricorda che un argomento può essere aggiunto a quella stringa. Per esempio:

  • python Angel.py
    • Nota che questo non ha argomenti. Questo è il primo! Preparati per questo.
  • python Angel.py 11011,00101,11101,11111,00001,11001,11001

Sottomissioni Java

È necessario inviare un titolo univoco e una classe Java che estenda la classe umana astratta scritta di seguito.

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

analisi

Se si desidera verificare la propria richiesta, seguire le istruzioni qui .

Note aggiuntive

Puoi inviare tutti i diversi invii che desideri. Le richieste che sembrano essere colluse saranno squalificate. L'autore di questa sfida sarà l'unico giudice in materia.

Una nuova istanza del programma o della classe Java verrà creata ogni volta che viene richiamata. È possibile conservare le informazioni scrivendo in un file. Non è possibile modificare la struttura o il comportamento di nulla, tranne la propria classe.

I giocatori verranno mescolati prima dell'inizio del processo. Demon e Angel parteciperanno ad ogni prova. Se il numero di giocatori è pari, anche Petyr Baelish si unirà. Demon combatte per Evil, Angel for Good e Petyr Baelish sceglie un lato pseudocasuale.


2
I commenti sono stati eliminati, in quanto obsoleti e su richiesta dell'OP. Vi prego di avvisarmi di eventuali commenti che devono essere eliminati.
Maniglia della porta

7
Woah, OP cambia il suo nome utente. Ok, quindi quando verrà visualizzato il risultato?
solo il

6
@Rainbolt Questo deve essere un lavoro da baraccone, lanciare questa sfida! La ragione di questa quantità di attenzione è la semplicità del protocollo e delle regole, che lo rende accessibile e consente anche voci semplici e funzionanti . TL; DR: la tua sfida è troppo bella! : D
tomsmeding,

3
@dgel posterò i dati grezzi, i valori massimi, più bassi, medi e forse un grafico a linee in modo da poter vedere chi ha fatto meglio mentre la concorrenza si trascinava.
Rainbolt,

6
Uno dei pod ha finito con 10 voci che hanno votato allo stesso modo ogni volta. Di conseguenza, due utenti hanno ottenuto punteggi perfetti o "un round short of perfect" di circa 450.000. Le stesse voci segnarono intorno al 1900 in altre prove. Il punteggio medio è vicino al 2000. A causa dell'estremo squilibrio nei risultati, ho deciso che un numero più significativo sarebbe una mediana. Ho modificato la sfida in modo che dopo 5 prove, il vincitore sarà la presentazione con la mediana più alta. Se qualcuno pensa che passare dalla media alla mediana sia ingiusto o altrimenti una cattiva scelta, si prega di commentare.
Rainbolt,

Risposte:


11

Il mercenario

Si schiera sempre con quello che ha pagato più denaro nell'ultimo round.

Tenendo conto del fatto che le brave persone guadagnano statisticamente di più.

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

2
Questo è il secondo post per dire qualcosa sui soldi. Mi manca un riferimento o qualcosa del genere?
Rainbolt,

È vero, ma questo ragazzo è un bastardo ancora più malvagio. Abbandonando i suoi amici ogni turno, solo per motivi di denaro.
fabigler

Nell'istruzione switch mancava un'istruzione return per il caso predefinito, che non veniva compilata. Ne ho aggiunto uno a caso.
Rainbolt,

4
Congratulazioni, re della collina! Non capisco come vince questa voce. Vuoi aggiungere una spiegazione, ora che ha una generosità di 300 reputazione associata?
Rainbolt,

4
Forse un bug, o ho frainteso i commenti e la descrizione, ma il mercenario in realtà non fa quello che doveva fare. Fatta eccezione per il primo round casuale, si schiererà sempre con il male a meno che meno di 1/6 delle persone abbiano votato per il male nel round precedente.
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

Va semplicemente con la minoranza dell'ultimo round, solo perché tutto il resto è mainstream.

Corri come

ruby hipster.rb

30

Petyr Baelish

Non si sa mai da che parte sta 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";
    }
}

Questa voce sarà inclusa solo se il numero di giocatori è pari. Questo assicura che ci sarà sempre la maggioranza.


28
Dalla parte di Petyr Baelish, ovviamente.
Cthulhu,

2
@Kevin Batte costantemente la maggior parte dei robot. Di solito segna 27ish.
cjfaure,

3
@Kevin Questa voce è stata inviata dall'autore della sfida. Non doveva fare bene. Esiste per assicurarsi che ci sarà sempre la maggioranza, perché con un numero pari di giocatori, potrebbe esserci un pareggio.
Rainbolt,

4
Perché oh Dio, perché questo ha ottenuto il maggior numero di voti? Non è giusto .
tomsmeding

3
@tomsmeding No. È una citazione da Game of Thrones lol.
Rainbolt,

29

C ++, The Meta Scientist

Questo fa essenzialmente lo stesso di The Scientist, ma non opera sui round nel suo complesso ma sui singoli giocatori. Cerca di mappare un'onda (o una funzione costante) su ciascun giocatore separatamente e predice la sua mossa nel turno successivo. Dalla previsione rotonda risultante, The Meta Scientist sceglie quale parte sembra avere la maggioranza.

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

Se si desidera attivare le istruzioni di debug, modificare la lettura della riga #if 0in#if 1 .

Compila g++ -O3 -std=c++0x -o MetaScientist MetaScientist.cpp(non hai bisogno di avvisi, quindi no -Wall) ed esegui MetaScientist.exe(eventualmente includendo l'argomento ovviamente). Se lo chiedi davvero bene, posso fornirti un eseguibile di Windows.

EDIT: A quanto pare, la versione precedente ha esaurito il tempo intorno a 600 round nel gioco. Questo non dovrebbe farlo. Il consumo di tempo è controllato dalla #define WINDOW (...)linea, più è più lento ma guarda più indietro.


2
Ti consiglio umilmente di provare a scegliere il lato perdente. Se riesci a indovinare correttamente correttamente, otterrai più di 3 punti per round.
Kevin,

1
@Kevin È vero, ma ho pensato che potrebbe indovinare la parte sbagliata abbastanza rapidamente, e devi indovinare correttamente la parte perdente più di sette volte di fila per ottenere un miglioramento rispetto a ottenere sempre la maggioranza giusta. Potrei cambiarlo però.
tomsmeding

1
@Kevin Inoltre, vorrei prima vedere come fanno (scienziato e meta scienziato) quando Rusher ci procura un quadro di valutazione questo fine settimana, come indicato nei commenti all'OP. Rusher, scusa, ma sono troppo pigro per compilare tutto il materiale da solo ... :)
tomsmeding

3
Nessun problema! Probabilmente non è sicuro eseguirli comunque. Vorrei solo rovinare la mia macchina con il codice scritto da 50 sconosciuti su Internet.
Rainbolt,

1
@ Kevin Ma è così MOLTI ! Posso, davvero, ma non mi piace. Vedrò come vanno queste cose.
tomsmeding

26

Angelo

Il giocatore più puro di tutti.

Programma

print "good"

Comando

python Angel.py

22
Python è un buon linguaggio. Sembra naturale che l'Angelo lo usi.
jpmc26,

23
Vorrei ricordare alla gente che un Python è un serpente. Un serpente.
Mr Lister,

3
@MrLister Posso ricordarti che Lucifero era un grande Angelo prima che Dio lo cacciasse dal cielo?
Zibbobz,

1
@Zibbobz Sì ... peccato davvero, che siano caduti. Avrebbero potuto ottenere così tanto insieme.
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";
           }
        }
    }
}

Nel libro 7, The Atlantis Complex , Artemis Fowl ha contratto una malattia psicologica (chiamata complesso di Atlantide) che lo ha costretto a fare tutto in multipli di 5 (parlare, azioni, ecc.). Quando non riuscì a farlo in alcuni multipli di 5, fu preso dal panico. Fondamentalmente lo faccio: vedo se il bene o il male (pregiudizio intenzionale) è divisibile per 5, se nessuno dei due lo è, quindi mi faccio prendere dal panico e vedo che è stato maggiore e corro con quello o panico ancora di più e casualmente scelgo.


4
Quando ho letto Artemis Fowl in Junior High, esistevano solo due libri. È bello vedere che ora ce ne sono sette e che la Disney lo sta trasformando in un film.
Rainbolt,

1
In realtà ci sono 8 libri.
Kyle Kanos,

7
Più è bello (a meno che tu non stia leggendo La ruota del tempo)
Rainbolt,

1
E ti sei dimenticato break;nel tuo switch.
johnchen902,

1
@ johnchen902, @ Manu: non ho molta esperienza con Java (uso Fortran90 + e vedo solo Java qui), quindi i miei errori. Li riparerò quando entro in ufficio.
Kyle Kanos,

19

Disparnumerophobic

I numeri dispari sono terrificanti.

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

17
Il commento mi ha fatto ridere / sbuffare.
phyrfox,

17

Linus, Ruby

Cerca di confondere gli analisti rompendo sempre il modello .

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

Salva come linus.rbe corri conruby linus.rb


16

Il BackPacker

Determina un giocatore che ha ancora scelto la minoranza corrispondente e sceglie il suo ultimo 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;
    }
}

The CrowdFollower

Determina un giocatore che ha ancora scelto la maggioranza corrispondente e sceglie il suo ultimo 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;
    }
}

Programma molto pulito!
Rainbolt,

Spiacenti, penso di aver copiato il tuo programma in un'altra lingua.
PyRulez,

@Rusher Ho aggiornato il codice e vorrei aggiungerlo come due voci, una con goWithMajority = truee una dove si trova false. Va bene, o devo aggiungere un secondo BackPacker per questo?
Angelo Fuchs,

@AngeloNeuschitzer Ho modificato questo post. In questo modo, non dimenticherò di aggiungere entrambi gli invii. Ti suggerisco di cambiare il nome davvero non creativo che gli ho dato e magari aggiungere una descrizione ad entrambi se lo desideri.
Rainbolt,

1
@Rainbolt Mi piace di più il tuo FrontPacker, in realtà. Lol'd.
Tomsmeding,

15

Chiromante

Questo è ancora in corso d'opera. Non l'ho ancora provato. Volevo solo vedere se l'OP pensa di infrangere le regole o meno.

L'idea è di simulare il turno successivo eseguendo alcune volte tutti gli altri partecipanti per ottenere una probabilità del risultato e agire di conseguenza.

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

}

Se il tuo bot esegue tutti gli altri robot ogni turno prima di rispondere, non ci vorranno più di 1 secondo per rispondere?
plannapus,

@plannapus Suppongo che il presupposto di questo bot sia che tutti gli altri varranno dal lato della cautela ed eviteranno qualcosa che valga 1 secondo di attesa. Sto pensando che valga la pena inviare e inserire un messaggio che consiste in un'attesa di 0,9 secondi, prima di tornare "buono", solo per confonderlo. In realtà, SBoss mi ha battuto: D
scragar

Yahhh! Quindi dovrei inserire nella lista nera quel bot nel mio codice. Sarebbe frustrante ... Anche con voci diverse in ambienti diversi come Python o Perl, il nuovo caricamento dell'interprete potrebbe essere sufficiente a portare questo codice al di sopra del limite di tempo.
Andris,

16
Se qualcun altro fa la stessa cosa, otterrai un ciclo infinito.
Brilliand,

4
La presentazione è scaduta. Ho attaccato un profiler e quasi mezzo secondo viene speso per chiamare alcuni invii. Almeno funziona però, quindi complimenti per quello.
Rainbolt,

15

C ++, The Scientist

Questo cerca di, con la storia di ciò che la maggioranza ha scelto per round in wave( majority()dà la scelta della maggioranza in un round), di adattare un'onda ai dati, di lunghezza d'onda 2*periode fase phase. Quindi, dato 0,1,1,1,0,1,0,1,1,1,0,0,0,1,0che seleziona period=3, phase=5( maxat=={3,5}): i suoi punteggi diventano 9 3 11 5 5 3 5 7 9 7 7 7 7 7 7. Effettua il ciclo in tutti i periodi possibili e se, per quel periodo, il punteggio è superiore a quello del massimo corrente, memorizza {period,phase}per il quale si è verificato.

Quindi estrapola l'onda trovata al round successivo e prende la maggioranza prevista.

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

Compila g++ -O3 -std=c++0x -o Scientist Scientist.cpp(non hai bisogno di avvisi, quindi no -Wall) ed esegui Scientist.exe(eventualmente includendo l'argomento ovviamente). Se lo chiedi davvero bene, posso fornirti un eseguibile di Windows.

Oh, e non osare scherzare con il formato di input. Altrimenti farà cose strane.

EDIT: A quanto pare, la versione precedente ha esaurito il tempo intorno a 600 round nel gioco. Questo non dovrebbe farlo. Il consumo di tempo è controllato dalla #define WINDOW (...)linea, più è più lento ma guarda più indietro.


8
Scaricare eseguibili scritti da sessanta + sconosciuti su Internet sembra una cattiva idea.
Rainbolt,

@Rusher Sono completamente d'accordo. Se vuoi problemi, questo è il primo passo della guida "for dummies". La mia offerta è
valida

2
Ho ottenuto questo per compilare (e competere) bene.
Rainbolt,

14

Runner di codice

Quindi, per rendere le cose interessanti, ho creato uno script per scaricare automaticamente il codice da ogni risposta postata, compilarlo se necessario e quindi eseguire tutte le soluzioni secondo le regole. In questo modo, le persone possono controllare come stanno andando. Basta salvare questo script in run_all.py (richiede BeautifulSoup) e quindi:

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

Poche cose:

  1. Se si desidera aggiungere il supporto per più lingue o in alternativa rimuovere il supporto per alcune, consultare def submission_type(lang).
  2. L'estensione dello script dovrebbe essere abbastanza semplice, anche per le lingue che richiedono compilazione (vedi CPPSubmission). Il tipo di lingua viene preso dal tag del meta-codice < !-- language: lang-java -- >, quindi assicurati di aggiungerlo se vuoi che il tuo codice venga eseguito (Rimuovi gli spazi extra prima e dopo <>). AGGIORNAMENTO : ora esiste un'inferenza estremamente basilare per provare a rilevare la lingua se non è definita.
  3. Se il tuo codice non viene eseguito o non termina entro il tempo assegnato, verrà aggiunto blacklist.texte verrà rimosso automaticamente dalle prove future. Se correggi il codice, rimuovi la voce dalla lista nera ed esegui nuovamente get,

Lingue attualmente supportate:

 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
}

Senza ulteriori indugi:

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

Perché nessuna lingua Fortran ??
Kyle Kanos,

@KyleKanos - Ho aggiunto il supporto per esso, aggiornerò il codice a breve.
WhatAWorld

Sìì! Ho (una specie) lavorato duramente sulla mia presentazione Fortran e Rusher non riesce a farlo funzionare, quindi vorrei che qualcuno lo ottenga :)
Kyle Kanos,

1
@Rusher: sono d'accordo con PeterTaylor su questo: l'evidenziazione della sintassi poiché l' unica modifica suggerita dovrebbe essere respinta. Le modifiche dovrebbero essere usate per correzioni sostanziali , non per cose minori.
Kyle Kanos

1
Ti meriti il ​​rappresentante per questo, ma dal momento che questa non è esattamente una risposta alla domanda (e potrebbe probabilmente trarre beneficio dalla comunità aggiungendo materiale per altre lingue) penso che questo dovrebbe tecnicamente essere un wiki della comunità.
Martin Ender,

13

The Beautiful Mind, Ruby

Prende la sua decisione sulla base di schemi di significato discutibile nella rappresentazione bit dell'ultimo 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

Corri come

ruby beautiful-mind.rb

13

Piustizioso, Lua

Un programma superstizioso che crede in Segni e Meraviglie.

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

eseguilo con:

lua Piustitious.lua

seguito dall'input.


11

The Winchesters

Sam e Dean sono bravi (il più delle volte).

package Humans;

public class TheWinchesters extends Human {

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

}

Sei sicuro che 9:1sia il giusto rapporto? Forse dovremmo fare un po 'di data mining e ottenere un rapporto più preciso?
recursion.ninja,

1
@awashburn Ho iniziato a guardare Supernatural 2 mesi fa (ora bloccato nella stagione 9) e 9:1mi sembra ok;)
CommonGuy

10

esperto di statistica

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

5
Quella seconda ultima riga è così fantastica
cjfaure il

5
@Undeserved Invece di Math.ceil(Math.random()-Math.random())te puoi fare anche solo Math.round(Math.random()).
tomsmeding

10

R, un bot un po 'bayesiano

Utilizzare la tabella delle frequenze per ciascun utente come probabilità precedente dell'output di altri utenti.

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

Richiamato usando Rscript BayesianBot.R seguito dall'input.

Modifica : solo per chiarire cosa sta facendo, ecco un passo per passo con l'input di esempio:

> 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

Quindi la linea che inizia per result<-, per ogni giocatore, sceglie casualmente 0 o 1 usando quest'ultimo tavolo come pesi (cioè per il giocatore 1 la probabilità di scegliere 0 è 2/7, di 1 1/7, ecc.). Seleziona un risultato per ogni giocatore / colonna e alla fine restituisce il numero che è finito essere il più comune.


10

svizzero

Sostiene sempre la neutralità. Condannato a non vincere mai.

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

Non ho scritto questo!
Rainbolt,

Questa è l'ironia. La neutralità non vince mai
fabigler

2
@Rusher ah ora ho capito: D
fabigler

1
Non si compila nemmeno: manca un punto e virgola.
Paŭlo Ebermann,

9

HAL 9000

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

Modifica: forse questo è più adatto per HAL 9000, ma fai attenzione! È molto malvagio. Consiglio cddi svuotare la directory prima di eseguirla.

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

Questo rimuove un file cwdper ogni invocazione!

Invocazione non così ovvia:

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 ~]$

È necessario fornire un comando che può essere utilizzato per eseguire il programma. Vedi la sezione "Risultati" della sfida per ulteriori informazioni.
Rainbolt,

@Rusher Done;)
core1024

9

Volontà della maggioranza

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

Salvalo come WotM.py, esegui comepython3 WotM.py seguito dall'input.

Un semplice programma, solo per vedere come andrà. Va con qualunque cosa la maggioranza abbia detto l'ultima volta, o altrimenti casuale.


È necessario fornire un comando che può essere utilizzato per eseguire il programma. Vedi la sezione "Risultati" della sfida per ulteriori informazioni.
Rainbolt,

Dannazione, questo rende il mio un duplicato. : D Modificato il mio in minoranza.
Martin Ender,

@Rusher Aggiunto il comando. Quello che stavi cercando?
Isaacg,

@isaacg Perfect!
Rainbolt

1
Ho calcolato la classifica media dai punteggi nel tabellone e questa voce vince con quella misura.
Brilliand

9

Alan Shearer

Ripete qualunque cosa abbia appena detto la persona accanto. Se la persona si rivela sbagliata, passa alla persona successiva e ripete invece ciò che dicono.

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

Fai riferimento a una variabile chiamata lastRoundprima ancora di dichiararla. Inoltre, hai aggiunto parentesi a tutte le tue String.lengthma non è una funzione. Puoi ottenere il tuo invio al punto in cui verrà compilato?
Rainbolt,

@Rusher - done :)
Algy Taylor,

@Algy: lastRound.lengthsi accede ancora (nel primo if) prima lastRoundviene dichiarato (in questo if's else). Prova a compilare (e forse eseguire) il tuo codice prima di inviarlo qui.
Paŭlo Ebermann,

@ PaŭloEbermann - scuse, non sono in un ambiente in cui posso eseguirlo - emendamento fatto, però
Algy Taylor

Ora fai riferimento a una variabile chiamata "personToCopy" quando non rientra nell'ambito. L'ho appena spostato all'interno del blocco else in modo che si compili, ma non so se è quello che volevi.
Rainbolt,

8

Più tardi è il male, JavaScript ( node.js )

Misura la quantità di tempo tra le esecuzioni. Se la differenza oraria è maggiore dell'ultima volta, deve essere malvagia. Altrimenti, bene.

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

Corri con: node laterisevil.js


8

Pattern Finder, Python

Cerca un modello ricorrente e, se non riesce a trovarne uno, va bene con la maggioranza.

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

Corri con

python3 pattern_finder.py

1
Adoro questo codice così tanto, quando lo eseguo, ottiene sempre 3000 punti, in qualche modo.
Realdeo,

8

The Turncoat

Il Turncoat ritiene che, a causa degli altri combattenti finora, la maggioranza si alternerà dopo ogni round tra il bene e il male più spesso di quanto rimanga dalla stessa parte. Quindi inizia il primo round schierandosi arbitrariamente con il bene, quindi alterna ogni round nel tentativo di rimanere nella squadra vincente o perdente il più delle volte.

package Humans;

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

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

Dopo aver scritto questo, mi sono reso conto che, a causa delle voci basate sull'analisi statistica, lo slancio avrebbe causato la maggior parte dei commutatori meno con il completamento di più round. Quindi, il pigro Turncoat.

The Lazy Turncoat

Il Lazy Turncoat inizia come il Turncoat, ma quando passano i round, diventa sempre più pigro per passare dall'altra parte.

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

2
Lazy Turncoat è fantastico!
Angelo Fuchs,

Sto includendo entrambi se non ti dispiace.
Rainbolt,

Vai avanti. Sono curioso di vedere come faranno entrambi, in particolare rispetto a quelli che compilano statistiche di voto.
jaybz,

@Rainbolt Ho appena notato uno stupido bug con Turncoat. Non è necessario correggerlo però. Funziona ancora, ma non del tutto come previsto, e anche se non è troppo tardi per risolverlo, risolverlo farà semplicemente comportarsi esattamente come una delle voci più recenti. Sentiti libero di includere / escludere se lo desideri.
jaybz,

8

Biografo, 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]

Il mio tentativo di accesso quasi intelligente (uno effettivamente intelligente richiederebbe test sul campo). Scritto in Ruby, quindi c'è una possibilità che sia troppo lento, ma sulla mia macchina ci vogliono comunque .11 secondi per calcolare l'ultimo round quando ci sono 40 giocatori casuali, quindi spero che funzionerà abbastanza bene.

salva come biographer.rb, esegui comeruby biographer.rb

L'idea è che per ogni giocatore, stima le loro possibilità di scegliere "buono" guardando sia le proprie scelte negli ultimi dieci round, sia i risultati complessivi, e trovando istanze nel passato in cui le circostanze identiche (i loro voti + complessivo risultati). Seleziona la lunghezza più lunga del lookbehind, fino a 10 round, in modo tale che ci sia un precedente, e lo utilizza per creare una frequenza (regolata secondo la Legge di Successione di Laplace, in modo che non siamo mai sicuri al 100% di nessuno).

Quindi esegue alcune simulazioni e vede quante volte Good vince. Se le simulazioni si sono rivelate per lo più allo stesso modo, probabilmente farà bene la previsione in generale, quindi sceglierà la minoranza prevista. Se non è sicuro, seleziona la maggioranza prevista.


8

Giuda

Giuda è davvero una brava persona. È un peccato che tradirà i bravi ragazzi per qualche soldo.

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

1
Questo vota sempre il male solo se ci sono abbastanza partecipanti, potresti voler rimuovere il ,fuori history, ancora di più in quanto Rusher sta per dividere il gioco in gruppi.
Angelo Fuchs,

Non sapevo che avrebbe diviso il gioco in gruppi. Ho effettivamente aspettato che questa domanda avesse abbastanza invii prima di pubblicare la mia risposta a causa delle dimensioni della stringa. Grazie per avermi fatto sapere.
William Barbosa,

Se sai come passare un argomento di 60000 caratteri a un processo in Windows, fammelo sapere. Altrimenti, scusami per aver sbagliato la voce e grazie per averla riparata! Non mi aspettavo di ricevere così tante proposte.
Rainbolt,

7

The Fallacious Gambler (Python)

Se una parte ha vinto la maggioranza più volte di seguito, il giocatore si rende conto che è più probabile che l'altra parte sia la maggioranza nel prossimo turno (giusto?) E questo influenza il suo voto. Punta alla minoranza, perché se riesce a farla diventare una minoranza una volta è probabile che ci riesca più volte (giusto?) E ottiene molti punti.

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

Per il primo turno:

python gambler.py

e successivamente:

python gambler.py 101,100,001 etc.

4
Mi piace come sembri sicuro del tuo codice, giusto? : P
IEatBagels

7

Automa cellulare

Questo utilizza regole convenzionali per Conway's Game of Life per scegliere un lato. Innanzitutto, viene creata una griglia 2D dai voti precedenti. Quindi, il "mondo" viene fatto avanzare di uno stadio e viene calcolato il numero totale di cellule viventi rimaste. Se questo numero è maggiore della metà del numero totale di celle, viene scelto "buono". Altrimenti, viene scelto "male".

Per favore, perdona qualsiasi errore, questo è stato distrutto durante la mia ora di pranzo. ;)

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

1
Ho rimosso la riga di stampa dal codice per il test. Le voci Java devono solo restituire il bene o il male, non stamparlo.
Rainbolt,

7

Il professore di cresta

Spero che l'uso delle librerie sia permesso, non mi va di farlo senza uno =)

L'idea di base è quella di formare un classificatore di regressione della cresta per ciascun partecipante negli ultimi round, usando i 30 risultati prima di ogni round come funzionalità. Inizialmente includeva l'ultimo round di risultati per tutti i giocatori per predire il risultato anche per ciascun giocatore, ma questo lo stava tagliando piuttosto vicino per il tempo in cui il numero di partecipanti aumenta (diciamo circa 50).

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

Compilare

Salvare il codice sorgente in un file chiamato ridge_professor.cc, scaricare la libreria Eigen e decomprimere la cartella Eigen all'interno della stessa cartella del file sorgente. Compila con g++ -I. -O3 -ffast-math -o ridge_professor ridge_professor.cc.

Correre

chiamare ridge_professor.exe e fornire l'argomento se necessario.

Domanda

Dal momento che non posso ancora commentare da nessuna parte, ti chiederò qui: il limite della dimensione dell'argomento su Windows non rende impossibile chiamare i binari risultanti con l'intera cronologia a poche centinaia di giri? Pensavo non potessi avere più di ~ 9000 caratteri nell'argomento ...


Grazie per aver attirato la mia attenzione su questo . Cercherò un modo per farlo funzionare se non funziona già bene in Java. Se Java non può farlo, la ricerca mi dice che il C ++ può, e ne approfitto per riapprendere il C ++. Torno presto con i risultati dei test.
Rainbolt,

A quanto pare, Java non è soggetto ai limiti del prompt dei comandi. Sembra che solo i comandi più grandi di 32k causino un problema. Ecco la mia prova (l'ho scritta da me): docs.google.com/document/d/… . Ancora una volta, apprezzo molto che tu abbia parlato di questo prima che le prove inizino domani.
Rainbolt,

@Rusher Ci sono già 57 bot e pensi che ogni corsa sia composta da 1000 round. Ciò renderebbe la tua stringa di 57k caratteri (quindi> 32k), no?
plannapus,

1
@Rusher Penso che potrebbe essere meglio estendere la sequenza temporale di un'altra settimana e chiedere ai partecipanti di cambiare i loro programmi per leggere lo stdin invece di usare una stringa di argomenti. Sarebbe banale per la maggior parte dei programmi cambiare
dgel

@dgel La sequenza temporale della sfida è infinitamente lunga, ma non voglio cambiare le regole in modo che tutti debbano riscrivere la loro risposta. Sono abbastanza sicuro che la regola che ho aggiunto la scorsa notte rovinerà solo un singolo invio, e ho intenzione di aiutare quella persona se riesce a portare il suo programma a un punto in cui viene compilato.
Rainbolt,

6

Crowley

Perché i Winchester sono molto meno interessanti senza questo tipo. Ovviamente si schiera con il male ... a meno che non sia necessario per prendersi cura di un male più grande.

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

Guardo gli ultimi due turni (0 virgole finora e 1 virgola finora) e se entrambi lasciano vincere il male, voto bene. Altrimenti voto male.


Ho capito bene? Guardi l'ultimo turno e se meno del 50% sono voti "buoni", schierati con "buono", altrimenti con il male? (Per curiosità: preferisci i nomi delle variabili criptiche o è un incidente?)
Angelo Fuchs,

1
@AngeloNeuschitzer Guardo gli ultimi due turni (0 virgole finora e 1 virgola finora) e se entrambi lasciano vincere il male, voto bene. Altrimenti voto male. Preferisco i nomi delle variabili che sono brevi da digitare se il codice è abbastanza corto, lo scopo del codice non verrà confuso. Non sono un programmatore professionista e questa è stata la prima volta che ho programmato in Java o qualcosa che qualcun altro ha visto il codice per 6,5 anni. Ho scritto questo per rinfrescare la mia memoria (i TLDR non sono criptici per me e io sono l'unico per cui di solito codice).
Kaine,

Per chiarezza ... Crowley è iniziato come un essere umano, quindi era intenzionale che inizi bene ... Non si aspettava che rimanesse buono per tutti i round, però ... dannazione
Kaine,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.