prologzebra-puzzle

Prolog Room Adjacency Puzzle


I am working on an assignment and I have to write a prolog program to solve a puzzle where there are 5 rooms and there are five people, Hunter, Laura, Arnie, Addiley and Ramey. Hunter cannot be in room 5, Laura cannot be in room 1, Arnie cannot be in room 1 or 5, Arnie cannot be adjacent to Laura or Addiley and Ramey is in a room with a higher index than Laura. I have seen various other answers for the exact same problem but no solution has worked thus far.

I have gotten most of the logic down, however the logic to check whether a person is adjacent to another person seems to not be working.

Here is my code:

layout([bedroom(_, 1), bedroom(_, 2), bedroom(_, 3), bedroom(_, 4), bedroom(_, 5)]).

adj(B,C):- B is C+1; B is C-1.

hallway(X) :- layout(X),
        member(bedroom(hunter, H), X),
        member(bedroom(laura, L), X),
        member(bedroom(arnie, N), X),
        member(bedroom(addiley, A), X),
        member(bedroom(ramey, R), X),
        H \= 5,
        L \= 1,
        N \= 1,
        N \= 5,
        N \= adj(N, L),
        N \= adj(N, A),
        R > L.

The resulting output is:

X = [bedroom(hunter,1),bedroom(laura,2),bedroom(arnie,3),bedroom(addiley,4),bedroom(ramey,5)]

However in this output, Arnie is adjacent to Laura and Addiley, seemingly breaking the rules that put into the adjacency logic. Why is it when I check for adjacency nothing seems to happen?


Solution

  • You are very close (and upvote having code and asking a specific question). The problem is here:

        N \= adj(N, L),
        N \= adj(N, A),
    

    adj(N, L) is true if they are adjacent numbers, and false if they aren't. It doesn't return a value, it just is true or isn't true and the code continues forwards or stops and backtracks and changes member() and then tries again; so you just need:

        not(adj(N, L)),
        not(adj(N, A)),
    

    to say that "it must not be true that Arnie and Laura have adjacent room numbers".

    Compare that with your line in English: "Arnie's room number must not be equal to whether Arnie's room number is adjacent to Laura's", which makes no sense. (Or, more specifically since = is different in Prolog, your line says "Arnie's room number variable N must not unify with the term adj(N, L). Well, member() bound variable N to hold a room number at this point, so variable N can't also be bound to the line of code adj(N, L). So the number and the code are always different, the lines were always true and they weren't testing anything useful).