2

I have a zebra/Einstein type Prolog puzzle very similar to the one depicted here:

A "Building" Riddle in Prolog.

The riddle is:

There are two buildings, each one has tree apartments (one apartment on each floor): one apartment of 3 rooms, one of 4 rooms and one of 5 rooms.

Dana, Joni and Noah live in building 1. Ron, Gale and Aron live in building 2.

Joni's apartment is higher then Dana's and Noah's. It means he lives on the third floor of building 1. Noah and Gale live on the same floor (in different buildings). Ron has one more room than Aron. Ron lives one floor above Gale. The highest apartment in building 2 is the 5 rooms apartment.

I need to find in which floor everyone lives.

This is the code.

solve([dana,building1,F1,R1],
      [noah,building1,F2,R2],
      [joni,building1,F3,R3],
      [gale,building2,F4,R4],
      [ron, building2,F5,R5],
      [aron,building2,F6,R6]) :-
   assign([1,2,3],[F1,F2,F3]),
   assign([1,2,3],[F4,F5,F6]),
   assign([3,4,5],[R1,R2,R3]),
   assign([3,4,5],[R4,R5,R6]),
   F3 > F2,
   F3 > F1,
   F2 =:= F4,
   R5 =:= R6-1,
   F5 =:= F4+1,
   (  F4 =:= 3, R4 =:= 5
   ;  F5 =:= 3, R5 =:= 5
   ;  F6 =:= 3, R6 =:= 5
   ).

assign(_,[]).
assign(Digs,[D|Vars]):-
   del(D,Digs,Digs1),
   assign(Digs1,Vars).

del(X,L,L1) :-
   remove(X,L,L1).

remove([],X,[]) :- !. 
remove([X|T],X,L1) :- !, remove(T,X,L1).   
remove([H|T],X,[H|L1]) :- remove(T,X,L1).

I don't understand which query to use with this following solution? When I try the query from the original post,

solve([dana,building1,F1,R1],[noah,building1,F2,R2],[joni,building1,F3,R3],
      [gale,building2,F4,R4],[ron, building2,F5,R5],[aron,building2,F6,R6]).

it says

Type error: `evaluable' expected, found `[]' (an empty_list)
In:
   [2] []>[]
   [1] solve([dana,building1|...],[noah,building1|...],[joni,building1|...],
             [gale,building2|...],[ron, building2|...],[aron,building2|...]) 
at  line 1

What is the correct query for this?

Thanks.

Community
  • 1
  • 1
Jamaico
  • 87
  • 10
  • `solve` calls `assign`, which calls `del` which calls `remove`, which is not defined in this code. You're correct to call `solve`. You'll need to hunt for a definition of `remove`, likely somewhere around where you got this code from. Or it it's expecting it to be a built-in and you're running a different version of Prolog from the author. – Paul Brown Aug 02 '19 at 00:24
  • [SWI's select/3](https://www.swi-prolog.org/pldoc/man?predicate=select/3) is a natural fit to this problem. – Will Ness Aug 02 '19 at 07:30
  • @PaulBrown I've added remove but now it fails for another reason. can you possibly help? thanks. – Jamaico Aug 02 '19 at 08:58
  • BTW if you have a working code now, you can post it on [CodeReview](https://codereview.stackexchange.com/) and ask for it to be reviewed there, to get some feedback on the code, whether it can be coded differently / "better" / simpler, etc. (hint: it can). Be sure to check that site's guidelines for asking if you decide to do so. – Will Ness Aug 03 '19 at 20:54

1 Answers1

1

The query is correct for the given code.

The code contains an error.

del(X,L,L1) :-
   remove(X,L,L1).   % WRONG

You need to change the order of arguments in the call to remove/3, to correspond to their use in the definition of remove/3.

You could discover it by testing in the small. Just trying the query assign([1,2,3],Floors) at the prompt, you'd discover whether it works as intended or not.

Or del(D,[1,2,3],Digs1), following the assign/2 definition,

assign([1,2,3],[D|Vars]):-
   del(D,[1,2,3],Digs1),
   ..... .

Or remove(D,[1,2,3],Digs1), following the del/3 definition,

del(D,[1,2,3],Digs1) :-
   remove(D,[1,2,3],Digs1).

Looking at the definition

remove([],   X,[]    ) :- !. 
remove([X|T],X,L1    ) :- !, remove(T,X,L1).
remove([H|T],X,[H|L1]) :- remove(T,X,L1).

knowing that our intended meaning for D is to hold one digit from among [1,2,3],

(the rest is intentionally left blank)

Will Ness
  • 70,110
  • 9
  • 98
  • 181