A tough (but solvable) riddle.

flannel jesus July 15, 2024 at 16:35 2525 views 10 comments
This riddle was not invented by me, but I have changed all the details to avoid it being easy to look up the canonical answer.

There are 5 apartments in a row. In each apartment is a person with a unique hair color, nationality and preferred musical style. Every person is an artist in a unique medium. Each of the 5 front doors is colored a unique color. So, we're facing all 5 doors in front of us, and I give you the following information:

1. The guy with Black hair listens to Classical Music
2. The Photographer listens to Electronic Dance Music.
3. The guy next door to the Indian guy listens to Classical Music.
4. The middle door is painted Teal.
5. The sculptor's door is painted pink.
6. The red head is the right-hand neighbor (from our pov looking at the doors) of the Brunette.
7. The man who listens to Jazz lives in the apartment next to the Brazilian.
8. The oil painter lives next to the guy with grey hair.
9. The red head has a purple door.
10. The Digital Painter has blonde hair.
11. The Watercolor Painter is Canadian.
12. The oil painter lives in the first (leftmost) apartment.
13. The guy with the Orange door likes Reggae.
14. The Australian likes Hip Hop.

So, whose door is White? And what medium does the Kenyan use for his art?

This is deducible, but not easily. In fact all 5 properties of all 5 apartments are deducible.

Comments (10)

bert1 July 15, 2024 at 16:59 #917706
Might this help?

User image
flannel jesus July 15, 2024 at 17:13 #917710
Reply to bert1 I didn't use something like that, but it might be helpful for someone
Philosophim July 15, 2024 at 21:11 #917793
I wouldn't call this a riddle. This is a logic problem. They can be pretty fun to do, but there are countless online. https://www.brainzilla.com/logic/logic-grid/ if you want to join up and play a bunch.
bert1 July 16, 2024 at 08:57 #917985
Reply to flannel jesus I'm impressed you did it without a grid. I suppose there are other ways to record the information.
flannel jesus July 16, 2024 at 09:17 #917988
Reply to bert1 I mean I used a hand-written "grid", just not one like that multi-layered one you posted. I had columns where i recorded information about each spot.

It was really annoying when I got to the point where I could no longer straight-forwardly deduce any answers, though, and had to copy my grid by hand to test out making certain assumptions.
RussellA July 17, 2024 at 08:38 #918282
Quoting flannel jesus
So, whose door is White? And what medium does the Kenyan use for his art?


The Brazilian's door is white. The Kenyan is a photographer.
flannel jesus July 17, 2024 at 10:00 #918288
Reply to RussellA Hey you got it!
RussellA July 17, 2024 at 10:13 #918290
Quoting flannel jesus
Hey you got it!


Not very elegantly, I'm afraid. Thanks for posting the logic problem.
Tarskian July 18, 2024 at 15:11 #918601
I've had a go at this one:

$ ./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


For the aficionados, the javascript program:


#!/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("----");
}
RussellA July 18, 2024 at 15:56 #918604
Quoting Tarskian
For the aficionados, the javascript program:


User image