guy43535453
guy43535453

Reputation: 13

Why is this prolog function running indefinitely, how do I fix it?

I am trying to create a prolog predicate to solve this zebra problem however It keeps on running indefinitely and does not produce a result, how can I fix this.

Here is the Zebra Problem:

The five biggest DJs in the world are going to play in an electronic music festival, each one in a specific stage. They are side by side waiting to play. Find out their nationalities,vhobbies and which genre they play.

DJ Properties:

Clues

Here is my code so far:

member(X, [X|_]).
member(X, [_|T]) :- member(X, T).

left_of(A, B, L) :- append(_, [A|T], L), member(B, T).

next_to(A, B, L) :- left_of(A, B, L) ; left_of(B, A, L).

solve(DJs) :-
    DJs = [_, _, _, _, _],

    % Clue 1
    member([scott, _, _, _, _, _], DJs),
    member([_, white, _, _, _, _], DJs),
    left_of([scott, _, _, _, _, _], [_, white, _, _, _, _], DJs),

    % Clue 2
    DJs = [_, _, _, [_, _, _, arcadia, _, _], _],

    % Clue 3
    DJs = [[_, _, _, _, 30, _], _, _, _, _],

    % Clue 4
    member([canadian, _, _, _, _, _], DJs),
    member([_, _, edm, _, _, _], DJs),
    left_of([canadian, _, _, _, _, _], [_, _, edm, _, _, _], DJs),

    % Clue 5
    next_to([_, _, _, _, _, painting], [_, _, dubstep, _, _, _], DJs),

    % Clue 6
    left_of([scott, _, _, _, _, _], [_, black, _, _, _, _], DJs),
    left_of([_, black, _, _, _, _], [_, _, dubstep, _, _, _], DJs),

    % Clue 7
    next_to([french, _, _, _, _, _], [_, blue, _, _, _, _], DJs),

    % Clue 8
    (DJs = [[_, _, _, _, _, camping], _, _, _, _] ; DJs = [_, _, _, _, [_, _, _, _, _, camping]]),

    % Clue 9
    member([_, blue, _, asgard, _, _], DJs),

    % Clue 10
    left_of([_, green, _, _, _, _], [_, _, _, _, _, painting], DJs),
    left_of([_, _, _, _, _, painting], [_, blue, _, _, _, _], DJs),

    % Clue 11
    DJs = [_, _, _, [_, _, _, _, 40, _], _],

    % Clue 12
    next_to([_, _, trance, _, _, _], [_, _, dubstep, _, _, _], DJs),

    % Clue 13
    left_of([canadian, _, _, _, _, _], [_, _, _, _, _, juggling], DJs),

    % Clue 14
    left_of([_, black, _, _, _, _], [_, _, _, _, _, singing], DJs),

    % Clue 15
    next_to([_, _, _, _, 35, _], [_, _, _, _, _, juggling], DJs),

    % Clue 16
    left_of([dutch, _, _, _, _, _], [_, _, _, _, 25, _], DJs),
    left_of([_, _, _, _, 25, _], [_, _, _, _, 40, _], DJs),

    % Clue 17
    left_of([_, blue, _, _, _, _], [_, _, _, xibalba, _, _], DJs),

    % Clue 18
    member([_, _, _, valhalla, _, surfing],DJs),

    % Clue 19
    member([_, red, _, _, _, _], DJs),
    left_of([french, _, _, _, _, _], [_, red, _, _, _, _], DJs),

    % Check properties
    member([american, _, _, _, _, _], DJs),
    member([canadian, _, _, _, _, _], DJs),
    member([dutch, _, _, _, _, _], DJs),
    member([french, _, _, _, _, _], DJs),
    member([scottish, _, _, _, _, _], DJs),

    member([_, black, _, _, _, _], DJs),
    member([_, blue, _, _, _, _], DJs),
    member([_, green, _, _, _, _], DJs),
    member([_, red, _, _, _, _], DJs),
    member([_, white, _, _, _, _], DJs),

    member([_, _, drum_and_bass, _, _, _], DJs),
    member([_, _, dubstep, _, _, _], DJs),
    member([_, _, edm, _, _, _], DJs),
    member([_, _, house, _, _, _], DJs),
    member([_, _, trance, _, _, _], DJs),

    member([_, _, _, arcadia, _, _], DJs),
    member([_, _, _, asgard, _, _], DJs),
    member([_, _, _, shangri_la, _, _], DJs),
    member([_, _, _, valhalla, _, _], DJs),
    member([_, _, _, xibalba, _, _], DJs),

    member([_, _, _, _, 25, _], DJs),
    member([_, _, _, _, 30, _], DJs),
    member([_, _, _, _, 35, _], DJs),
    member([_, _, _, _, 40, _], DJs),
    member([_, _, _, _, 45, _], DJs),

    member([_, _, _, _, _, camping], DJs),
    member([_, _, _, _, _, juggling], DJs),
    member([_, _, _, _, _, painting], DJs),
    member([_, _, _, _, _, singing], DJs),
    member([_, _, _, _, _, surfing], DJs).

Upvotes: 1

Views: 146

Answers (1)

false
false

Reputation: 10102

Try to put your code into small manageable parts first. And then, use the to see if the answers you get are the answers you want. Just your first clue is:

clue1(DJs) :-
    DJs = [_, _, _, _, _],
    % Clue 1
    member([scott, _, _, _, _, _], DJs),
    member([_, white, _, _, _, _], DJs),
    left_of([scott, _, _, _, _, _], [_, white, _, _, _, _], DJs).

?- clue1(DJs).
   DJs = [[scott,white,_A,_B,_C,_D],[_E,white,_F,_G,_H,_I],_J,_K,_L], unexpected
;  DJs = [[scott,white,_A,_B,_C,_D],_E,[_F,white,_G,_H,_I,_J],_K,_L], unexpected
;  ... % many answers omitted
;  DJs = [[_A,white,_B,_C,_D,_E],[scott,_F,_G,_H,_I,_J],[_K,white,_L,_M,_N,_O],_P,_Q], unexpected
;  ... % many answers omitted
;  false.

In total, just for the first clue, there are 250 answers. Many of which can never lead to a solution: The first two answers have two white instead of just one. The last shown answer has scott to the right (and not left) of a white. It is quite similar with the subsequent clues. Let's remove the two member/2 goals since they are already implied by left_of/2. As a result we narrowed down the problem to 10 answers.

?- clue1(DJs).
   DJs = [[scott,_A,_B,_C,_D,_E],[_F,white,_G,_H,_I,_J],_K,_L,_M]
;  DJs = [[scott,_A,_B,_C,_D,_E],_F,[_G,white,_H,_I,_J,_K],_L,_M]
;  DJs = [[scott,_A,_B,_C,_D,_E],_F,_G,[_H,white,_I,_J,_K,_L],_M]
;  DJs = [[scott,_A,_B,_C,_D,_E],_F,_G,_H,[_I,white,_J,_K,_L,_M]]
;  DJs = [_A,[scott,_B,_C,_D,_E,_F],[_G,white,_H,_I,_J,_K],_L,_M]
;  DJs = [_A,[scott,_B,_C,_D,_E,_F],_G,[_H,white,_I,_J,_K,_L],_M]
;  DJs = [_A,[scott,_B,_C,_D,_E,_F],_G,_H,[_I,white,_J,_K,_L,_M]]
;  DJs = [_A,_B,[scott,_C,_D,_E,_F,_G],[_H,white,_I,_J,_K,_L],_M]
;  DJs = [_A,_B,[scott,_C,_D,_E,_F,_G],_H,[_I,white,_J,_K,_L,_M]]
;  DJs = [_A,_B,_C,[scott,_D,_E,_F,_G,_H],[_I,white,_J,_K,_L,_M]]
;  false.

Now, you can observe the failure with some patience. To improve speed you could move up clues, that consist of a single unification like, clue 2, 3, and 11. Also you could ensure with the help of dif/2 that all corresponding entries are different. This would improve speed, but still there would be failure.

Here is a generalization of your program that still fails. I have removed many of the goals in it, leaving only:

solve(DJs) :-
    DJs = [_, _, _, _, _],
    left_of([scott, _, _, _, _, _], [_, white, _, _, _, _], DJs),
    member([american, _, _, _, _, _], DJs),
    member([canadian, _, _, _, _, _], DJs),
    member([dutch, _, _, _, _, _], DJs),
    member([french, _, _, _, _, _], DJs),
    member([scottish, _, _, _, _, _], DJs).

?- solvex(DJs).
   false, unexpected.

Because this fragment fails, also your original program will fail. By fixing this problem, your program works. So you should be able to figure that out. Finally, your problem has, however, 48 solutions which is a bit unusual for a zebra puzzle which typically has only a single solution.

Upvotes: 1

Related Questions