flannel jesus
Philosophim
bert1
flannel jesus
RussellAAccepted Answer
So, whose door is White? And what medium does the Kenyan use for his art? — flannel jesus
RussellA
Hey you got it! — flannel jesus
Tarskian
$ ./doors-artists.js
final number of complete solutions:1
----
door_index hair_color nationality musical_style door_color profession
1 black Brazilian classical white oil_painter
2 grey Indian jazz pink sculptor
3 blonde Australian hiphop teal dig_painter
4 brunette Canadian reggae orange waterc_painter
5 red Kenyan elec_dance purple photographer
#!/usr/bin/env qjs
//The following is what the French would call "le référentiel"
var properties={
"hair_color":["black","brunette","grey","red","blonde"],
"nationality":["Indian","Brazilian","Canadian","Australian","Kenyan"],
"musical_style":["classical","elec_dance","jazz","reggae","hiphop"],
"door_color":["teal","pink","purple","orange","white"],
"profession":["photographer","sculptor","oil_painter",
"dig_painter","waterc_painter"]
};
//constraints_type_1:
//It specifies that a particular property value must always
//coexist with another property value
var constraints_type_1 = [
{"cix":1,"property_needle_1":"hair_color","value_needle_1":"black",
"property_needle_2":"musical_style","value_needle_2":"classical"},
{"cix":2,"property_needle_1":"musical_style","value_needle_1":"elec_dance",
"property_needle_2":"profession","value_needle_2":"photographer"},
{"cix":4,"property_needle_1":"door_index","value_needle_1":3,
"property_needle_2":"door_color","value_needle_2":"teal"},
{"cix":5,"property_needle_1":"profession","value_needle_1":"sculptor",
"property_needle_2":"door_color","value_needle_2":"pink"},
{"cix":9,"property_needle_1":"hair_color","value_needle_1":"red",
"property_needle_2":"door_color","value_needle_2":"purple"},
{"cix":10,"property_needle_1":"profession","value_needle_1":"dig_painter",
"property_needle_2":"hair_color","value_needle_2":"blonde"},
{"cix":11,"property_needle_1":"profession","value_needle_1":"waterc_painter",
"property_needle_2":"nationality","value_needle_2":"Canadian"},
{"cix":12,"property_needle_1":"profession","value_needle_1":"oil_painter",
"property_needle_2":"door_index","value_needle_2":1},
{"cix":13,"property_needle_1":"door_color","value_needle_1":"orange",
"property_needle_2":"musical_style","value_needle_2":"reggae"},
{"cix":14,"property_needle_1":"nationality","value_needle_1":"Australian",
"property_needle_2":"musical_style","value_needle_2":"hiphop"}
];
//check constraints of type 1
function isValidForType1(solution) {
for(let assignment of solution) {
for(let constraint of constraints_type_1) {
let property_needle_1=constraint["property_needle_1"];
let value_needle_1=constraint["value_needle_1"];
let property_needle_2=constraint["property_needle_2"];
let value_needle_2=constraint["value_needle_2"];
//the assignment must have both properties assigned
//for a constraint violation to even be possible
if(!assignment.hasOwnProperty(property_needle_1)) continue;
if(!assignment.hasOwnProperty(property_needle_2)) continue;
//check for: value1 correct but value2 wrong
if(assignment[property_needle_1]==value_needle_1 &&
assignment[property_needle_2]!==value_needle_2)
return false;
//check for: value2 correct but value1 wrong
if(assignment[property_needle_2]==value_needle_2 &&
assignment[property_needle_1]!==value_needle_1)
return false;
}
}
return true;
}
//constraints_type_2
//It specifies that a particular property value must always coexist
//with a property value of a neigbor
var constraints_type_2 = [
{"cix":3,"property_needle":"nationality","value_needle":"Indian",
"property_neighbor":"musical_style","value_neighbor":"classical"},
{"cix":7,"property_needle":"nationality","value_needle":"Brazilian",
"property_neighbor":"musical_style","value_neighbor":"jazz"},
{"cix":8,"property_needle":"hair_color","value_needle":"grey",
"property_neighbor":"profession","value_neighbor":"oil_painter"}
];
// utility function: find neighbor of assignment by door index
function findNeighborByDoorIndex(solution,door_index) {
for(let assignment of solution) {
if(assignment["door_index"]==door_index)
return assignment;
}
//not found
//This should never happen. Maybe throw an exception of sorts?
return null;
}
//check constraints of type 2
function isValidForType2(solution) {
for(let constraint of constraints_type_2) {
let property_needle=constraint["property_needle"];
let value_needle=constraint["value_needle"];
let property_neighbor=constraint["property_neighbor"];
let value_neighbor=constraint["value_neighbor"];
for(let assignment of solution) {
//the assignment must have the property assigned
if(!assignment.hasOwnProperty(property_needle)) continue;
//the assignment must have the value assigned to the property
if(assignment[property_needle]!==value_needle) continue;
//retrieve door_index from assignment
let door_index=assignment["door_index"];
//we assume that we will not find a valid neighbor
let foundValidNeighbor=false;
//check left neighbor, if applicable
if(door_index>1) {
let assignmentLeftNeighbor=findNeighborByDoorIndex(solution,door_index-1);
if(!assignmentLeftNeighbor.hasOwnProperty(property_neighbor)) continue;
if(assignmentLeftNeighbor[property_neighbor]==value_neighbor) {
foundValidNeighbor=true;
}
}
//check right neighbor, if applicable
if(door_index<5) {
let assignmentRightNeighbor=findNeighborByDoorIndex(solution,door_index+1);
if(!assignmentRightNeighbor.hasOwnProperty(property_neighbor)) continue;
if(assignmentRightNeighbor[property_neighbor]==value_neighbor) {
foundValidNeighbor=true;
}
}
if(!foundValidNeighbor) {
return false;
}
}
}
return true;
}
//check constraints of type 3
//cix=6, Special case.
//this function only checks:
//"The red head is the right-hand neighbor of the Brunette."
function isValidForType3(solution) {
for(let assignment of solution) {
//the assignment must have the property assigned
if(!assignment.hasOwnProperty("hair_color")) continue;
//the assignment must have the value assigned to the property
if(assignment["hair_color"]!=="brunette") continue;
//we found the brunette
//check that there is a right-hand neighbor
var door_index=assignment["door_index"];
//Brunette cannot be assigned to door 5
if(door_index==5) return false;
//find right-hand neighbor
var assignmentRightNeighbor=findNeighborByDoorIndex(solution,door_index+1);
//The right-hand neighbor must be the red head
if(assignmentRightNeighbor["hair_color"]!=="red") return false;
}
return true;
}
//validate solution
function isValid(solution)
{
let validForType1=isValidForType1(solution);
if(!validForType1) return false;
let validForType2=isValidForType2(solution);
if(!validForType2) return false;
let validForType3=isValidForType3(solution);
if(!validForType3) return false;
return true;
}
//permutator
const permutator = (inputArr) => {
let result = [];
const permute = (arr, m = []) => {
if (arr.length === 0) {
result.push(m)
} else {
for (let i = 0; i < arr.length; i++) {
let curr = arr.slice();
let next = curr.splice(i, 1);
permute(curr.slice(), m.concat(next))
}
}
}
permute(inputArr)
return result;
}
//for debugging purposes
function output(label,structure) {
console.log(label+":"+JSON.stringify(structure));
}
//initial solution space
var solutionSpace=[
[{"door_index":1},{"door_index":2},{"door_index":3},
{"door_index":4},{"door_index":5}]
];
//iterate over the properties
for(let property of Object.keys(properties)) {
let propertyValues=properties[property];
let permutations=permutator(propertyValues);
let newSolutionSpace=[];
//iterate over the permutations of the property values
for(let permutation of permutations) {
//cartesian multiplication of existing solutions with
//new permutations
for(let solution of solutionSpace) {
let newSolution=[];
for (let i = 0; i < solution.length; i++) {
let assignment=solution[i];
let newAssignment={...assignment};
newAssignment[property]=permutation[i];
newSolution.push(newAssignment);
}
//verify if the solution satisfies all constraints
if(isValid(newSolution)){
newSolutionSpace.push(newSolution);
}
}
}
//the new solution space now replaces the existing one
solutionSpace=newSolutionSpace;
}
console.log("final number of complete solutions:"+solutionSpace.length);
//output the solutions
function pad(str){
let pad=Array(15).join(' ');
return (str + pad).substring(0, pad.length);
}
console.log("----");
let headerPrintedAlready=false;
for(let solution of solutionSpace) {
for(let assignment of solution) {
let line="";
for(let key of Object.keys(assignment)) {
line=line+pad(assignment[key]);
}
if(!headerPrintedAlready) {
let header="";
for(let key of Object.keys(assignment)) {
header=header+pad(key);
}
console.log(header);
console.log("");
headerPrintedAlready=true;
}
console.log(line);
}
console.log("----");
}
Get involved in philosophical discussions about knowledge, truth, language, consciousness, science, politics, religion, logic and mathematics, art, history, and lots more. No ads, no clutter, and very little agreement — just fascinating conversations.