
function kola() {
  this.alphabet= new Array();
  this.rang= new Array();
  this.f=new Array();
  this.prefix;
  this.prem; 
  this.mot;
  this.seq=new Array();
  this.alphadiff=new Array();
  this.diff=new Array();
  this.stat=new Array();
  this.nseq;
  this.c = new Array();
  
  
  function init() {
    var t="", r="";
    var i;
    var s=document.frm.alpha.value;
    this.alphabet = s.split(/\s+/);
    for(i=0;i<this.alphabet.length;i++) {
      this.rang[this.alphabet[i]]=i;
    }
    s = document.frm.im.value;
    var u = new Array();
    u = s.split(/\s+/);
    for(i=0;i<u.length;i++) {
      this.f[this.alphabet[i]] = parseInt(u[i]);
    }
    for(i = u.length; i < this.alphabet.length; i++) {
      this.f[this.alphabet[i]] = 1;
    }
    for(i=0;i<this.alphabet.length;i++) {
      r +=this.f[this.alphabet[i]];
    }
    for(i=0;i<this.alphabet.length;i++) {
      this.stat[i]=0;
    }
    s = document.frm.mot.value;
    s = s.replace(/^\s+/,"");
    s = s.replace(/\s+$/,"");
    s = s.replace(/\s+/g,"");
    this.prefix=s;
    this.prem = s.charAt(this.prefix.length-1);
    this.mot =this.prefix;
    this.c[0]=this.prefix.length;
    
    for(i=0;i<this.alphabet.length;i++) {
        this.seq[i] = new Array();
        this.seq[i][0] = 0;
	this.seq[i][1] = 0;
	this.alphadiff[i]=new Array();
    }
    for(i=0;i<this.prefix.length;i++) { 
      var j=this.rang[this.prefix.charAt(i)];
      this.seq[j][0] +=1; // rempli pour i=0
      this.seq[j][1] +=1; // on recopie en i=1
    }
      this.nseq = 1;
    for(var i=0;i<3;i++) this.diff[i]=new Array();
  }
  this.init=init;
  
  
/*
  construction de la suite de kolakoski
  12112122122112112212112122112112122122112122121121122122
  on obtient successivement les bouts
  1, 12, 1211, 121121, 121121221,
  
                         1                  0   1    1    0
  1 -> un 2         on a 12                 1   2    1    1
  12 -> deux 1           1211               2   4    3    1
  121 -> un 2            12112            
  1211 -> un 1           121121             3   6    4    2
  12112 -> deux 2        12112122
  121121 -> un 1         121121221          4   9    5    4
  1211212                12112122122
  12112122               1211212212211
  121121221              12112122122112     5   14   7    7
  etc.

  au début la suite est "1" à la position 0
  le curseur 'pos' se place sur les éléments successifs de la suite
  en partant de 0
  pendant ce même temps 'cur=cur2=1' part de 1 et 
  cur2 croît du nbre d'éléments nouveaux ajoutés à la suite
  lorsque pos est égal à cur on affiche et on fait le saut cur=cur2
  
*/
  function calc() {
    
    var s, nm = document.frm.lg.value;

    var a,b,k, l, i,j, c=this.prefix.length-1, s, r=this.rang[this.mot.charAt(pos)];
    var t, pos = this.prefix.length-1, cur=pos+1, cur2=pos+1;
    for(l=1; l < nm; l += k) {
      a = this.mot.charAt(pos);
      k = this.f[a];
//      k = this.f[this.alphabet[(this.rang[a]+1)%this.alphabet.length]];
      cur2 += k;
      r = (r+1)%this.alphabet.length;
      b = this.alphabet[r]; // on a changé de lettre
      this.stat[r] += k;  // nb d'occurrences de la lettre de rang r (sur le tout)
      this.seq[r][this.nseq] += k;  // nb d'occurrences de la lettre de rang r 
                                    // dans la sous-suite de rang 'this.nseq'
// r = (r+1)%this.alphabet.length;
      s="";
      for(j=0;j<k /* && l+j<nm */;j++) {
        s += b;
      }
      this.mot += s;
      pos++;
      if(pos == cur) {
        this.c[this.nseq]=cur2;  // longueur de la sous-suite de rang 'this.nseq'
        cur = cur2;
	for(i=0; i<this.alphabet.length; i++) {
	  this.seq[i][this.nseq+1] = this.seq[i][this.nseq]
	}
	this.nseq += 1;
      }
//      pos++;
    }
/**/
    for(var i=0;i<this.nseq;i++) 
      this.diff[0][i]=this.c[i];
    
    for(var j=1;j<3;j++) 
      for(var i=0;i<this.nseq-j;i++) 
        this.diff[j][i]=this.diff[j-1][i+1]-this.diff[j-1][i];
  
    for(var i=0;i<this.alphabet.length;i++)
      for(var j =0; j<this.nseq-1;j++) 
        this.alphadiff[i][j]=this.seq[i][j+1]-this.seq[i][j];
/**/        
//    alert(this.nseq);
  }
  this.calc=calc;
  
  function affiche() {
    var s0="",s2="\nSomme A = ", s3= "Diffs D  = ",s4= "Diffs D2 = ",s1="Stats = ", s = "",sl="";
    for(var i=0;i<this.alphabet.length;i++) {
      s0 += "A("+this.alphabet[i]+") : ";
      for(var j =0; j<this.nseq;j++) {
        s0 +=this.seq[i][j]+" ";
      }
      s0 += "...\n"
    }
    for(var i=0;i<this.alphabet.length;i++) {
      s0 += "Diffs d("+this.alphabet[i]+") : ";
      for(var j =1; j<this.nseq;j++) {
        s0 +=this.seq[i][j]-this.seq[i][j-1]+" ";
      }
      s0 += "...\n"
    }
    for(var i=0;i<this.nseq;i++) {
      s2 += this.c[i]+" ";
      sl += this.c[i];
      if(i<this.nseq-1) sl += ", ";
    }
    document.frm2.sequence.value=sl;
    s2 += "\n";
    for(var i=1;i<this.nseq;i++) {
      s3 += this.c[i]-this.c[i-1]+" ";
    }
    s3 += "\n";
    for(var i=2;i<this.nseq;i++) {
      s4 += this.c[i]-2*this.c[i-1]+this.c[i-2]+" ";
    }
    s4 += "\n";
    for(var i=0;i<this.alphabet.length;i++) {
      s1 += this.stat[i]+" "
    }
    s4 += "\n";
    for(var k=0; k<this.mot.length; k+=60) {
      s = s+this.mot.substr(k,60)+"\n";
    }
    document.frm.area.value=s0+s2+s3+s4+s1+s;
//    document.frm.area.value=s1+s;
    
  }
  this.affiche=affiche;

  function diff() {
    var s;
    s=this.prefix+"\n";
    for(var i=0;i<this.nseq-1;i++) {
      s += this.mot.substr(this.c[i],this.c[i+1]-this.c[i])+"\n"
    }
    document.frm.area.value = s
  }
  this.diff = diff;

  function sousChaines() {
    var m, motif=document.frm.model.value;
    document.frm.nbocc.value="";
    do {
      m = motif;
      motif=m.replace(/\s/g,"")
    } while (m!=motif);
    var model = new RegExp(motif,"g");
    var a = this.mot.match(model);
    document.frm.nbocc.value = a.length;
  }
  this.sousChaines=sousChaines;
}

var Ko;
function effectue() {
  Ko = new kola();
  Ko.init();
  Ko.calc();
  Ko.affiche();
}

function afficheko() {
  Ko.affiche();
}
function diffko() {
  Ko.diff();
}
function polyko() {
  Ko.poly();
}
function effect() {
  Ko.sousChaines();
}


var exo = new Array( "a b c", "1 2 3", "a", "20000", "a", //0
"1 2", "1 2","1", "20000", "1",
"1 2", "1 2","22", "20000", "1",
"1 3", "1 3","1", "20000", "1",
"1 2 3", "1 2 3", "1", "50000", "1",
"1 2 3 4", "1 2 3 4", "1", "50000", "1", 
"a b c d e", "1 2 3 5 7 11", "1", "100000", "1",
"a b", "1 4", "a", "100000", "a",
"a b", "1 6", "a", "100000", "a",
"a b", "1 8", "a", "100000", "a",
"a b", "1 10", "a", "100000", "a", //10
"a b", "1 3", "a", "100000", "a",
"a b", "1 5", "a", "100000", "a",
"a b", "1 7", "a", "100000", "a",
"a b", "1 9", "a", "100000", "a",
"a b", "3 1", "a", "100000", "a",
"a b", "3 5", "a", "100000", "a",
"a b", "3 7", "a", "100000", "a",
"a b", "3 9", "a", "100000", "a",
"a b", "2 11", "a", "100000", "a",
"a b", "4 11", "a", "100000", "a", //20
"a b", "6 11", "a", "100000", "a",
"a b", "8 11", "a", "100000", "a",
"0 1 2 3 4 5","1 2 1 1 2 1", "0", "1500", "0"
);


function exemple(n) {
  document.frm.alpha.value = exo[5*n];
  document.frm.im.value = exo[5*n+ 1];
  document.frm.mot.value = exo[5*n+ 2];
  document.frm.lg.value = exo[5*n+ 3];
  document.frm.model.value = exo[5*n+ 4];
  effectue();
  afficheko();
  effect();
}

