blob: 2999fc09acdae9e147dd5de4cd63e0ec78551419 [file] [edit]
// See http://unriskinsight.blogspot.com/2014/06/fast-functional-goats-lions-and-wolves.html
// Sascha Kratky (kratky@unrisk.com), uni software plus GmbH & MathConsult GmbH
//
// run with Google v8:
// d8 magicForest.js -- 117 155 106
//
// run with Mozilla SpiderMonkey:
// js magicForest.js 117 155 106
function Forest(goats, wolves, lions) {
this.goats = goats;
this.wolves = wolves;
this.lions = lions;
}
Forest.prototype.wolfDevoursGoat = function() {
if (this.goats > 0 && this.wolves > 0)
return new Forest(this.goats - 1, this.wolves - 1, this.lions + 1);
else
return null;
}
Forest.prototype.lionDevoursGoat = function() {
if (this.goats > 0 && this.lions > 0)
return new Forest(this.goats - 1, this.wolves + 1, this.lions - 1);
else
return null;
}
Forest.prototype.lionDevoursWolf = function() {
if (this.lions > 0 && this.wolves > 0)
return new Forest(this.goats + 1, this.wolves - 1, this.lions - 1);
else
return null;
}
Forest.prototype.meal = function() {
return [this.wolfDevoursGoat(), this.lionDevoursGoat(), this.lionDevoursWolf()].filter(
function(f) { return f !== null; })
}
Forest.prototype.isStable = function() {
if (this.goats === 0) return (this.wolves === 0) || (this.lions === 0);
return (this.wolves === 0) && (this.lions === 0);
}
Forest.prototype.toString = function()
{
return "[goats=" + this.goats + ", wolves=" + this.wolves + ", lions=" + this.lions + "]";
}
Forest.compare = function(forest1, forest2) {
var cmp = forest1.goats-forest2.goats;
if (cmp !== 0) return cmp;
cmp = forest1.wolves-forest2.wolves;
if (cmp !== 0) return cmp;
return forest1.lions-forest2.lions;
}
function meal(forests) {
var nextForests = [];
forests.forEach(function(forest) {
nextForests.push.apply(nextForests, forest.meal())
});
// remove duplicates
return nextForests.sort(Forest.compare).filter(function(forest, index, array) {
return (index === 0 || Forest.compare(forest, array[index - 1]) !== 0);
});
}
function devouringPossible(forests) {
return forests.length > 0 && !forests.some(function(f) { return f.isStable(); });
}
function stableForests(forests) {
return forests.filter(function(f) { return f.isStable(); });
}
function findStableForests(forest) {
var forests = [forest];
while (devouringPossible(forests)) {
forests = meal(forests);
}
return stableForests(forests);
}
function go(g,w,l) {
var initialForest = new Forest(g, w, l);
findStableForests(initialForest)/*.forEach(function(f){ console.log(f); })*/
}
function goUI()
{
d=new Date();
g=parseInt("217");
w=parseInt("255");
l=parseInt("206");
go(g, w, l);
// print("Time taken: " + (new Date() - d) + "ms");
}
goUI();