Baik vs. Jahat


112

Hasil - 19 Juli 2014

King of the Hill saat ini adalah Mercenary oleh pengguna Fabigler ! Terus kirimkan entri dan jatuhkan dia dari singgasananya!

Klik di sini untuk melihat Papan Skor.

Program yang diajukan pada atau sebelum 19 Juli 2014 dimasukkan. Semua pengiriman lainnya akan dimasukkan dalam uji coba mendatang. Hasil baru harus diposting sekitar 9 Agustus, sehingga memberi Anda banyak waktu.


Ilustrasi digambar oleh saudara Diilustrasikan oleh Chris Rainbolt, kakak saya dan lulusan baru dari Savannah College of Art and Design

pengantar

Para malaikat dan iblis bertempur dan, seperti biasa, menggunakan bumi sebagai medan pertempuran mereka. Manusia terjebak di tengah dan dipaksa memihak. Kekuatan netral yang tidak dikenal memberi penghargaan kepada mereka yang secara konsisten berjuang untuk pihak yang kalah.

Permainan

Setiap percobaan, Anda akan dipasangkan secara acak dan kemudian dikocok dengan antara 20 dan 30 pengiriman lainnya. Setiap percobaan akan terdiri dari 1000 putaran. Setiap putaran, Anda akan melewati input dan diharapkan menghasilkan output. Output Anda akan direkam dan dinilai. Proses ini akan diulang 1000 kali.

Memasukkan

Anda akan menerima argumen tunggal yang mewakili suara masa lalu masing-masing pemain. Putaran dibatasi oleh koma. A 0mewakili pemain yang memihak Evil pada ronde itu. A 1mewakili pemain yang memihak Good. Dalam suatu percobaan, para pemain akan selalu berada dalam urutan yang sama. Pilihan Anda sendiri akan dimasukkan, tetapi tidak diidentifikasi secara eksplisit. Sebagai contoh:

101.100.100

Dalam contoh ini, tiga putaran telah selesai dan tiga pemain bersaing. Pemain satu selalu memihak Baik. Pemain dua selalu memihak Evil. Pemain tiga bertukar dari Baik di ronde 1 ke Jahat di ronde 2 dan 3. Salah satu pemain itu adalah Anda.

Keluaran

Pengajuan Java

  • Kembalikan string goodjika Anda ingin berpihak pada Good.
  • Kembalikan string eviljika Anda ingin memihak Jahat.

Kiriman Non-Jawa

  • Keluarkan string goodke stdout jika Anda ingin berpihak pada Good.
  • Keluarkan string evilke stdout jika Anda ingin memihak Jahat.

Jika program Anda menghasilkan atau mengembalikan apa pun, melempar pengecualian, tidak mengkompilasi, atau membutuhkan waktu lebih dari satu detik untuk menghasilkan apa pun pada mesin yang tepat ini , maka itu akan didiskualifikasi.

Mencetak gol

Skor akan diposting dalam spreadsheet Google docs untuk mudah dilihat segera setelah saya dapat mengkompilasi semua entri saat ini. Jangan khawatir - saya akan terus menjalankan uji coba selama kalian terus mengirimkan program!

  • Anda menerima 3 poin untuk berpihak pada mayoritas selama putaran.
  • Anda menerima n - 1 poin untuk berpihak pada minoritas selama putaran, di mana n adalah jumlah kali berturut-turut Anda memihak minoritas.

Skor Anda akan menjadi median dari 5 uji coba. Setiap percobaan terdiri dari 1000 putaran.

Kiriman

Kiriman Non-Jawa

Anda harus mengirimkan judul unik, program, dan string baris perintah Windows yang akan menjalankan program Anda. Ingatlah bahwa argumen dapat ditambahkan ke string itu. Sebagai contoh:

  • python Angel.py
    • Perhatikan bahwa yang ini tidak memiliki argumen. Ini bulat satu! Bersiaplah untuk ini.
  • python Angel.py 11011,00101,11101,11111,00001,11001,11001

Pengajuan Java

Anda harus mengirimkan judul unik dan kelas Java yang memperluas kelas Manusia abstrak yang ditulis di bawah ini.

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

Pengujian

Jika Anda ingin menguji kiriman Anda sendiri, ikuti instruksi di sini .

catatan tambahan

Anda dapat mengirimkan banyak pengiriman berbeda seperti yang Anda inginkan. Kiriman yang tampaknya berkolusi akan didiskualifikasi. Penulis tantangan ini akan menjadi satu-satunya hakim dalam hal ini.

Sebuah instance baru dari program atau kelas Java Anda akan dibuat setiap kali dipanggil. Anda dapat menyimpan informasi dengan menulis ke file. Anda tidak boleh mengubah struktur atau perilaku apa pun kecuali kelas Anda sendiri.

Pemain akan dikocok sebelum sidang dimulai. Demon dan Angel akan berpartisipasi dalam setiap percobaan. Jika jumlah pemainnya genap, Petyr Baelish juga akan bergabung. Demon fights for Evil, Angel for Good, dan Petyr Baelish memilih sisi pseudorandom.


2
Komentar dibersihkan, karena sudah usang dan atas permintaan OP. Tolong beri tahu saya jika ada komentar yang harus dihapus.
Gagang pintu

7
Woah, OP mengubah nama penggunanya. Oke, jadi kapan hasilnya akan ditampilkan?
justhalf

6
@Rainbolt Ini pasti pekerjaan yang luar biasa, menjalankan tantangan ini! Alasan untuk jumlah perhatian ini adalah kesederhanaan protokol dan aturan, membuatnya dapat diakses sementara juga memungkinkan entri yang sederhana dan berfungsi . TL; DR: Tantangan Anda terlalu bagus! : D
tomsmeding

3
@gel Saya akan memposting data mentah, atas, bawah, rata-rata, dan mungkin bagan garis sehingga kita dapat melihat siapa yang lebih baik saat kompetisi berlangsung.
Rainbolt

6
Salah satu pod berakhir dengan 10 entri yang memberikan suara dengan cara yang sama setiap kali. Akibatnya, dua pengguna berakhir dengan skor sempurna atau "kurang satu putaran sempurna" sekitar 450.000. Entri yang sama mencetak sekitar 1900 dalam uji coba lainnya. Skor rata-rata mendekati 2000. Karena ketidakseimbangan ekstrem dalam hasil, saya memutuskan bahwa angka yang lebih bermakna akan menjadi median. Saya mengedit tantangan sehingga setelah 5 uji coba, pemenang akan menjadi karya dengan median tertinggi. Jika ada yang berpikir bahwa pindah dari mean ke median adalah tidak adil atau pilihan yang buruk, silakan komentar.
Rainbolt

Jawaban:


11

Mercenary

Selalu memihak orang yang membayar paling banyak uang putaran terakhir.

Memperhatikan bahwa orang baik berpenghasilan lebih banyak secara statistik.

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
Ini adalah posting kedua untuk mengatakan sesuatu tentang uang. Apakah saya kehilangan referensi atau sesuatu?
Rainbolt

Benar, tapi orang ini bahkan lebih jahat. Meninggalkan teman-temannya setiap belokan, hanya demi uang.
Fabigler

Pernyataan beralih Anda tidak memiliki pernyataan pengembalian untuk kasus default, menyebabkannya tidak dapat dikompilasi. Saya menambahkan yang acak.
Rainbolt

4
Selamat, Raja Bukit! Saya tidak mengerti bagaimana entri ini menang. Ingin menambahkan penjelasan, sekarang ia memiliki 300 reputasi hadiah yang melekat padanya?
Rainbolt

4
Mungkin bug, atau saya salah memahami komentar dan deskripsi, tetapi Mercenary tidak benar-benar melakukan apa yang seharusnya dilakukan. Kecuali untuk ronde acak pertama, ia akan selalu berpihak pada kejahatan kecuali kurang dari 1/6 orang memilih kejahatan pada ronde sebelumnya.
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

Cukup dengan minoritas putaran terakhir, hanya karena segala sesuatu yang lain adalah arus utama.

Jalankan seperti

ruby hipster.rb

30

Petyr Baelish

Anda tidak pernah tahu sisi siapa Petyr Baelish berada.

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

Entri ini hanya akan dimasukkan jika jumlah pemainnya genap. Ini memastikan bahwa akan selalu ada mayoritas.


28
Di pihak Petyr Baelish, jelas.
Cthulhu

2
@Kevin Secara konsisten mengalahkan sebagian besar bot. Biasanya skor 27ish.
cjfaure

3
@Kevin Entri ini diajukan oleh penulis tantangan. Itu tidak dimaksudkan untuk dilakukan dengan baik. Itu ada untuk memastikan bahwa akan selalu ada mayoritas, karena dengan jumlah pemain genap, mungkin ada dasi.
Rainbolt

4
Mengapa oh Tuhan mengapa yang ini mendapat suara terbanyak? Itu tidak adil .
tommeding

3
@tommeding No. Ini kutipan dari Game of Thrones lol.
Rainbolt

29

C ++, The Meta Scientist

Yang satu ini pada dasarnya sama dengan The Scientist, tetapi tidak beroperasi pada putaran secara keseluruhan tetapi pada pemain individu. Ia mencoba untuk memetakan gelombang (atau fungsi konstan) untuk masing-masing pemain secara terpisah dan memprediksi gerakan mereka di babak berikutnya. Dari prediksi putaran yang dihasilkan, The Meta Scientist memilih pihak mana saja yang tampaknya memiliki mayoritas.

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

Jika Anda ingin mengaktifkan pernyataan debug, ubah baris bacaan #if 0menjadi #if 1.

Kompilasi dengan g++ -O3 -std=c++0x -o MetaScientist MetaScientist.cpp(Anda tidak perlu peringatan, jadi tidak ada -Wall) dan jalankan dengan MetaScientist.exe(mungkin termasuk argumen tentu saja). Jika Anda bertanya dengan sangat baik, saya dapat memberikan Anda executable Windows.

EDIT: Rupanya, versi sebelumnya kehabisan waktu sekitar 600 putaran ke dalam permainan. Ini seharusnya tidak melakukan itu. Konsumsi waktu dikendalikan oleh #define WINDOW (...)garis, lebih banyak lebih lambat tetapi terlihat lebih jauh ke belakang.


2
Dengan rendah hati saya sarankan Anda mencoba memilih sisi yang kalah. Jika Anda secara konsisten dapat menebak dengan benar, Anda akan mendapatkan lebih dari 3 poin per ronde.
Kevin

1
@ Kevin Itu benar, tapi saya pikir itu mungkin menebak sisi yang salah dengan cukup cepat, dan Anda harus menebak dengan benar sisi yang kalah lebih dari tujuh kali berturut-turut untuk mendapatkan peningkatan dari selalu mendapatkan hak yang benar. Saya mungkin mengubahnya.
mulai

1
@Kevin Juga, saya pertama-tama ingin melihat bagaimana hal ini terjadi (Scientist and Meta Scientist) ketika Rusher mendapatkan papan skor untuk kami akhir pekan ini, seperti yang ditunjukkannya dalam komentar di OP. Rusher, maaf, tapi aku terlalu malas untuk mengkompilasi semua barang sendiri ... :)
tomsmeding

3
Jangan khawatir! Mungkin tidak aman untuk menjalankannya. Biarkan saya mengacaukan mesin saya dengan kode yang ditulis oleh 50 orang asing di Internet.
Rainbolt

1
@ Kevin Tapi itu BANYAK ! Memang saya bisa, tetapi saya tidak menyukainya. Saya akan melihat bagaimana tarif ini.
tommeding

26

malaikat

Pemain paling murni dari semuanya.

Program

print "good"

Perintah

python Angel.py

22
Python adalah bahasa yang baik. Tampaknya wajar jika Malaikat harus menggunakannya.
jpmc26

23
Bolehkah saya mengingatkan orang bahwa Python adalah Ular. A Serpent.
Tn. Lister

3
@ Tuan, Bolehkah saya mengingatkan Anda bahwa Lucifer adalah Malaikat yang hebat sebelum Allah mengusirnya dari surga?
Zibbobz

1
@ Zibbobz Ya ... benar-benar memalukan, bahwa mereka jatuh. Mereka bisa mencapai banyak hal bersama.
Tn. 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";
           }
        }
    }
}

Dalam Buku 7, Kompleks Atlantis , Artemis Fowl mengidap penyakit psikologis (disebut kompleks Atlantis) yang memaksanya melakukan segala sesuatu dalam kelipatan 5 (berbicara, bertindak, dll). Ketika dia tidak bisa melakukannya dalam kelipatan 5, dia panik. Pada dasarnya saya melakukan itu: lihat apakah baik atau jahat (bias disengaja) dibagi dengan 5, jika tidak ada, maka saya panik & melihat mana yang lebih besar & menjalankannya atau panik lebih jauh & memilih secara acak.


4
Ketika saya membaca Artemis Fowl di SMP, hanya ada dua buku. Sangat menyenangkan untuk melihat bahwa sekarang ada tujuh, dan Disney membuatnya menjadi film.
Rainbolt

1
Sebenarnya ada 8 buku.
Kyle Kanos

7
Semakin meriah (kecuali jika Anda membaca The Wheel of Time)
Rainbolt

1
Dan Anda lupa break;di switch.
johnchen902

1
@ johnchen902, @ Manu: Saya tidak terlalu berpengalaman di java (saya menggunakan Fortran90 + & hanya melihat java di sini), maka kesalahan saya. Saya akan memperbaikinya ketika saya masuk ke kantor dalam satu jam.
Kyle Kanos

19

Disparnumerophobic

Angka ganjil itu menakutkan.

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
Komentar membuat saya tertawa / mendengus.
phyrfox

17

Linus, Ruby

Berusaha mengacaukan analis dengan selalu melanggar pola .

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

Simpan sebagai linus.rbdan jalankanruby linus.rb


16

BackPacker

Menentukan pemain yang telah memilih minoritas yang paling cocok dan memilih suara terakhirnya.

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

CrowdFollower

Menentukan pemain yang telah memilih mayoritas yang paling cocok dan memilih suara terakhirnya.

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

Program yang sangat bersih!
Rainbolt

Aduh, saya pikir saya mungkin telah menyalin program Anda dalam bahasa yang berbeda.
PyRulez

@Rusher Saya memperbarui kode dan ingin menambahkan ini sebagai dua entri, satu dengan goWithMajority = truedan satu di mana false. Apakah itu oke, atau apakah saya perlu menambahkan BackPacker kedua untuk ini?
Angelo Fuchs

@AngeloNeuschitzer Saya mengedit posting ini. Dengan cara ini, saya tidak akan lupa untuk menambahkan kedua kiriman. Saya sarankan Anda mengubah nama yang benar-benar tidak kreatif yang saya berikan, dan mungkin menambahkan deskripsi untuk keduanya jika Anda mau.
Rainbolt

1
@ Rainbolt, saya lebih suka FrontPacker Anda. Lol.
tommeding

15

Peramal

Ini masih dalam proses. Saya belum mengujinya. Saya hanya ingin melihat apakah OP berpikir itu melanggar aturan atau tidak.

Idenya adalah untuk mensimulasikan putaran selanjutnya dengan mengeksekusi semua peserta lain beberapa kali untuk mendapatkan probabilitas hasil dan bertindak sesuai.

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

}

Jika bot Anda menjalankan semua bot lainnya masing-masing putaran sebelum menjawab, tidakkah perlu lebih dari 1 detik untuk menjawab?
plannapus

@plannapus Saya akan menebak asumsi dengan bot ini adalah bahwa semua orang akan berbuat salah di sisi hati-hati dan menghindari apa pun yang dekat menunggu 1 detik. Saya berpikir mungkin mengirimkan dan masuk yang berharga yang terdiri dari menunggu 0,9 detik, sebelum kembali "baik", hanya untuk mengacaukannya. Sebenarnya, SBoss telah mengalahkan saya untuk itu: D
scragar

Yahhh! Maka saya harus daftar hitam bot itu dalam kode saya. Itu akan membuat frustasi ... Juga dengan entri yang berbeda di lingkungan yang berbeda seperti Python atau Perl, pemuatan penerjemah yang direplikasi mungkin cukup untuk membawa kode ini di atas batas waktu.
Andris

16
Jika orang lain melakukan hal yang sama dengan ini, Anda mendapatkan loop tak terbatas.
Brilliand

4
Waktu pengiriman habis. Saya melampirkan profiler, dan hampir setengah detik dihabiskan memanggil beberapa pengiriman. Setidaknya itu berfungsi, jadi selamat untuk itu.
Rainbolt

15

C ++, Ilmuwan

Yang satu ini mencoba, dengan sejarah apa yang dipilih mayoritas per putaran wave( majority()memberikan pilihan mayoritas pada putaran), cocok dengan gelombang ke data, panjang gelombang 2*perioddan fase phase. Jadi, diberikan 0,1,1,1,0,1,0,1,1,1,0,0,0,1,0itu memilih period=3, phase=5( maxat=={3,5}): nilainya menjadi 9 3 11 5 5 3 5 7 9 7 7 7 7 7 7. Itu melingkupi semua periode yang mungkin dan jika, untuk periode itu, skor lebih tinggi daripada maksimum saat ini, itu menyimpan {period,phase}yang terjadi.

Itu kemudian mengekstrapolasi gelombang yang ditemukan ke babak berikutnya dan mengambil mayoritas yang diprediksi.

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

Kompilasi dengan g++ -O3 -std=c++0x -o Scientist Scientist.cpp(Anda tidak perlu peringatan, jadi tidak ada -Wall) dan jalankan dengan Scientist.exe(mungkin termasuk argumen tentu saja). Jika Anda bertanya dengan sangat baik, saya dapat memberikan Anda executable Windows.

Oh, dan jangan berani mengacaukan format input. Itu akan melakukan hal-hal aneh sebaliknya.

EDIT: Rupanya, versi sebelumnya kehabisan waktu sekitar 600 putaran ke dalam permainan. Ini seharusnya tidak melakukan itu. Konsumsi waktu dikendalikan oleh #define WINDOW (...)garis, lebih banyak lebih lambat tetapi terlihat lebih jauh ke belakang.


8
Mengunduh file executable yang ditulis oleh enam puluh + orang asing di Internet sepertinya ide yang buruk.
Rainbolt

@Rusher, saya sepenuhnya setuju. Jika Anda memang menginginkan masalah, itulah langkah pertama dalam panduan "for dummies". Tawaran saya tetap :)
tomsmeding

2
Punya yang ini untuk mengkompilasi (dan bersaing) dengan baik.
Rainbolt

14

Pelari Kode

Jadi, untuk membuat hal-hal menarik, saya membuat skrip untuk secara otomatis mengunduh kode dari setiap jawaban yang diposting, kompilasi jika perlu, dan kemudian jalankan semua solusi sesuai dengan aturan. Dengan cara ini, orang dapat memeriksa bagaimana kinerja mereka. Simpan saja skrip ini ke run_all.py (memerlukan BeautifulSoup) lalu:

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

Beberapa hal:

  1. Jika Anda ingin menambahkan dukungan untuk lebih banyak bahasa, atau secara alternatif menghapus dukungan untuk beberapa bahasa, lihat def submission_type(lang).
  2. Memperluas skrip harus cukup mudah, bahkan untuk bahasa yang memerlukan kompilasi (lihat CPPSubmission). Jenis bahasa diambil dari tag kode meta < !-- language: lang-java -- >, jadi pastikan untuk menambahkannya jika Anda ingin kode Anda dijalankan (Hapus spasi tambahan sebelum dan sesudah <>). UPDATE : Sekarang ada beberapa kesimpulan yang sangat mendasar untuk mencoba dan mendeteksi bahasa jika tidak didefinisikan.
  3. Jika kode Anda gagal berjalan sama sekali, atau gagal menyelesaikan dalam waktu yang ditentukan, maka kode itu akan ditambahkan ke blacklist.textdan akan dihapus dari uji coba selanjutnya secara otomatis. Jika Anda memperbaiki kode Anda, hapus saja entri Anda dari daftar hitam dan jalankan kembali get,

Bahasa yang didukung saat ini:

 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
}

Tanpa basa-basi:

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

Mengapa tidak ada bahasa Fortran ??
Kyle Kanos

@KyleKanos - Saya menambahkan dukungan untuk itu, akan segera memperbarui kode.
WhatAWorld

Yay! Saya (agak) bekerja keras pada pengajuan Fortran saya & Rusher tidak bisa membuatnya jadi saya ingin seseorang untuk mendapatkannya :)
Kyle Kanos

1
@Rusher: Saya setuju dengan PeterTaylor untuk yang satu ini: penyorotan sintaksis karena hanya edit yang disarankan yang harus ditolak. Pengeditan harus digunakan untuk koreksi besar , bukan hal-hal kecil.
Kyle Kanos

1
Anda memang pantas mendapat perwakilan untuk ini, tetapi karena ini bukan jawaban untuk pertanyaan (dan mungkin bisa mendapat manfaat dari komunitas menambahkan hal-hal untuk bahasa lain) Saya pikir ini secara teknis harus menjadi wiki komunitas.
Martin Ender

13

The Beautiful Mind, Ruby

Membuat keputusan berdasarkan pola signifikansi yang dipertanyakan dalam representasi bit babak terakhir

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

Jalankan seperti

ruby beautiful-mind.rb

13

Piustitious, Lua

Program takhayul yang mempercayai Signs and Wonders.

history = arg[1]

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

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

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

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

jalankan dengan:

lua Piustitious.lua

diikuti oleh input.


11

The Winchesters

Sam dan Dean baik (sebagian besar waktu).

package Humans;

public class TheWinchesters extends Human {

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

}

Apakah Anda yakin 9:1rasio yang tepat? Mungkin kita harus melakukan penambangan data dan mendapatkan rasio yang lebih tepat?
recursion.ninja

1
@awashburn Saya mulai menonton Supernatural 2 bulan yang lalu (sekarang macet di musim 9) dan 9:1sepertinya tidak masalah bagi saya;)
CommonGuy

10

Ahli statistik

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
Baris terakhir kedua itu sangat luar biasa
cjfaure

5
@Userved Selain Math.ceil(Math.random()-Math.random())Anda juga bisa melakukannya Math.round(Math.random()).
tomsmeding

10

R, bot yang agak Bayesian

Gunakan tabel frekuensi untuk setiap pengguna sebagai probabilitas sebelumnya dari output pengguna lain.

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

Dipanggil menggunakan Rscript BayesianBot.Rdiikuti oleh input.

Sunting : Hanya untuk memperjelas apa yang dilakukan ini, berikut adalah langkah demi langkah dengan contoh input:

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

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

Kemudian garis yang dimulai dengan result<-, untuk setiap pemain, memilih secara acak 0 atau 1 menggunakan tabel terakhir ini sebagai bobot (yaitu untuk pemain 1 probabilitas memilih 0 adalah 2/7, dari memilih 1 5/7, dll). Itu mengambil satu hasil untuk setiap pemain / kolom dan akhirnya mengembalikan nomor yang berakhir menjadi yang paling umum.


10

Orang Swiss

Selalu mempertahankan netralitas. Ditakdirkan untuk tidak pernah menang.

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

Saya tidak menulis ini!
Rainbolt

Itu ironi. Netralitas tidak pernah menang
Fabigler

2
@Rusher ah saya mengerti sekarang: D
fabigler

1
Bahkan tidak bisa dikompilasi - ada titik koma yang hilang.
PaĹ­lo Ebermann

9

HAL 9000

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

Sunting: mungkin ini lebih cocok untuk HAL 9000, tapi hati-hati! Itu sangat jahat. Saya sarankan cduntuk mengosongkan direktori sebelum menjalankannya.

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

Ini menghapus satu file dari cwduntuk setiap doa!

Doa yang tidak begitu jelas:

Dalam M $

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

D:>hal_9000.pl
evil

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

Anda perlu memberikan perintah yang dapat digunakan untuk menjalankan program Anda. Lihat bagian "Hasil Kerja" dari tantangan untuk informasi lebih lanjut.
Rainbolt

@Rusher Done;)
core1024

9

Will of the Mayoritas

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

Simpan sebagai WotM.py, jalankan sebagai python3 WotM.pydiikuti oleh input.

Program sederhana, hanya untuk melihat bagaimana itu akan dilakukan. Cocok dengan apa pun yang dikatakan mayoritas terakhir kali, atau acak.


Anda perlu memberikan perintah yang dapat digunakan untuk menjalankan program Anda. Lihat bagian "Hasil Kerja" dari tantangan untuk informasi lebih lanjut.
Rainbolt

Sialan, itu membuat milikku duplikat. : D Mengubah milik saya menjadi minoritas.
Martin Ender

@Rusher Menambahkan perintah. Itu yang kamu cari?
isaacg

@isaacg Sempurna!
Rainbolt

1
Saya menghitung peringkat rata-rata dari skor di papan skor, dan entri ini menang dengan ukuran itu.
Brilliand

9

Alan Shearer

Ulangi apa pun yang dikatakan orang yang duduk di sebelahnya. Jika orang tersebut ternyata salah, ia beralih ke orang berikutnya dan mengulangi apa yang mereka katakan.

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

Anda mereferensi variabel yang dipanggil lastRoundsebelum Anda mendeklarasikannya. Anda juga menambahkan tanda kurung ke semua Anda String.lengthtetapi itu bukan fungsi. Bisakah Anda mendapatkan kiriman Anda ke titik di mana ia akan dikompilasi?
Rainbolt

@Rusher - selesai :)
Algy Taylor

@Algy: lastRound.lengthmasih diakses (di if pertama) sebelum lastRounddideklarasikan (in if's else). Coba kompilasi (dan mungkin jalankan) kode Anda sebelum mengirimkannya di sini.
PaĹ­lo Ebermann

@ PaĹ­loEbermann - permintaan maaf, saya tidak berada di lingkungan di mana saya dapat menjalankannya - amandemen dibuat
Algy Taylor

Sekarang Anda mereferensikan variabel yang disebut "personToCopy" ketika itu di luar jangkauan. Saya baru saja memindahkannya di dalam blok lain sehingga akan dikompilasi, tetapi saya tidak tahu apakah itu yang Anda inginkan.
Rainbolt

8

Nanti adalah Jahat, JavaScript ( node.js )

Mengukur jumlah waktu antara eksekusi. Jika perbedaan waktu lebih besar dari waktu terakhir, itu pasti jahat. Kalau tidak, bagus.

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

Jalankan dengan: node laterisevil.js


8

Pencari Pola, Python

Mencari pola berulang, dan jika tidak dapat menemukannya, cukup gunakan mayoritas.

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

jalankan bersama

python3 pattern_finder.py

1
Saya sangat suka kode ini, ketika saya menjalankannya, selalu mendapatkan 3000 poin, entah bagaimana.
Realdeo

8

Turncoat

Turncoat percaya bahwa karena kombatan lain sejauh ini, mayoritas akan bergantian setelah setiap putaran antara yang baik dan yang jahat lebih sering daripada tetap di sisi yang sama. Dengan demikian ia memulai babak pertama dengan berpihak sewenang-wenang dengan yang baik, kemudian bergantian setiap putaran dalam upaya untuk tetap pada tim yang menang atau kalah lebih sering daripada tidak.

package Humans;

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

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

Setelah menulis ini, saya menyadari bahwa karena entri yang didasarkan pada analisis statistik, momentum akan menyebabkan mayoritas untuk beralih sisi lebih sedikit karena lebih banyak putaran telah selesai. Karena itu, Malas Turncoat.

The Malas Turncoat

Lazy Turncoat dimulai seperti Turncoat, tetapi ketika putaran berlalu, ia menjadi semakin malas untuk beralih ke sisi lain.

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 luar biasa!
Angelo Fuchs

Saya termasuk keduanya jika Anda tidak keberatan.
Rainbolt

Lanjutkan. Saya ingin tahu bagaimana keduanya akan melakukan, terutama vs yang menyusun statistik pemungutan suara.
jaybz

@Rainbolt Saya baru saja melihat bug bodoh dengan Turncoat. Tidak perlu memperbaikinya. Ini masih berfungsi, tidak sepenuhnya seperti yang dimaksudkan, dan bahkan jika belum terlambat untuk memperbaikinya, memperbaikinya hanya akan membuatnya berperilaku persis seperti salah satu entri yang lebih baru. Jangan ragu untuk memasukkan / mengecualikan jika Anda mau.
jaybz

8

Penulis biografi, 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]

Upaya saya pada entri yang hampir cerdas (yang benar-benar cerdas akan membutuhkan pengujian terhadap bidang). Ditulis dalam Ruby, jadi ada kemungkinan ini akan terlalu lambat, tetapi pada komputer saya, ini membutuhkan 0,11 detik untuk menghitung putaran terakhir ketika ada 40 pemain acak, jadi saya harap ini akan bekerja dengan cukup baik.

simpan sebagai biographer.rb, jalankan sebagairuby biographer.rb

Idenya adalah bahwa untuk setiap pemain, itu memperkirakan peluang mereka untuk memilih "baik" dengan melihat kedua pilihan mereka sendiri untuk sepuluh putaran terakhir, dan hasil keseluruhan, dan menemukan contoh di masa lalu di mana keadaan yang sama (suara mereka + keseluruhan hasil) terjadi. Ini mengambil tampilan terpanjang di belakang panjang, hingga 10 putaran, sehingga ada preseden, dan menggunakannya untuk membuat frekuensi (disesuaikan sesuai dengan Hukum Suksesi Laplace, sehingga kami tidak pernah 100% yakin tentang siapa pun).

Kemudian menjalankan beberapa simulasi dan melihat seberapa sering Good menang. Jika simulasi ternyata sebagian besar dengan cara yang sama, maka itu mungkin akan melakukan prediksi dengan baik secara umum sehingga mengambil prediksi minoritas. Jika tidak percaya diri, ia memilih mayoritas yang diprediksi.


8

Lubang di pintu

Yudas adalah orang yang sangat baik. Sangat disayangkan dia akan mengkhianati orang baik untuk beberapa sen.

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
Ini hanya pernah memberikan suara jahat jika ada cukup peserta, Anda mungkin ingin menghapus ,dari history, bahkan lebih sehingga Rusher akan berpisah permainan dalam kelompok.
Angelo Fuchs

Saya tidak tahu dia akan membagi permainan dalam kelompok. Saya sebenarnya menunggu pertanyaan ini untuk memiliki cukup kiriman sebelum memposting jawaban saya karena ukuran string. Terima kasih telah memberi tahu saya.
William Barbosa

Jika Anda tahu cara meneruskan argumen 60000 karakter ke proses di Windows, beri tahu saya. Jika tidak, maaf karena mengacaukan entri Anda, dan terima kasih telah memperbaikinya! Saya tidak mengantisipasi menerima begitu banyak kiriman.
Rainbolt

7

The Fallacious Gambler (Python)

Jika satu pihak telah memenangkan mayoritas beberapa kali berturut-turut, penjudi menyadari bahwa pihak lain lebih mungkin menjadi mayoritas putaran berikutnya (kan?) Dan ini mempengaruhi suaranya. Dia mengincar minoritas, karena jika dia berhasil menjadi minoritas begitu dia akan berhasil di sana beberapa kali (kan?) Dan mendapatkan banyak poin.

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  

Pemakaian

Untuk babak pertama:

python gambler.py

dan sesudahnya:

python gambler.py 101,100,001 etc.

4
Saya suka bagaimana Anda tampaknya yakin tentang kode Anda, bukan? : P
IEatBagels

7

Otomat Seluler

Ini menggunakan aturan konvensional untuk Permainan Kehidupan Conway untuk memilih pihak. Pertama, kisi 2D dibuat dari suara sebelumnya. Kemudian, "dunia" melangkah maju satu tahap, dan jumlah total sel hidup yang tersisa dihitung. Jika jumlah ini lebih besar dari setengah jumlah total sel, "baik" dipilih. Kalau tidak, "kejahatan" dipilih.

Maafkan kesalahan apa pun, ini hancur selama jam makan siang saya. ;)

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
Saya menghapus baris cetak dari kode untuk pengujian .. Entri Java hanya perlu mengembalikan yang baik atau jahat, bukan mencetaknya.
Rainbolt

7

Profesor Ridge

Saya harap menggunakan perpustakaan diperbolehkan, jangan merasa seperti melakukan ini tanpa satu =)

Ide dasarnya adalah untuk melatih classifier regresi ridge untuk setiap peserta pada putaran terakhir, menggunakan 30 hasil sebelum setiap putaran sebagai fitur. Awalnya termasuk babak terakhir hasil untuk semua pemain untuk memprediksi hasil untuk setiap pemain juga, tapi itu memotongnya agak dekat untuk waktu ketika jumlah peserta semakin besar (katakanlah, 50 atau lebih).

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

Untuk Mengkompilasi

Simpan kode sumber dalam file yang disebut ridge_professor.cc, unduh perpustakaan Eigen dan unzip folder Eigen yang ditemukan di dalam folder yang sama dengan file sumber. Kompilasi dengan g++ -I. -O3 -ffast-math -o ridge_professor ridge_professor.cc.

Untuk berlari

panggil ridge_professor.exe dan berikan argumen yang diperlukan.

Pertanyaan

Karena saya belum bisa berkomentar di mana saja, saya akan bertanya di sini: bukankah ukuran argumen pada windows membuatnya tidak mungkin untuk memanggil binari yang dihasilkan dengan seluruh sejarah pada beberapa ratus putaran? Saya pikir Anda tidak dapat memiliki lebih dari ~ 9000 karakter dalam argumen ...


Terima kasih telah menarik perhatian saya pada ini . Saya akan mencari cara untuk membuatnya berfungsi jika belum berfungsi dengan baik di Jawa. Jika Java tidak dapat melakukannya, penelitian memberi tahu saya bahwa C ++ dapat, dan saya akan mengambil kesempatan untuk mempelajari kembali C ++. Saya akan segera kembali dengan hasil tes.
Rainbolt

Ternyata, Java tidak tunduk pada batasan command prompt. Tampaknya hanya perintah yang lebih besar dari 32k yang menyebabkan masalah. Inilah bukti saya (saya menulisnya sendiri): docs.google.com/document/d/… . Sekali lagi, saya sangat menghargai Anda membawa ini sebelum uji coba dimulai besok.
Rainbolt

@Rusher Sudah ada 57 bot dan Anda berencana untuk setiap run yang terdiri dari 1000 putaran. Itu akan membuat string Anda 57k karakter (karena itu> 32k), bukan?
plannapus

1
@Rusher Saya pikir mungkin lebih baik untuk memperpanjang waktu seminggu lagi dan meminta peserta untuk mengubah program mereka untuk membaca stdin daripada menggunakan string argumen. Akan sepele bagi sebagian besar program untuk berubah
dgel

@dgel Garis waktu untuk tantangan sangat panjang, tapi saya tidak ingin mengubah aturan dengan cara yang harus ditulis ulang oleh setiap orang. Saya cukup yakin bahwa aturan yang saya tambahkan tadi malam hanya akan mengacaukan satu kiriman, dan saya berencana membantu orang itu jika ia pernah mendapatkan programnya ke titik di mana ia dikompilasi.
Rainbolt

6

Crowley

Karena Winchesters jauh lebih menarik tanpa orang ini. Dia jelas memihak kejahatan ... kecuali jika dibutuhkan untuk mengurus kejahatan yang lebih besar.

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

Saya melihat dua putaran terakhir (0 koma sejauh ini dan 1 koma sejauh ini) dan jika keduanya membiarkan kejahatan menang, saya memilih yang baik. Kalau tidak, saya memilih yang jahat.


Apakah saya benar? Anda melihat pada belokan terakhir dan jika kurang dari 50% suara "baik" Anda memihak "baik" lain dengan kejahatan? (Karena penasaran: Apakah Anda lebih suka nama-nama variabel samar atau itu kecelakaan?)
Angelo Fuchs

1
@AngeloNeuschitzer Saya melihat dua putaran terakhir (0 koma sejauh ini dan 1 koma sejauh ini) dan jika keduanya membiarkan kejahatan menang, saya memilih yang baik. Kalau tidak, saya memilih yang jahat. Saya lebih suka nama variabel yang pendek untuk mengetik jika kode cukup pendek tujuan kode tidak akan bingung. Saya bukan programmer profesional dan ini adalah pertama kalinya saya memprogram di java atau sesuatu yang orang lain lihat kode dalam 6,5 tahun. Saya menulis ini untuk menyegarkan ingatan saya (TLDR. Mereka tidak samar bagi saya dan saya satu-satunya yang biasanya saya kode untuk.)
kaine

Untuk kejelasan ... Crowley mulai sebagai manusia jadi disengaja dia mulai baik ... Tidak menyangka dia tetap baik untuk semua putaran meskipun ... sialan
kaine
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.