// Construction d'une table de nombres premiers

// table de nombres premiers premier[0]=2, premier[1]=3, premier[2]=5 ...

var Factorielle = new Array();

function fact(n) {
  if(Factorielle[n]!=null) return Factorielle[n];
  else return null;
}

var premier=new Array(2,3,5)
var MAX_N=5;

function initiePrem(n) {
// Construction de la table de nombres premiers en prolongeant
// la table existante suffisamment loin
//  if(n>MAX_MAX_N) n= MAX_MAX_N;

  var NOUV_N= (n%2==0)?n+1 : n;
  if(NOUV_N<=MAX_N) return;
  for(var i=MAX_N+2;i<=NOUV_N;i +=2) {
    var test=true;
    for(j=0;test && premier[j]*premier[j]<=i;j++) {
      if(i%premier[j]==0) test=false
    }
    if(test) premier[premier.length]=i;
  }
  MAX_N= NOUV_N
}

initiePrem(200);

function decompose(tab, n, k) {
     var x=n;
     for(var i=0; premier[i]<=x; i++) {
        var p=premier[i];
        while(x%p==0) {
          if(tab[i]==null) tab[i]=0
          tab[i] += k;
          x /=p;
        }
     }
     return tab;
}

// chaîne des nb de chiffres 0 1 2 3 4 5 6 7 8 9
//     s = "5 4 8 2 0 1 4 2 1 4"
// est un nb de 31 chiffres
var multi0 = function(tb, s0) {
	var s = s0+""
	var str=""
	s = s.replace(/^\s+/,"")
	s = s.replace(/\s+$/,"")
	s = s.replace(/\s+/g," ")
	var args = s.split(/\s+/g)
	//alert(args)
	var lg = args.length
	for(var i=lg; i<10; i++) {
		args[i]=0
	}
	var n=0;
	for(var i=0; i<lg; i++) {
		n += parseInt(args[i]);
	}
	if(n==0) return
	str += "Ces nombres entiers ont tous "+n+" chiffres.<br />\n" +
	"Les effectifs des chiffres de 0 à 9 sont les mêmes pour ces nombres, ce sont : "
	for(i=0; i<=9; i++) {
		str += args[i]+", "
	}
	str += "<br /><br />\n";
	initiePrem(n)
	//var tb = []
	if(tb == null)
		tb=""
	for(var i=2; i<=n-1;i++) {         // (n-1) !
		decompose(tb, i, 1)
	}
	//alert("1\n"+tb)
	tb = decompose(tb, n-parseInt(args[0]), 1)	// (n-n0)
	for(var i=0; i<lg; i++) { 	// nb chiffres   n_i = args[i]
		for(var j=2; j<=parseInt(args[i]); j++) {//    1/ (n_i)!
			decompose(tb, j, -1)
		}
	}
	return str
}

	var binomial = function(tb, n, p) {
		var q = (p>n-p) ? n-p : p
		for(var i=0; i<q; i++) {
			decompose(tb, n-i, 1)
		}
		for(var i=2; i<=q; i++) {
			decompose(tb, i, -1)
		}
        }

        // binomial(n+9, 9) - 1

        // binomial(n+10,10)-n-1.

var binom9 = function(n) {
	var tb=[]
	binomial(tb, n+9, 9)
        var gi = new gint(), gj= new gint()
        gi.fromEP(tb);
	gj.fromN(1)
	gi.sub(gj)
        var s = gi.toString();
        delete(gi)
	delete(gj)
        return s
}

var binom10 = function(n) {
        var tb=[]
        binomial(tb, n+10, 10)
        var gi = new gint(), gj= new gint()
        gi.fromEP(tb);
	gj.fromN(n+1)
        gi.sub(gj)
        var s = gi.toString();
        delete(gi)
	delete(gj)
        return s
}


var ecrPrimaire = function(tb) {
	var s=""
	for(var x in tb) {
		if(tb[x]==0) 
			continue;
		var np = premier[x]
		var p = tb[x]
			
		if(s != "") {
			s += " &times;"
		}
		s += np
		if(p>1) {
			s += "<sup>"+p+"</sup>"
		}
	}
	if(s=="")
		s="1"
	return s
}
   

var ecrDecimale  = function(tb) {
	var gi = new gint();
	gi.fromEP(tb);
	var s = gi.toString();
	delete gi
	return s
}



var latex=false

var gint = function(){
	this.limit=1E5;
	this.n=0;
	this.blocs=new Array();
	this.str="";

  // à partir de l'écriture primaire d'un entier
 	this.fromEP = function(tab) {
		if(tab==null) {
			return;
		}
   		var p;
   		this.blocs[0] = 1;
   		for(var i=0; i<tab.length; i++) {
      			if(tab[i]!=0) {
        			p = premier[i];
        			for(var j=0;j<tab[i]; j++) {
          				this.kmult(p);
        			}
      			}
   		}
  	}
	this.fromN = function(n) {
		this.blocs[0] = 1;
		this.kmult(n);
	}

  	// multiplication par k petit entier (k< 10^6 par exemple)
	this.kmult = function(k) {
		var r=0;
		for(var i=0; i<this.blocs.length; i++) {
			this.blocs[i] = k*this.blocs[i]+r;
			r=0;
			if(this.blocs[i]>=this.limit) {
         var u=this.blocs[i];
         this.blocs[i] %= this.limit;
         r = (u - this.blocs[i])/this.limit;
       }
    }
    if(r>0) {
      this.blocs[this.blocs.length]=r;
    }
  }
 

  // ajout d'un autre grand entier
	this.add = function(g) {
     //alert(this+"\n"+g);
     var r=0, u, v;
     for(var i=0; i<this.blocs.length || i< g.blocs.length || r>0; i++) {
        u = (this.blocs[i]==null)? 0 : this.blocs[i];
        v = (g.blocs[i]==null)? 0 : g.blocs[i];
        this.blocs[i] = u+v+r;  // < 2 * this.limit
        if(this.blocs[i]>= this.limit) {
          this.blocs[i] -= this.limit;
          r=1;  // car 1*limit <= somme < 2 * limit
        }
      }
  }
  
  // on suppose g < this et un rï¿½sultat positif
  this.sub = function(g) {
     var r=0, u, v;
     for(var i=0; i<this.blocs.length || i< g.blocs.length || r>0; i++) {
        u = (this.blocs[i]==null)? 0 : this.blocs[i];
        v = (g.blocs[i]==null)? 0 : g.blocs[i];
        w = u-v-r;
        if(w<0) {
          w += this.limit;
          r = 1;
        }
        this.blocs[i] = w;
      }
  }
  
  this.toString = function() {
    var last, s="";
    for(last = this.blocs.length-1; this.blocs[last]==0;last--);
    //if(last==0) return this.blocs[0]+"";
    for(var i=last; i>=0; i--) {
      var s1=this.blocs[i]+"";
      if(i<last) {
        while(s1.length<5) s1 = "0"+s1;
      }
      s += s1;
    }
    var s2="";
    var lig;
    if(latex) lig=110
    else lig = 70;
    for(var i=0; i < s.length; i+=lig) {
      if(latex) {
      s2 += "$"+s.substr(i,lig)+"$"
      } else {
        s2 += s.substr(i,lig)
      }
      if(i+lig<s.length)
      if(latex) {
        s2 = s2+"\\\\\n";
      } else {
        s2 +="\n   ";
      }
    }
    this.str = s2;
    return this.str;
  }

}
/*
var t=[]
for(var i = 2; i<=100; i++) {
decompose(t, i, 1)
}
alert(t)

var t=[]
multi0(t, "2 3 1 4 2 5 2 4 1 2")
alert(t)
*/
function nbnaturels(){
	var s0 = document.fmulti.nchiffres.value

	s0 = s0.replace(/^\s+/,"")
	s0 = s0.replace(/\s+$ /,"")
	document.fmulti.nchiffres.value = s0
	var s = s0;
	var g = s0.split(/\s/g);
	if(g.length==1) {
		var t1 = [];
		for(var i=0;i<10; i++) {
			t1[i]=0
		}
		for(var i=0;i<s.length; i++) {
			u=parseInt(s.charAt(i))
			t1[u]++
		}
		s = ""
		for(var i=0;i<10; i++) {
                        s += ((i!=0)? " ":"") + t1[i]
                }
	}		
	var t = []
	var sa = multi0(t, s)
	var ep = ecrPrimaire(t)
	var ed = ecrDecimale(t)
	var r = ed.length
	sa += "Le nombre de naturels différents écrits avec ces quantités de chiffres est <br />\n"+
		"Écriture primaire : <br />"+ep+"<br />Écriture décimale : <br />"+ed+" (qui a "+ r +" chiffre"+((r>1)?"s":"")+")"
	document.getElementById("IDnat").innerHTML=sa
}

function chifHasard() {
	var s = ""
	for(var i=0; i<10; i++) {
		s += Math.floor(10*Math.random())+" ";
	}
	document.fmulti.nchiffres.value = s
	nbnaturels()
}
function chifNbHasard() {
        var s = ""
	var l =2+Math.floor(65*Math.random())
	s += (1+Math.floor(9*Math.random()))
	for(var i=1; i<l; i++) {
		s += ""+Math.floor(10*Math.random())
	}
	document.fmulti.nchiffres.value = s
        nbnaturels()
}


function chifEfface() {
	document.getElementById("IDnat").innerHTML=""
	document.fmulti.nchiffres.value = ""
}

function nbdiff(s) {
	document.fmulti.nchiffres.value = s
        nbnaturels()
}



function nonordnaturels() {
	var n = parseInt(document.fnonord.nchiffres.value)
	//alert(n)

	// binomial(n+9, 9)
	var s1 = binom9(n)
	// binomial(n+10,10)-n.
	var s2 = binom10(n)
	var s = "Le nombre d'entiers naturels non nuls ayant "+n+" chiffres<br />" +	
		"1) exactement est : "+s1+"<br />" +
		"2) au plus est&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : "+s2+"<br />"
	document.getElementById("IDnonord").innerHTML=s

}

function nonordHasard() {
	var n = 1+Math.floor(1000*Math.random())
	document.fnonord.nchiffres.value = n
	nonordnaturels()
}

function nonordEfface() {
	document.getElementById("IDnonord").innerHTML=""
        document.fnonord.nchiffres.value = ""

}

//0, 9, 54, 219, 714, 2001, 5004, 11439, 24309, 48619,
/*
var ta=[]
binomial(ta, 13, 4)
var gb=new gint()
gb.fromEP(ta)

alert(gb.toString())
*/

