Хорошо против зла

112

Результаты - 19 июля 2014 г.

Текущий Король Холма - Наемник от пользователя Fabigler ! Продолжайте представлять записи и сбить его с трона!

Нажмите здесь, чтобы посмотреть табло.

Программы, представленные 19 июля 2014 года или ранее, были включены. Все остальные материалы будут включены в будущие испытания. Новые результаты должны быть опубликованы около 9 августа, так что у вас будет достаточно времени.


Иллюстрация, нарисованная братом Иллюстрированный Крисом Рейнболтом, моим братом и выпускником колледжа искусств и дизайна Саванны.

Введение

Ангелы и демоны сражаются и, как обычно, используют землю в качестве своего поля битвы. Люди застряли в середине и вынуждены принять сторону. Неизвестная нейтральная сила вознаграждает тех, кто последовательно сражается за проигравшую сторону.

Игра

Каждое испытание, вы будете псевдослучайно в паре, а затем перетасовано от 20 до 30 других представлений. Каждое испытание будет состоять из 1000 раундов. Каждый раунд, вы будете проходить ввод и ожидается, что будет производить вывод. Ваш вывод будет записан и оценен. Этот процесс будет повторяться 1000 раз.

вход

Вы получите один аргумент, который представляет прошлые голоса каждого игрока. Раунды разделены запятой. А 0представляет игрока, который принял сторону Зла в этом раунде. A 1представляет игрока, который встал на сторону Good. В течение испытания игроки всегда будут в том же порядке. Ваш собственный голос будет включен, но не определен явно. Например:

101100100

В этом примере три раунда были завершены, и три игрока соревнуются. Первый игрок всегда на стороне хорошего. Второй игрок всегда на стороне зла. Игрок третий поменялся местами с Добра в 1-м раунде на Зло в 2-м и 3-м турах. Одним из этих игроков был вы.

Выход

Представления Java

  • Верните строку, goodесли вы хотите принять сторону Good.
  • Верните строку, evilесли вы хотите принять сторону зла.

Представления не Java

  • Выведите строку goodв stdout, если вы хотите принять сторону Good.
  • Выведите строку evilв stdout, если вы хотите принять сторону зла.

Если ваша программа выводит или возвращает что-то еще, выдает исключение, не компилирует или занимает более одной секунды, чтобы вывести что-либо на этом конкретном компьютере , это будет дисквалифицировано.

счет

Результаты будут опубликованы в электронной таблице Google для легкого просмотра, как только я смогу скомпилировать все текущие записи. Не волнуйтесь - я буду продолжать испытания до тех пор, пока вы, ребята, продолжаете отправлять программы!

  • Вы получаете 3 очка за то, что встали на сторону большинства в течение раунда.
  • Вы получаете n - 1 балл за то, что встали на сторону меньшинства в течение раунда, где n - это количество раз, которое вы на стороне меньшинства.

Ваша оценка будет медиана 5 испытаний. Каждое испытание состоит из 1000 раундов.

Практические результаты

Представления не Java

Вы должны предоставить уникальный заголовок, программу и строку командной строки Windows, которые будут запускать вашу программу. Помните, что аргумент может быть добавлен к этой строке. Например:

  • python Angel.py
    • Обратите внимание, что у этого нет аргументов. Это раунд один! Будьте готовы к этому.
  • python Angel.py 11011,00101,11101,11111,00001,11001,11001

Представления Java

Вы должны предоставить уникальный заголовок и класс Java, который расширяет абстрактный класс Human, написанный ниже.

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

тестирование

Если вы хотите проверить свою заявку, следуйте инструкциям здесь .

Дополнительные примечания

Вы можете подавать столько разных заявок, сколько пожелаете. Представления, которые кажутся сговорщиками, будут дисквалифицированы. Автор этого вызова будет единственным судьей по этому вопросу.

Новый экземпляр вашей программы или класса Java будет создаваться при каждом вызове. Вы можете сохранить информацию, записав в файл. Вы не можете изменять структуру или поведение чего-либо, кроме вашего собственного класса.

Игроки будут перетасованы до начала игры. Демон и Ангел будут участвовать в каждом испытании. Если число игроков четное, к ним присоединится и Петр Баелиш. Демоны сражаются за зло, Ангел за добро, а Петр Бейлиш выбирает псевдослучайную сторону.

Rainbolt
источник
2
Комментарии были удалены, так как они устарели и по запросу ОП. Пожалуйста, сообщите мне о любых комментариях, которые необходимо восстановить.
Дверная ручка
7
Вау, ОП меняет свое имя пользователя. Итак, когда будет отображаться результат?
полугодие
6
@Rainbolt Должно быть, это чертовски тяжелая работа, это вызов! Причиной такого количества внимания является простота протокола и правил, делающих его доступным, а также допускающих простые, рабочие записи. TL; DR: Ваш вызов слишком хорош! : D
Томсминг
3
@dgel Я опубликую необработанные данные, верхние, нижние, средние значения и, возможно, линейный график, чтобы мы могли видеть, кто добился большего успеха по мере роста конкуренции.
Rainbolt
6
Одна из коробочек закончилась 10 записями, которые голосовали каждый раз одинаково. Следовательно, два пользователя получили идеальный результат или «один раунд без идеальных» оценок около 450 000. Те же записи набрали около 1900 в других испытаниях. Средний балл близок к 2000 году. Из-за крайнего дисбаланса в результатах я решил, что более значимым будет среднее значение. Я отредактировал задание так, чтобы после 5 испытаний победителем была заявка с наибольшим медианой. Если кто-то думает, что переход от среднего к среднему является несправедливым или плохим выбором, прокомментируйте.
Rainbolt

Ответы:

11

Наемник

Всегда на стороне того, кто заплатил больше всего денег в последнем раунде.

Учитывая, что хорошие люди зарабатывают статистически больше.

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

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

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

        if (goodMoneyPaid > evilMoneyPaid)
        {
            return "good";
        } else {
            return "evil";
        }
    }
}
fabigler
источник
2
Это второй пост, чтобы сказать что-то о деньгах. Я пропускаю ссылку или что-то?
Рейнболт
Правда, но этот парень еще более злой ублюдок. Бросаю своих друзей каждый ход, только ради денег.
fabigler
В вашем операторе switch отсутствует оператор return для случая по умолчанию, из-за чего он не компилируется. Я добавил случайный.
Рейнболт
4
Поздравляю, король горы! Я не понимаю, как эта запись побеждает. Хотите добавить объяснение, теперь, когда к нему прикреплена награда в 300 репутаций?
Rainbolt
4
Возможно, ошибка, или я неправильно понял комментарии и описание, но наемник на самом деле не делает то, что должен был сделать. За исключением первого случайного раунда, он всегда будет на стороне зла, если менее чем 1/6 людей проголосовали за зло в предыдущем раунде.
Джейбз
39

Хипстер, рубин

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

Просто идет с меньшинством последнего раунда, просто потому что все остальное является мейнстримом.

Беги как

ruby hipster.rb
Мартин Эндер
источник
30

Петир Баелиш

Никогда не знаешь, на чьей стороне Петр Баелиш.

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

Эта запись будет включена, только если количество игроков четное. Это гарантирует, что всегда будет большинство.

Rainbolt
источник
28
Со стороны Петра Баелиша, очевидно.
Ктулху
2
@Kevin Это постоянно бьет большинство ботов. Обычно это 27 баллов.
cjfaure
3
@Kevin Эта запись была предоставлена ​​автором конкурса. Это не предназначалось, чтобы преуспеть. Он существует, чтобы быть уверенным, что всегда будет большинство, потому что при четном количестве игроков может быть ничья.
Рейнболт
4
Боже, почему этот получил наибольшее количество голосов? Это просто нечестно .
Томсминг
3
@tomsmeding Нет. Это цитата из Игры престолов, смеется.
Рейнболт
29

C ++, мета-ученый

Этот по сути тот же, что и «Ученый», но действует не на раунды в целом, а на отдельных игроков. Он пытается отобразить волну (или постоянную функцию) для каждого игрока в отдельности и предсказывает их движение в следующем раунде. Исходя из предсказания, полученного в результате раунда, мета-ученый выбирает ту сторону, которая имеет большинство.

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

#define WINDOW (200)

using namespace std;

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

Если вы хотите включить операторы отладки, измените чтение строки #if 0на #if 1.

Скомпилируйте с g++ -O3 -std=c++0x -o MetaScientist MetaScientist.cpp(вам не нужны предупреждения, поэтому нет -Wall) и запустите с MetaScientist.exe(возможно, включая аргумент, конечно). Если вы спросите действительно хорошо, я могу предоставить вам исполняемый файл Windows.

РЕДАКТИРОВАТЬ: Судя по всему, предыдущая версия исчерпала время около 600 раундов в игру. Это не должно делать это. Его время контролируется #define WINDOW (...)линией, больше медленнее, но смотрит назад.

tomsmeding
источник
2
Я смиренно предлагаю вам попытаться выбрать проигравшую сторону. Если вы сможете правильно угадывать, вы получите более 3 очков за раунд.
Кевин
1
@Kevin Это правда, но я подумал, что это может угадать неправильную сторону довольно быстро, и вам нужно правильно угадать проигравшую сторону более семи раз подряд, чтобы получить улучшение по сравнению с тем, чтобы всегда получать правильное большинство. Я мог бы изменить это все же.
Томсминг
1
@Kevin Кроме того, я сначала хотел бы увидеть, как это происходит (ученый и мета-ученый), когда Рашер получает нам табло на этих выходных, как он указал в комментариях к ОП. Рашер, извини, но я слишком ленив, чтобы собрать все вещи сам ... :)
Томсминг
3
Не волнуйтесь! Вероятно, в любом случае запускать их небезопасно. Просто позвольте мне испортить мою машину с кодом, написанным 50 незнакомцами в Интернете.
Рейнболт
1
@Kevin Но это так МНОГО ! Я действительно могу, но мне это не нравится. Я посмотрю, как эти тарифы.
Томсминг
26

ангел

Самый чистый игрок из всех.

программа

print "good"

команда

python Angel.py
Rainbolt
источник
22
Python - хороший язык Кажется естественным, что Ангел использует это.
jpmc26
23
Позвольте напомнить людям, что Питон - это Змея. Змей.
Мистер Листер
3
@MrLister Могу я напомнить вам, что Люцифер был великим Ангелом, прежде чем Бог изгнал его с небес?
Зиббобз
1
@Zibbobz Да ... действительно позор, что они выпали. Они могли бы многого достичь вместе.
Мистер Листер
24

Артемида Фаул

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

В книге 7, The Atlantis Complex , Артемис Фаул контракт психологического заболевания ( так называемый Атлантида комплексом) , который заставил его сделать все , что в упаковке 5 (говорение, действий и т.д.). Когда он не мог сделать это в кратном 5, он запаниковал. Я делаю в основном это: вижу, делится ли добро или зло (преднамеренное смещение) на 5, если нет, то я паникую и вижу, что было лучше, бегаю с этим или паникую еще дальше и случайно выбираю.

Кайл Канос
источник
4
Когда я читал «Артемис Фаул» в средней школе, существовали только две книги. Приятно видеть, что сейчас их семь, и что Дисней делает это в кино.
Рейнболт
1
Там на самом деле 8 книг.
Кайл Канос
7
Чем больше, тем лучше (если вы не читаете Колесо Времени)
Rainbolt
1
И ты забыл break;в своем switch.
johnchen902
1
@ johnchen902, @ Manu: Я не очень опытен в Java (я использую Fortran90 + и вижу только Java здесь), отсюда и мои ошибки. Я исправлю их, когда доберусь до офиса через час.
Кайл Канос
19

Disparnumerophobic

Нечетные числа ужасают.

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";
    }
}
pseudonym117
источник
17
Комментарий заставил меня смеяться / фыркать.
phyrfox
17

Линус, Рубин

Стремится обескуражить аналитиков, всегда нарушая схему .

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

Сохранить как linus.rbи запустить сruby linus.rb

histocrat
источник
16

BackPacker

Определяет игрока, который больше всего выбрал соответствующее меньшинство и выбирает свой последний голос.

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

Определяет игрока, который больше всех выбрал совпадающее большинство, и выбирает свой последний голос.

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;
    }
}
Анджело Фукс
источник
Очень чистая программа!
Рейнболт
Ой, я думаю, что я, возможно, скопировал вашу программу на другом языке.
PyRulez
@Rusher Я обновил код и хотел бы добавить это как две записи, одна с goWithMajority = trueи одна, где его false. Это нормально, или мне нужно добавить второй BackPacker для этого?
Анджело Фукс
@AngeloNeuschitzer Я редактировал этот пост. Таким образом, я не забуду добавить обе заявки. Я предлагаю вам изменить действительно нетворческое имя, которое я дал, и, возможно, добавить описание к обоим, если хотите.
Рейнболт
1
@Rainbolt Мне больше нравится ваш FrontPacker. Lol'd.
Томсминг
15

Предсказатель

Это все еще в стадии разработки. Я еще не проверял это. Я просто хотел посмотреть, считает ли ОП, что это нарушает правила или нет.

Идея состоит в том, чтобы смоделировать следующий раунд, выполнив несколько других участников, чтобы получить вероятность результата и действовать соответственно.

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

}
Андрис
источник
Если ваш бот запускает все остальные боты каждый ход, прежде чем ответить, не займет ли это больше 1 секунды, чтобы ответить?
plannapus
@plannapus Я собираюсь предположить, что с этим ботом предполагается, что все остальные будут ошибаться и избегать чего-либо, близкого к ожиданию в течение 1 секунды. Я думаю, что, возможно, стоит подать заявку и запись, состоящую из 0,9 секундного ожидания, прежде чем вернуть «хорошо», просто чтобы поиграть с ним. На самом деле, SBoss побил меня этим: D
scragar
Yahhh! Тогда мне придется занести этот бот в черный список. Это было бы неприятно ... Также с разными записями в разных средах, таких как Python или Perl, повторной загрузки интерпретатора может быть достаточно, чтобы вывести этот код сверх лимита времени.
Андрис
16
Если кто-то делает то же самое, что и вы, вы получаете бесконечный цикл.
Brilliand
4
Время подачи истекло. Я прикрепил профилировщик, и почти полсекунды тратится на вызов некоторых представлений. По крайней мере, это работает, так что поздравляю с этим.
Рейнболт
15

C ++, Ученый

Этот пытается, с историей того, что большинство выбрало за раунд wave( majority()дает выбор большинства на раунд), согласовать волну с данными, длиной волны 2*periodи фазой phase. Таким образом, учитывая, что 0,1,1,1,0,1,0,1,1,1,0,0,0,1,0он выбирает period=3, phase=5( maxat=={3,5}): его оценки становятся 9 3 11 5 5 3 5 7 9 7 7 7 7 7 7. Он зацикливается на все возможные периоды и, если для этого периода счет выше, чем для текущего максимума, он сохраняет, {period,phase}для которого это произошло.

Затем он экстраполирует найденную волну на следующий раунд и принимает предсказанное большинство.

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

Скомпилируйте с g++ -O3 -std=c++0x -o Scientist Scientist.cpp(вам не нужны предупреждения, поэтому нет -Wall) и запустите с Scientist.exe(возможно, включая аргумент, конечно). Если вы спросите действительно хорошо, я могу предоставить вам исполняемый файл Windows.

О, и не смей возиться с форматом ввода. В противном случае он будет делать странные вещи.

РЕДАКТИРОВАТЬ: Судя по всему, предыдущая версия исчерпала время около 600 раундов в игру. Это не должно делать это. Его время контролируется #define WINDOW (...)линией, больше медленнее, но смотрит назад.

tomsmeding
источник
8
Загрузка исполняемых файлов, написанных шестьюдесятью незнакомцами в Интернете, кажется плохой идеей.
Рейнболт
@Rusher Я полностью согласен. Если вам нужны проблемы, это первый шаг в руководстве "для чайников". Мое предложение остается в
силе
2
Получил этот, чтобы скомпилировать (и конкурировать) нормально.
Рейнболт
14

Код бегун

Итак, чтобы было интересно, я создал скрипт, который автоматически загружает код из каждого опубликованного ответа, компилирует его при необходимости, а затем запускает все решения в соответствии с правилами. Таким образом, люди могут проверить, как у них дела. Просто сохраните этот скрипт в run_all.py (требуется BeautifulSoup) и затем:

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

Несколько вещей:

  1. Если вы хотите добавить поддержку большего количества языков или, в качестве альтернативы, удалить поддержку для некоторых, см def submission_type(lang).
  2. Расширение сценария должно быть довольно простым, даже для языков, которые требуют компиляции (см. CPPSubmission). Тип языка извлекается из тега мета-кода < !-- language: lang-java -- >, поэтому обязательно добавьте его, если хотите, чтобы ваш код запускался (удалите лишние пробелы до и после <>). ОБНОВЛЕНИЕ : теперь есть некоторый чрезвычайно простой вывод, чтобы попытаться обнаружить язык, если он не определен.
  3. Если ваш код не запускается вообще или не завершается в течение отведенного времени, он будет добавлен blacklist.textи будет удален из будущих испытаний автоматически. Если вы исправить код, просто удалить запись из черного списка и повторного запуска get,

Поддерживаемые в настоящее время языки:

 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
}

Без дальнейших церемоний:

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
WhatAWorld
источник
Почему нет языка фортран ??
Кайл Канос
@KyleKanos - я добавил поддержку, скоро обновлю код.
WhatAWorld
Ура! Я (Сорта) усердно работал над своим представлением на Фортране, и Рашер не может заставить его работать, поэтому я хотел бы, чтобы кто-то получил это :)
Кайл Канос,
1
@Rusher: Я согласен с PeterTaylor в этом: подсветка синтаксиса, поскольку единственное предложенное редактирование должно быть отклонено. Правки должны использоваться для существенных исправлений , а не мелочи.
Кайл Канос
1
Вы заслуживаете репутации для этого, но так как это не совсем ответ на вопрос (и, вероятно, может быть полезно, если сообщество добавит материал для других языков), я думаю, что технически это должна быть вики сообщества.
Мартин Эндер
13

Прекрасный разум, Рубин

Принимает решение на основе сомнительных шаблонов в битовом представлении последнего раунда

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

Беги как

ruby beautiful-mind.rb
Мартин Эндер
источник
13

Piustitious, Луа

Суеверная программа, которая верит в Знамения и Чудеса.

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

запустить его с:

lua Piustitious.lua

с последующим вводом.

AndoDaan
источник
11

Винчестеры

Сэм и Дин хороши (большую часть времени).

package Humans;

public class TheWinchesters extends Human {

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

}
CommonGuy
источник
Вы уверены, что 9:1это правильное соотношение? Может быть, нам следует провести анализ данных и получить более точное соотношение?
recursion.ninja
1
@awashburn Я начал смотреть «Сверхъестественное» 2 месяца назад (сейчас застрял в 9-м сезоне), и 9:1мне это кажется нормальным;)
CommonGuy
10

статистик

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
Эта вторая последняя строчка такая
классная
5
@ Незаслуженно вместо Math.ceil(Math.random()-Math.random())тебя тоже можно делать просто Math.round(Math.random()).
Томсминг
10

R, несколько байесовский бот

Используйте таблицу частот для каждого пользователя в качестве априорной вероятности вывода других пользователей.

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

Вызывается с помощью, Rscript BayesianBot.Rа затем вводится.

Изменить : просто чтобы уточнить, что это делает, вот пошаговый пример ввода:

> 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

Затем линия, начинающаяся с result<-, для каждого игрока выбирает случайным образом либо 0, либо 1, используя эту последнюю таблицу в качестве весов (т. Е. Для игрока 1 вероятность выбора 0 составляет 2/7, выбора 1 5/7 и т. Д.). Он выбирает один результат для каждого игрока / колонки и, наконец, возвращает число, которое закончилось как наиболее распространенное.

plannapus
источник
10

швейцарцы

Всегда поддерживает нейтралитет. Обречен никогда не побеждать.

package Humans;

/**
 * Never choosing a side, sustaining neutrality
 * @author Fabian
 */
public class Swiss extends Human {   
    public String takeSides(String history) {
        return "neutral"; // wtf, how boring is that?
    }
}
fabigler
источник
Я не писал это!
Рейнболт
Это ирония. Нейтралитет никогда не побеждает
потрясающий
2
@Rusher ах я понял сейчас: D
fabigler
1
Он даже не компилируется - пропущена точка с запятой.
Paŭlo Ebermann
9

HAL 9000

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

Изменить: возможно, это больше подходит для HAL 9000, но будьте осторожны! Это очень зло. Я рекомендую cdочистить каталог перед его запуском.

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

Это удаляет один файл cwdдля каждого вызова!

Не очень очевидный вызов:

В М $

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

D:>hal_9000.pl
evil

В * nix

[core1024@testing_pc ~]$ tee hal_9000.pl
#!/usr/bin/env perl
print eval("evil")
# Press C-D here
[core1024@testing_pc ~]$ chmod +x $_
[core1024@testing_pc ~]$ ./$_
evil[core1024@testing_pc ~]$
core1024
источник
Вам необходимо указать команду, которую можно использовать для запуска вашей программы. См. Раздел «Результаты» для получения дополнительной информации.
Рейнболт
@Rusher Done;)
core1024
9

Воля большинства

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

Сохраните как WotM.py, запустите как python3 WotM.pyследует после ввода.

Простая программа, просто чтобы посмотреть, как она будет работать. Идет с тем, что большинство говорило в прошлый раз, или иначе.

isaacg
источник
Вам необходимо указать команду, которую можно использовать для запуска вашей программы. См. Раздел «Результаты» для получения дополнительной информации.
Рейнболт
Черт возьми, это делает мою копию. : D поменял мой на меньшинство.
Мартин Эндер
@Rusher Добавил команду. Это то, что вы искали?
Исаак
@isaacg Отлично!
Рейнболт
1
Я вычислил средний рейтинг по оценкам на табло, и эта запись побеждает по этому показателю.
Brilliand
9

Алан Ширер

Повторяет то, что только что сказал человек, с которым он сидит рядом. Если человек оказывается неправ, он переходит к следующему человеку и вместо этого повторяет то, что они говорят.

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";
        }
    }
}
Алджи Тейлор
источник
Вы ссылаетесь на переменную, вызванную еще lastRoundдо того, как вы ее объявили. Кроме того, вы добавили круглые скобки ко всем своим, String.lengthно это не функция. Можете ли вы получить ваше представление к точке, где оно будет компилироваться?
Рейнболт
@Rusher - готово :)
Алджи Тейлор
@Algy: lastRound.lengthвсе еще доступен (в первом if) до того, lastRoundкак объявлен (в этом случае if). Пожалуйста, попробуйте скомпилировать (и, возможно, запустить) свой код, прежде чем отправлять его здесь.
Пауло Эберманн
@ PaŭloEbermann - извиняюсь, я не в такой среде, где я могу это сделать - поправка сделана
Algy Taylor
Теперь вы ссылаетесь на переменную personToCopy, когда она выходит из области видимости. Я просто переместил его внутрь блока else, чтобы он компилировался, но я не знаю, хотел ли ты этого.
Рейнболт
8

Позже это зло, JavaScript ( node.js )

Измеряет количество времени между казнями. Если разница во времени больше, чем в прошлый раз, это должно быть зло. В остальном хорошо.

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

Бежать с: node laterisevil.js

nderscore
источник
8

Pattern Finder, Python

Ищет повторяющийся шаблон, и если он не может найти его, просто идет с большинством.

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

бежать с

python3 pattern_finder.py
CesiumLifeJacket
источник
1
Мне очень нравится этот код, когда я его запускаю, он всегда получает 3000 очков.
Realdeo
8

Отступник

Отступники считают, что из-за других участников боевых действий большинство после каждого раунда будет чередовать добро и зло чаще, чем на одной стороне. Таким образом, он начинает первый раунд с того, что произвольно переходит на сторону добра, а затем чередует каждый раунд в попытке остаться в выигрышной или проигравшей команде чаще, чем нет.

package Humans;

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

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

После написания этого я понял, что из-за записей, основанных на статистическом анализе, импульс заставил бы большинство переходить на другую сторону меньше, поскольку больше раундов было завершено. Отсюда и ленивый перебежчик.

Ленивый перебежчик

Ленивый перебежчик начинает, как перебежчик, но по мере прохождения раундов он становится все ленивее и ленивее переключаться на другую сторону.

package Humans;

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

        return choice < between ? "good" : "evil";
    }
}
jaybz
источник
2
Ленивый перебежчик великолепен!
Анджело Фукс
Я включаю оба, если не возражаешь.
Рейнболт
Преуспевать. Мне любопытно посмотреть, как они оба будут делать, особенно те, которые собирают статистику голосования.
Джейбз
@Rainbolt Я только что заметил глупую ошибку с перебежчиком. Нет необходимости исправлять это все же. Он по-прежнему работает, но не совсем так, как задумано, и даже если еще не поздно исправить это, исправление приведет к тому, что он будет вести себя точно так же, как одна из новых записей в любом случае. Не стесняйтесь включать / исключать, если хотите.
jaybz
8

Биограф, Рубин

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]

Моя попытка почти интеллектуального вступления (на самом деле интеллектуальный требовал тестирования на поле). Написано на Ruby, так что есть вероятность, что это будет слишком медленно, но на моем компьютере все равно требуется 0,11 секунды для расчета последнего раунда, когда в нем 40 случайных игроков, поэтому я надеюсь, что он будет работать достаточно хорошо.

сохранить как biographer.rb, запустить какruby biographer.rb

Идея состоит в том, что для каждого игрока он оценивает свои шансы на выбор «хорошо», рассматривая как свои собственные выборы за последние десять раундов, так и общие результаты, а также находя в прошлом случаи, когда были идентичные обстоятельства (их голоса + общее число). результаты) произошло. Он выбирает самую длинную длину взгляда за спину, до 10 раундов, так что есть какой-то прецедент, и использует ее для создания частоты (скорректированной в соответствии с Законом о наследовании Лапласа, чтобы мы никогда не были на 100% уверены ни в ком).

Затем он запускает некоторые симуляции и видит, как часто добро побеждает. Если моделирование получилось в основном таким же образом, то, вероятно, в общем случае прогнозирование будет успешным, поэтому будет выбрано предсказанное меньшинство. Если он не уверен, он выбирает предсказанное большинство.

histocrat
источник
8

Иуда

Иуда действительно хороший человек. Жаль, что он предаст хороших парней за несколько копеек.

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
Это только когда-либо говорит о зле, если есть достаточно участников, вы можете удалить ,их history, даже больше, так как Рашер собирается разделить игру на группы.
Анджело Фукс
Я не знал, что он собирается разделить игру на группы. Я действительно ждал этого вопроса, чтобы получить достаточно представлений, прежде чем опубликовать свой ответ из-за размера строки. Спасибо, что дал мне знать.
Уильям Барбоза,
Если вы знаете, как передать аргумент в 60000 символов процессу в Windows, дайте мне знать. В противном случае, извините за испорченную запись, и спасибо за исправление! Я не ожидал получить так много представлений.
Рейнболт
7

Ложный Игрок (Питон)

Если одна сторона выиграла большинство раз несколько раз подряд, игрок понимает, что другая сторона с большей вероятностью станет большинством в следующем раунде (верно?), И это влияет на его голос. Он стремится к меньшинству, потому что, если он превратит это в меньшинство, однажды он может сделать это несколько раз (верно?) И получить много очков.

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  

использование

Для первого раунда:

python gambler.py

и потом:

python gambler.py 101,100,001 etc.
коммандос
источник
4
Мне нравится, как вы уверены в своем коде, верно? : P
IEatBagels
7

Сотовый Автомат

Это использует общепринятые правила игры жизни Конвея, чтобы выбрать сторону. Сначала создается 2D сетка из предыдущих голосований. Затем «мир» продвигается на одну ступень вперед и вычисляется общее количество оставшихся живых клеток. Если это число больше половины общего количества ячеек, выбирается «хорошо». В противном случае «зло» выбрано.

Пожалуйста, простите любые ошибки, это было разбито во время моего обеденного часа. ;)

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
Я удалил строку печати из кода для тестирования. Записи Java должны возвращать только добро или зло, а не печатать их.
Рейнболт
7

Хребет Профессор

Я надеюсь, что использование библиотек разрешено, не хочется делать это без одного =)

Основная идея состоит в том, чтобы обучить классификатор регрессии гребня для каждого участника в последних раундах, используя 30 результатов перед каждым раундом в качестве функций. Первоначально включал в себя последний раунд результатов для всех игроков, чтобы предсказать результат для каждого игрока, но это сокращало его довольно близко для времени, когда число участников увеличивается (скажем, 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;
    }
}

Скомпилировать

Сохраните исходный код в файле с именем ridge_professor.cc, загрузите библиотеку Eigen и разархивируйте найденную внутри папку Eigen в ту же папку, что и исходный файл. Компилировать сg++ -I. -O3 -ffast-math -o ridge_professor ridge_professor.cc .

Бежать

вызовите ridge_profess.exe и предоставьте аргумент по мере необходимости.

Вопрос

Поскольку я пока нигде не могу комментировать, я спрошу здесь: не делает ли ограничение размера аргумента в окнах невозможным вызов конечных двоичных файлов со всей историей за несколько сотен оборотов? Я думал, что в аргументе не может быть больше ~ 9000 символов ...

dgel
источник
Спасибо, что привлекли мое внимание к этому . Я придумаю способ заставить его работать, если он уже не работает в Java. Если Java не может этого сделать, исследования говорят мне, что C ++ может, и я воспользуюсь возможностью переучить C ++. Я скоро вернусь с результатами испытаний.
Рейнболт
Как оказалось, Java не подпадает под ограничения командной строки. Похоже, что только команды больше 32k вызывают проблемы. Вот мое доказательство (я написал это сам): docs.google.com/document/d/… . Опять же, я очень ценю, что вы подняли этот вопрос до того, как завтра начнутся испытания
Рейнболт
@Rusher Уже есть 57 ботов, и вы планируете, чтобы каждый забег состоял из 1000 раундов. Это сделало бы вашу строку 57k символов (следовательно> 32k), не так ли?
plannapus
1
@Rusher Я думаю, что может быть лучше продлить график еще на одну неделю и попросить участников изменить свои программы на чтение стандартного ввода вместо использования строки аргумента. Было бы тривиально изменить большинство программ
dgel
@dgel Временные рамки для испытания бесконечно велики, но я не хочу менять правила так, чтобы каждый мог переписать свой ответ. Я почти уверен, что правило, которое я добавил прошлой ночью, повлияет только на одно представление, и я планирую помочь этому человеку, если он когда-нибудь доведет свою программу до точки, где она будет компилироваться.
Рейнболт
6

Crowley

Потому что винчестеры гораздо менее интересны без этого парня. Он явно встает на сторону зла ... если только ему не нужно заботиться о большем зле.

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

Я смотрю на последние два хода (0 запятых и 1 запятая), и если оба позволят злу победить, я проголосую за добро. В противном случае я голосую за зло.

Кэйн
источник
Я правильно понял? Вы смотрите на последний поворот, и если менее 50% являются «хорошими» голосами, вы на стороне «хороших», а со злом? (Из любопытства: вы предпочитаете загадочные имена переменных или это случайность?)
Анджело Фукс
1
@AngeloNeuschitzer Я смотрю последние два хода (пока 0 запятых и 1 запятую), и если они оба позволяют злу побеждать, я голосую за добро. В противном случае я голосую за зло. Я предпочитаю имена переменных, которые являются короткими для ввода, если код достаточно короткий, цель кода не будет запутана. Я не профессиональный программист, и это был первый раз, когда я программировал на Java или что-то еще, кто-то видел код за 6,5 лет. Я написал это, чтобы освежить мою память. (TLDR для меня не загадочны, и я единственный, для кого я обычно
пишу
Для ясности ... Кроули начинал как человек, поэтому он намеренно начал хорошо ... Не ожидал, что он останется хорошим во всех раундах, хотя ... черт
Кейн