//CHECKJS  C:\temp\sudoku\utility.js 11/6/2005 12:30:13 PM
//utility.js hansonr@stolaf.edu 7:00 AM 10/28/2005
// generally useful functions
Pwr2=[];for(var _i=0;_i<28;_i++)Pwr2[_i]=Math.pow(2,_i)
XCache={}

function Aa3Sort(a,b){
	var A=a[3].toUpperCase()
	var B=b[3].toUpperCase()
	if(A!=B)return(A>B?1:-1)
	return(a[3]>b[3]?-1:a[3]<b[3]?1:a[1]>b[1]?-1:a[1]<b[1]?1:0)
}

function aList(List){
	var s=""
	for(var i=0;i<List.length;i++)if(List[i])s+=","+List[i]
	return s.substring(1,s.length)
}

function arrayAdd(A,n){
	if(!A)return ""
	var B=[]
	for(var i=0;i<A.length;i++)B[i]=A[i]+n
	return B
}

function coinflip(){
	return Math.floor(Math.random()*2)
}

function coordOf(C,k){
	return C.showinfo+"#"+(k+1)
}

function docWrite(s,opt){
	if(!opt)opt="menubar,scrollbars,width=800,height=600,left=100,top=30"
	var sm=""+Math.random()
	sm=sm.substring(3,10)
	var w=open("","DT_"+sm,opt)
	w.document.open()
	w.document.write(s)
	w.document.close()
}

function docOpen(s,opt){
	if(!opt)opt="menubar,scrollbars,width=600,height=600,left=100,top=30"
	var sm=""+Math.random()
	sm=sm.substring(3,10)
	var w=open(s,"DT_"+sm,opt)
}

var nPos = 0
var nImpos=0

function isPossible(D, k) {
	return(D.Impossible[k] ? 0 : 1)
}

function eliminateK(D,k,s){
	if (!isPossible(D,k)){
		nImpos++;
		return 0
	}
	nPos++
	lastmsg=s=D.showinfo+" ISN'T "+(k+1)+": "+s
	D.Eliminated[k]=k+1
	if(idonotstop){
		//from [All] via doAll()
		if(eliminationmsg.indexOf(s)>=0){
			return 0
		}
		eliminationmsg+=s+"\n"
	}else{
		D.Impossible[k]=k+1
		D["impossibleType"+k]=s
		iseliminated=1
	}
	redlist+=D.showinfo
	redlistk+=coordOf(D,k)
	if(s.indexOf("[")>=0)s=s.replace(/\[/,"<font color=blue>").replace(/\[/,"<font color=teal>").replace(/\]/g,"</font>")
	logAddMessage(s)
	return idonotstop ? 0 : 1
}

function initXArray(A){
	A.N=[]
	A.XRow=[]
	A.XCol=[]
	A.XCell=[]
	A.XBlock=[]
	A.XBlockCell=[]
	A.XBlockRow=[]
	A.XBlockCol=[]
	A.XRowSubset=[]
	A.XColSubset=[]
	A.XBlockK=[0,0,0,0,0,0,0,0,0]
	for(var i=0;i<9;i++){
		A.N[i]=0
		A.XRow[i]=[0,0,0,0,0,0,0,0,0]
		A.XCol[i]=[0,0,0,0,0,0,0,0,0]
		A.XCell[i]=[0,0,0,0,0,0,0,0,0]
		A.XBlock[i]=[0,0,0,0,0,0,0,0,0]
		A.XBlockCell[i]=[0,0,0,0,0,0,0,0,0]
		A.XBlockRow[i]=[0,0,0,0,0,0,0,0,0]
		A.XBlockCol[i]=[0,0,0,0,0,0,0,0,0]
		A.XRowSubset[i]=[0,0,0,0,0,0,0,0,0]
		A.XColSubset[i]=[0,0,0,0,0,0,0,0,0]
	}
}

function rightJust(s,n){
	s="          "+s
	return s.substring(s.length-n,s.length)
}

function xList(xlist){
	if(xlist==0)return []
	var sx="l"+xlist;if(XCache[sx])return XCache[sx]
	var A=[]
	for(var i=0;i<9;i++)if(xlist & Pwr2[i])A.push(i)
	return XCache[sx]=A
}

function xFirst(xlist){
	for(var i=0;i<9;i++)if(xlist & Pwr2[i])return i
	return -1
}

function xNum(xlist){
	if(xlist==0)return 0
	var sx="n"+xlist;if(XCache[sx])return XCache[sx]
	var n=0
	for(var i=0;i<9;i++)if(xlist & Pwr2[i])n++
	return XCache[sx]=n
}

function xNumP(xlist){
	var n=0
	for(var i=0;i<9;i++)if(xlist & Pwr2[i])n++
	return (n==0||n==1?"<font color=red>1</font>":n)
}

function xSet(List){
	var x=0
	for(var i=0;i<List.length;i++)if(List[i])x|=Pwr2[i]
	return x
}

function xSetArray(A,C,k){
	var i=C.row
	var j=C.col
	A.N[k]++
	A.XBlock[C.block][k]|=Pwr2[C.bptr]
	A.XRow[i][k]|=Pwr2[j] //(row vector)
	A.XCol[j][k]|=Pwr2[i] //(column vector)
	A.XCell[i][j]|=Pwr2[k]//allowed associated with this cell
	A.XBlockCell[C.block][C.bptr]|=Pwr2[k]
	A.XRowSubset[i][k]|=Pwr2[j-(j%3)] //in row i, k appears in subsets 0, 3, or 6
	A.XColSubset[j][k]|=Pwr2[i-(i%3)] //in col j, k appears in subsets 0, 3, or 6
	A.XBlockRow[C.block][k]|=Pwr2[i] //in block p, k appears in rows x,y,z
	A.XBlockCol[C.block][k]|=Pwr2[j] //in block p, k appears in cols x,y,z

//if(A==Logic.True||A==Logic.False)addLogic(0,0,0,0,"setting "+coordOf(C,k)+" in "+(A==Logic.False?"Logic.False":"Logic.True")+" "+xStr(A.XCell[C.row][C.col]))

}

function xStr(xlist){
	if(xlist==0)return ""
	var sx="s"+xlist;if(XCache[sx])return XCache[sx]
	var s=""
	if(s.length)return s
	for(var i=0;i<9;i++)if(xlist & Pwr2[i])s+=","+(i+1)
	return XCache[sx]=s.substring(1,s.length)
}

	

function xVal(x){
	if(x==0)return 0
	var sx="v"+x;if(XCache[sx])return XCache[sx]
	for(var i=0;i<9;i++)if(x==Pwr2[i])return XCache[sx]=i
	return XCache[sx]=0
}

function xNumArray(xA){
	// xA is a disjoint set of bitset values
	// used for counting cells
	var n = 0
	for (var i = 0; i < 9; i++)if (xA[i])n+=xNum(xA[i])
	return n
}

function xNumArray2(x1, x2){
	var n = 0
	var x
	// x=() is correct here -- assigning x
	for (var i = 0; i < 9; i++)if (x=(x1[i]|x2[i]))n+=xNum(x)
	return n
}

function cardinalityOf(A){
	var n = 0
	for (var i = 0; i < 9; i++)if (A[i])n++
	return n
}

function cardinalityOf2(A,B){
	var n = 0
	for (var i = 0; i < 9; i++)if (A[i]||B[i])n++
	return n
}



Glyphs = []

function resetGlyphs(asblank) {
	for (var k = 0; k < 9; k++) {
		Glyphs[k] = []
		for (var i = 0; i < 17; i++)
			Glyphs[k][i] = 0
		resetGlyph(k)
	}
}

function resetGlyph(k) {
	var g = Glyphs[k]
	var gr = 0
	var gc = 0
	for (var r = 0; r < 9; r++) {
		var x = Possible.XRow[r][k]
		if (x==0)continue
		var Cols = xList(x)
		var gr = r << 1
		var i0 = Cols[0] << 1
		var i1 = (Cols[Cols.length-1] << 1)+1
		for (var i = i0; i < i1; i++) {
			g[gr] |= Pwr2[i]
		}
	}
	for (var c = 0; c < 9; c++) {
		var x = Possible.XCol[c][k]
		if (x==0)continue
		var Rows = xList(x)
		var gc = c << 1
		var i0 = Rows[0] << 1
		var i1 = (Rows[Rows.length-1] << 1)+1
		for (var i = i0; i < i1; i++) {
			g[i] |= Pwr2[gc]
		}
	}
}
