function EV() {
this.__e = {};
}
EV.prototype.__e = {};
EV.prototype.emit = function(n) {
var that = this;
var args = [].slice.apply(arguments, [1]);
(this.__e[n] || []).map(function(lis) {
lis.map(function(fn) {
fn.apply(that, args)
})
})
return this;
}
EV.prototype.on = function(n) {
var args = [].slice.apply(arguments, [1]);
this.__e[n] = this.__e[n] || [];
this.__e[n].push(args);
return this;
}
function inherits(ctor, superCtor) {
var Obj = function() {};
Obj.prototype = superCtor.prototype;
ctor.prototype = new Obj
}
function permutates(xs) {
var ret = [];
for (var i = 0; i < xs.length; i = i + 1) {
var rest = permutates(xs.slice(0, i).concat(xs.slice(i + 1)));
if (!rest.length) {
ret.push([xs[i]])
} else {
for (var j = 0; j < rest.length; j = j + 1) {
ret.push([xs[i]].concat(rest[j]))
}
}
}
return ret;
}
function mo() {
this.variabler = {};
this.tabel = {};
this.tableHead = [];
this.tableName = "";
this.regler = [];
this._internal_step_counter = 0;
this.rmat = [];
this.funcs = {};
this.rulas = [];
}
inherits(mo, EV)
mo.prototype.addVariabelSet = function(navn, arr) {
this.variabler[navn] = arr;
return this;
}
mo.prototype.addVariableTable = function(navn, arr) {
this.tableHead = arr;
this.tableName = navn;
return this;
}
mo.prototype.addFunction = function(name, func) {
this.funcs[name] = func;
return this;
}
mo.prototype.addClause = function() {
var args = Array.prototype.slice.apply(arguments, []);
while (args.length) {
var arg = args.shift();
var props = Object.keys(arg);
var propid1, propid2;
if (this.variabler[props[0]]) {
propid1 = Object.keys(this.variabler).indexOf(props[0]);
}
if (this.variabler[props[1]]) {
propid2 = Object.keys(this.variabler).indexOf(props[1]);
} else {}
var arr = []
if (propid1 > -1 && propid2 > -1) {
val1 = this.variabler[props[0]].indexOf(arg[props[0]])
val2 = this.variabler[props[1]].indexOf(arg[props[1]])
arr = ["check", propid1, propid2, val1, val2, [props[0], arg[props[0]], props[1], arg[props[1]]].join(" ")];
} else {
var lookfor = props[props.length - 1];
if (this.funcs[lookfor]) {
arr = this.funcs[lookfor].apply(this, [arg])
}
}
}
this.rulas.push(arr);
return this;
}
mo.prototype.build = function(tabl) {
var r = [];
var arr = [];
var pertable = []
for (var navn in this.variabler) {
pertable.push(permutates((this.variabler[navn]).map(function(a, i) {
return i
})));
}
return pertable;
}
mo.prototype.checkn = function(prop1, prop2, val1, val2) {
return this.current[this.sos[prop1]][val1] == val2
}
mo.prototype.check = function(prop1, prop2, val1, val2) {
var i;
// console.log(prop1,this.sos[prop1], prop2, this.current[this.sos[prop1]],this.current[this.sos[prop2]],val1,val2)
for (i = 0; i < 5; i++) {
if (this.current[this.sos[prop1]][i] == val1) {
// console.log("II,",i,this.current[this.sos[prop1]][i],"=",val1,"&", this.current[this.sos[prop2]][i],"=",val2 );
var p;
p = (this.current[this.sos[prop2]][i] == val2)
return p;
}
}
return false;
}
mo.prototype.checkLeft = function(prop1, prop2, val1, val2) {
var i;
for (i = 0; i < 4; i++) {
if (this.current[this.sos[prop1]][i] == val1) {
var p;
p = (this.current[this.sos[prop2]][i + 1] == val2)
return p;
}
}
return false;
}
mo.prototype.checkRight = function(prop1, prop2, val1, val2) {
var i;
for (i = 1; i < 5; i++) {
if (this.current[this.sos[prop1]][i] == val1) {
var p;
p = (this.current[this.sos[prop2]][i - 1] == val2)
return p;
}
}
return false;
}
mo.prototype.checkBoth = function(prop1, prop2, val1, val2) {
return this.checkLeft(prop1, prop2, val1, val2) || this.checkRight(prop1, prop2, val1, val2)
}
function intersection() {
var result = [];
var lists;
if (arguments.length === 1) {
lists = arguments[0];
} else {
lists = arguments;
}
for (var i = 0; i < lists.length; i++) {
var currentList = lists[i];
for (var y = 0; y < currentList.length; y++) {
var currentValue = currentList[y];
if (result.indexOf(currentValue) === -1) {
var existsInAll = true;
for (var x = 0; x < lists.length; x++) {
if (lists[x].indexOf(currentValue) === -1) {
existsInAll = false;
break;
}
}
if (existsInAll) {
result.push(currentValue);
}
}
}
}
return result;
}
mo.prototype.solve = function() {
var self = this;
self.current = this.build("House").shift();
var sa = Object.keys(this.variabler);
self.sos = sa.map(function(a) {
return 0; //self.current.length - 1; //Math.floor(Math.random()*self.current.length-1);
})
self.subspace = self.current.length;
self.varspace = sa.length;
self.space = Math.pow(self.subspace, self.varspace - 1);
var iteration = 0;
var maxi = 0;
var ioa = -1;
var soso = [];
var sat = false;
self.rulas = self.rulas; //slice(0, 9);
/* self.rulas.sort(function(a, b) {
return a[1] > b[1] ? -1 : a[1] < b[1] ? 1 : a[2] > b[2] ? 1 : a[2] < b[2] ? -1 : 0
})
*/
// console.log(self.rulas);
// return false;
// først find variabler som bruges i samme opslag.
var tas = {}
var firsta = [];
self.rulas.map(function(ru) {
console.log(ru);
if (ru[1] == ru[2]) {
firsta.push(ru);
}
})
self.sos = self.sos.map(function(a) {
return 0
})
var osa = -1
console.log(firsta);
var cands = [];
for (var x = 0; x < firsta.length; x++) {
self.sos = self.sos.map(function(a) {
return 0
})
var t = firsta[x];
var ca = [];
for (var i = 0; i < self.subspace; i++) {
var ff = false;
self.sos[t[1]] = i
console.log(self.sos);
ff = self[t.slice(0, 1)[0]].apply(self, t.slice(1))
if (ff) {
ca.push(i);
}
}
cands.push([t[1], ca]);
}
console.log(cands);
// var inta=intersection.apply(this,cands.map(function(a){ return a[1]}));
self.sos = self.sos.map(function(a) {
return 0
})
var cc = cands.length;
var ticks = [0, 0, 0, 0, 0];
var ic = 0;
var iomax = self.rulas.length;
var ioa = 0;
for (var i0 = 0; i0 < cands[0][1].length; i0++) {
if (cands[1]) {
for (var i1 = 0; i1 < cands[1][1].length; i1++) {
if (cands[2]) {
for (var i2 = 0; i2 < cands[2][1].length; i2++) {
if (cands[3]) {
} else {
var st = [0, 1, 2, 3, 4]
self.sos[cands[0][0]] = cands[0][1][i0]
self.sos[cands[1][0]] = cands[1][1][i1]
self.sos[cands[2][0]] = cands[2][1][i2]
st.splice(st.indexOf(cands[0][0]), 1);
st.splice(st.indexOf(cands[1][0]), 1);
st.splice(st.indexOf(cands[2][0]), 1);
for (var i3 = 0; i3 < 120; i3++) {
for (var i4 = 0; i4 < 120; i4++) {
ic++
self.sos[st[0]] = i3
self.sos[st[1]] = i4
var io = 0;
var ff = true;
while (io < iomax && ff) {
ff = false;
var t = self.rulas[io];
ff = self[t.slice(0, 1)[0]].apply(self, t.slice(1))
if (ff) {
io++;
}
}
if (io > ioa) {
// soso.push([].concat(self.sos));
ioa = io;
var tt = self.rulas.map(function(t) {
return [self[t.slice(0, 1)[0]].apply(self, t.slice(1))].concat(t);
})
console.log(ic, io, ioa, iomax, self.sos.join(" "), tt.map(function(a) {
return a.join(" ")
}));
}
if(ioa >= iomax){
return self.sos;
}
if(ic % 1000000 === 0){
console.log("X", ic, io,ioa,iomax, self.sos[cands[0][0]], self.sos[cands[1][0]], self.sos[cands[2][0]], i3, i4);
}
}
}
}
}
} else {
console.log(cands[0][1][i1], cands[1][1][i2])
}
}
}
}
return false;
// console.log("II",inta);
/* for (var i = 0; i < self.subspace; i++) {
self.sos[0] = i;
var mio = 0;
var ff = true;
var iomax = 1; // firsta.length;
while (mio < iomax && ff) {
var t = firsta[mio];
ff = self[t.slice(0, 1)[0]].apply(self, t.slice(1))
if (ff) {
mio++;
}
}
if (mio > 0) {
cands.push(i);
} else {}
}
self.sos[0] = 0;
*/
//cands = [105,81]
var iomax = self.rulas.length;
while (!sat && cands.length > 0) {
var cand1 = cands.shift();
self.sos[0] = cand1;
iteration = 0;
while (!sat && iteration < self.space) {
var io = 0;
var ff = true;
while (io < iomax && ff) {
var t = self.rulas[io];
ff = self[t.slice(0, 1)[0]].apply(self, t.slice(1))
if (ff) {
io++;
}
}
if (io > ioa) {
soso.push([].concat(self.sos));
ioa = io;
var tt = self.rulas.map(function(t) {
return [self[t.slice(0, 1)[0]].apply(self, t.slice(1))].concat(t);
})
console.log(iteration, io, ioa, iomax, self.sos.join(" "), tt.map(function(a) {
return a.join(" ")
}));
}
if (io >= iomax) {
sat = true;
// console.log((iteration).toFixed(0) + " ", ioa, "::", self.sos.join(" "), soso.join(" | "));
} else {
self.sos[1] = iteration % self.subspace;
self.sos[2] = Math.floor(iteration / self.subspace) % self.subspace;
self.sos[3] = Math.floor(iteration / (self.subspace * self.subspace)) % self.subspace;
self.sos[4] = Math.floor(iteration / (self.subspace * self.subspace * self.subspace)) % self.subspace;
// self.sos[0] = Math.floor(iteration / (self.subspace * self.subspace * self.subspace * self.subspace)) % self.subspace;
}
if (iteration % 10000000 === 0) {
self.emit("status", (iteration / (self.space / 100)).toFixed(2), ioa + ":: " + cands.length + ":: " + self.sos.join(" "))
}
// console.log(iteration, self.sos.join(" "));
iteration++;
}
}
/* while (!sat && iteration < self.space) {
var io = 0;
var ff = true;
while (io < iomax && ff) {
var t = self.rulas[io];
ff = self[t.slice(0, 1)[0]].apply(self, t.slice(1))
if (ff) {
io++;
}
}
if (io > ioa) {
soso.push([].concat(self.sos));
ioa = io;
var tt = self.rulas.map(function(t) {
return [self[t.slice(0, 1)[0]].apply(self, t.slice(1))].concat(t);
})
console.log(iteration, io, ioa, iomax, self.sos.join(" "), tt.map(function(a) {
return a.join(" ")
}));
}
if (io >= iomax) {
sat = true;
// console.log((iteration).toFixed(0) + " ", ioa, "::", self.sos.join(" "), soso.join(" | "));
} else {
self.sos[4] = iteration % self.subspace;
self.sos[1] = Math.floor(iteration / self.subspace) % self.subspace;
self.sos[2] = Math.floor(iteration / (self.subspace * self.subspace)) % self.subspace;
self.sos[3] = Math.floor(iteration / (self.subspace * self.subspace * self.subspace)) % self.subspace;
self.sos[0] = Math.floor(iteration / (self.subspace * self.subspace * self.subspace * self.subspace)) % self.subspace;
}
if (iteration % 10000000 === 0) {
self.emit("status", (iteration / (self.space / 100)).toFixed(2), self.sos.join(" "))
}
iteration++;
}*/
if (sat) {
console.log("SOLUTION FOUND");
}
var tt = self.rulas.map(function(t) {
return [self[t.slice(0, 1)[0]].apply(self, t.slice(1))].concat(t);
})
console.log(iteration, self.sos.join(" "), tt.map(function(a) {
return a.join(" ")
}));
self.printit()
}
mo.prototype.printit = function(vals) {
var self = this;
var vals = vals || self.sos;
var lpad = function(s, l) {
while (s.length < l) {
s = " " + s
};
return s;
}
var rpad = function(s, l) {
while (s.length < l) {
s = s + " "
};
return s;
}
var s = [];
s.push([" ", 1, 2, 3, 4, 5].map(function(a) {
return lpad("" + a, 12)
}).join(" "));
Object.keys(self.variabler).map(function(k, ia) {
s.push([k, 0, 1, 2, 3, 4].map(function(a, io) {
return a == k ? rpad(k + ":" + vals[ia], 20) : lpad("" + self.variabler[k][self.current[vals[ia]][a]], 12)
}).join(" "))
// s.push( )
})
console.log(s.join("\n") + "\n")
}
mo.prototype.stats = function() {
console.log("steps ", this._internal_step_counter)
console.log(this);
}
var t = new mo()
.addVariabelSet("Nationality", [ "Dane","Norwegian", "Swede", "Englishman", "German"])
.addVariabelSet("Color", ["Red", "White", "Yellow", "Blue","Green"])
.addVariabelSet("Smokes", ["Prince", "Blend", "Dunhill", "BlueMasters", "PallMall"])
.addVariabelSet("Drinks", ["Water", "Bier", "Milk", "Tea", "Coffee"])
.addVariabelSet("Animals", ["Dogs", "Birds", "Cats", "Horses", "Fish"])
.addVariableTable("House", [0, 1, 2, 3, 4])
.addFunction("Neighbor", function(arg) {
var prop1 = Object.keys(arg)[0];
var prop2 = Object.keys(arg[Object.keys(arg)[1]])[0]
var val1 = arg[prop1];
var val2 = arg["Neighbor"][prop2];
var propid1 = Object.keys(this.variabler).indexOf(prop1)
var propid2 = Object.keys(this.variabler).indexOf(prop2)
var valid1 = (this.variabler[prop1]).indexOf(val1)
var valid2 = (this.variabler[prop2]).indexOf(val2)
return ["checkBoth", propid1, propid2, valid1, valid2, [prop1, val1, "Besides", prop2, val2].join(" ")]
})
.addFunction("Neighbor_Before", function(arg) {
var prop1 = Object.keys(arg)[0];
var prop2 = Object.keys(arg[Object.keys(arg)[1]])[0]
var val1 = arg[prop1];
var val2 = arg["Neighbor_Before"][prop2];
var propid1 = Object.keys(this.variabler).indexOf(prop1)
var propid2 = Object.keys(this.variabler).indexOf(prop2)
var valid1 = (this.variabler[prop1]).indexOf(val1)
var valid2 = (this.variabler[prop2]).indexOf(val2)
return ["checkLeft", propid1, propid2, valid1, valid2, [prop1, val1, "Before", prop2, val2].join(" ")]
})
.addFunction("Neighbor_After", function() {
var prop1 = Object.keys(arg)[0];
var prop2 = Object.keys(arg[Object.keys(arg)[1]])[0]
var val1 = arg[prop1];
var val2 = arg["Neighbor_After"][prop2];
var propid1 = Object.keys(this.variabler).indexOf(prop1)
var propid2 = Object.keys(this.variabler).indexOf(prop2)
var valid1 = (this.variabler[prop1]).indexOf(val1)
var valid2 = (this.variabler[prop2]).indexOf(val2)
return ["checkRight", propid1, propid2, valid1, valid2, [prop1, val1, "After", prop2, val2].join(" ")]
})
.addFunction("House", function(arg) {
var prop1 = Object.keys(arg)[0];
var prop2 = prop1
var propid1 = Object.keys(this.variabler).indexOf(prop1)
var val1 = arg[prop1];
var val2 = arg["House"];
var valid1 = (this.variabler[prop1]).indexOf(val1)
return ['checkn', propid1, propid1, valid1, val2, [prop1, val1, "House", val2].join(" ")]
})
.addClause({
"Nationality": "Norwegian",
"House": 0
})
.addClause({
"Drinks": "Milk",
"House": 2
})
.addClause({
"Nationality": "Norwegian",
"Neighbor": {
"Color": "Blue"
}
})
.addClause({
"Nationality": "Englishman",
"Color": "Red"
})
.addClause({
"Smokes": "Blend",
"Neighbor": {
"Drinks": "Water"
}
})
.addClause({
"Nationality": "Swede",
"Animals": "Dogs"
})
.addClause({
"Nationality": "Dane",
"Drinks": "Tea"
})
.addClause({
"Color": "Green",
"Neighbor_Before": {
"Color": "White"
}
})
.addClause({
"Color": "Green",
"Drinks": "Coffee"
})
.addClause({
"Smokes": "PallMall",
"Animals": "Birds"
})
.addClause({
"Color": "Yellow",
"Smokes": "Dunhill"
})
.addClause({
"Nationality": "German",
"Smokes": "Prince"
})
.addClause({
"Smokes": "Blend",
"Neighbor": {
"Animals": "Cats"
}
})
.addClause({
"Animals": "Horses",
"Neighbor": {
"Smokes": "Dunhill"
}
})
.addClause({
"Smokes": "BlueMasters",
"Drinks": "Bier"
})
/* .addClause("$House('Nationality','Norwegian')","eq","$House().first")
.addClause("$House('Drinks','Milk')","eq","$House().mid")
.addClause("$House('Nationality','Englishman')","eq","$House('Color','Red')")
.addClause("Math.abs($House('Smokes','Blend') - $House('Drinks','Water'))===1")
*/
/*.addClause(0,"Norwegian",-1,-1,-1,-1)
.addClause(2,-1,-1,-1,"Milk",-1)
.addClause(-1,"Englishman","Red",-1,-1,-1,-1)
.addClause(-1,"N Norwegian","Blue",-1,-1,-1,-1)
.addClause("Math.abs($House('Nationality','Norwegian') - $House('Color','Blue'))===1")
.addClause("Math.abs($House('Smokes','Blend') - $House('Drinks','Water'))===1")
.addClause("$House('Nationality','Swede')===$House('Animals','Dogs')")
.addClause("$House('Nationality','Dane')===$House('Drinks','Tea')")
.addClause("($House('Color','Green')+1)===$House('Color','White')")
.addClause("$House('Color','Green')===$House('Drinks','Coffee')")
.addClause("$House('Smokes','PallMall')===$House('Animals','Birds')")
.addClause("$House('Color','Yellow')===$House('Smokes','Dunhill')")
.addClause("Math.abs($House('Smokes','Blend')-$House('Animals','Cats'))===1")
.addClause("$House('Smokes','BlueMasters')===$House('Drinks','Bier')")
//.addClause("Math.abs($House('Animals','Horses')-$House('Smokes','Dunhill'))===1")
//.addClause("$House('Nationality','German')===$House('Smokes','Prince')")
*/
/*
The Englishman lives in the red house.
The Swede keeps dogs.
The Dane drinks tea.
The green house is just to the left of the white one.
The owner of the green house drinks coffee.
The Pall Mall smoker keeps birds.
The owner of the yellow house smokes Dunhills.
The man in the center house drinks milk.
The Norwegian lives in the first house.
The Blend smoker has a neighbor who keeps cats.
The man who smokes Blue Masters drinks bier.
The man who keeps horses lives next to the Dunhill smoker.
The German smokes Prince.
The Norwegian lives next to the blue house.
The Blend smoker has a neighbor who drinks water.
*/
//console.log(t.randoma("House"));
//t.stats();
t.on("status", function(per, found) {
console.log("PER", per, found);
})
var result = t.solve();
console.log(t.printit(result));
/*
var Colors = ["Red", "White", "Yellow", "Blue", "Green"],
Nationality = ["Norwegian", "Dane", "Swede", "Englishman", "German"],
Cigarettes = ["Prince", "Blend", "Dunhill", "Blue Masters", "Pall Mall"],
Drinks = ["Water", "Bier", "Milk", "Tea", "Coffee"],
Animals = ["Dogs", "Birds", "Cat", "Horses", "Fish"];*/