Skip to main content
6 of 11
corrected minor mistake due to change in code
tomsmeding
  • 2.1k
  • 16
  • 20

##C++, The Scientist

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

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

#include <iostream>
#include <utility>
#include <cstdlib>
#include <cstring>

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;
    }
    int nump,numr;
    nump=strchr(argv[1],',')-argv[1];
    numr=(strlen(argv[1])+1)/(nump+1);
    int period,r;
    int *wave=new int[numr];
    bool allequal=true;
    cerr<<"wave: ";
    for(r=0;r<numr;r++){
        wave[r]=majority(argv[1]+r*(nump+1));
        if(wave[r]!=wave[0])allequal=false;
        cerr<<wave[r]<<" ";
    }
    cerr<<endl;
    if(allequal){
        cerr<<"All equal!"<<endl;
        if(numr>=50){ //if it's stable, minority
            if(wave[0]==1)cout<<"evil"<<endl;
            else cout<<"good"<<endl;
        } else { //else, majority for safety
            if(wave[0]==1)cout<<"good"<<endl;
            else cout<<"evil"<<endl;
        }
        return 0;
    }
    int score,*scores=new int[numr];
    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
    cerr<<"scores: ";
    for(period=1;period<=numr;period++){
        scores[period-1]=0;
        phasemax=-1;
        for(phase=0;phase<2*period;phase++){
            score=0;
            for(r=0;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;
        }
        cerr<<scores[period-1]<<" ";
    }
    cerr<<"(max="<<max<<" at {"<<maxat.first<<","<<maxat.second<<"})"<<endl;
    cerr<<" max: ("<<numr<<"+"<<maxat.second<<")%(2*"<<maxat.first<<")/"<<maxat.first<<"=="<<((numr+maxat.second)%(2*maxat.first)/maxat.first)<<endl;
    if((numr+maxat.second)%(2*maxat.first)/maxat.first==0)cout<<"good"<<endl;
    else cout<<"evil"<<endl;
    delete[] wave;
    delete[] scores;
    return 0;
}

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

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

tomsmeding
  • 2.1k
  • 16
  • 20