// gloumouth1.free.fr

public class DivinationSequentielle implements Divination {
    private int longueurAnalyse;
    private boolean[] precedents;
    private int[] sequences;
    private boolean[] debut;
    private int nbJoues = 0;
    private int nbSucces = 0;

    public DivinationSequentielle(int longueurAnalyse) {
        this.longueurAnalyse = longueurAnalyse;
        precedents = new boolean[longueurAnalyse];
        for(int i = 0; i < longueurAnalyse; i++) precedents[i] = false;
        debut = new boolean[longueurAnalyse];
        for(int i = 0; i < longueurAnalyse; i++) debut[i] = Math.random() < 0.5;;
        int n = pow(2, longueurAnalyse);
        sequences = new int[n];
        for(int i = 0; i < n; i++) sequences[i] = 0;
    }

    public static int pow(int a, int b) {
        int retour = 1;
        for(int i = 1; i <= b; i++) retour *= a;
        return retour;
    }

    public void setNouveau(boolean nouveau) {
        if (getProchain() == nouveau) nbSucces++;
        boolean[] oldPrecedents = getPrecedents();
        int newLongueur = Math.min(longueurAnalyse, oldPrecedents.length + 1);
        for(int i = 1; i < newLongueur; i++) precedents[i] = oldPrecedents[i - 1];
        precedents[0] = nouveau;
        nbJoues++;
        sequences[getNumSequence(getPrecedents())]++;
    }

    public int getNumSequence(boolean[] tab) {
        int numSequence = 0;
        for(int i = 0; i < tab.length; i++)
            numSequence += toInt(tab[i]) * pow(2, i);
        return numSequence;
    }

    public static int toInt(boolean b) {
        return b ? 1 : 0;
    }


    public boolean[] getPrecedents() {
        int min = Math.min(nbJoues, longueurAnalyse);
        boolean[] retour = new boolean[min];
        for(int i = 0; i < min; i++) retour[i] = precedents[i];
        return retour;
    }

    public boolean getProchain() {
        if (getNbJoues() < longueurAnalyse) return debut[getNbJoues()];
        boolean[] sequenceFuture = new boolean[longueurAnalyse];
        for(int i = 1; i < longueurAnalyse; i++) sequenceFuture[i] = precedents[i - 1];
        sequenceFuture[0] = false;
        int futureFalse = sequences[getNumSequence(sequenceFuture)];
        sequenceFuture[0] = true;
        int futureTrue = sequences[getNumSequence(sequenceFuture)];
        return futureTrue > futureFalse;
    }

    public int getNbJoues() {
        return nbJoues;
    }

    public int getNbSucces() {
        return nbSucces;
    }
}
