0

I am having trouble generating all lists that meet certain criteria.

city(new_york, 47).
city(chicago, 100).

all_unique([]).
all_unique([H|T]) :- H = [] ; (not(member(H, T)), all_unique(T)).

cities([Head|Tail]) :-
    length(Tail, L),
    L < 2,
    city(Head, _A),
    (Tail = [] ; cities(Tail)).

When I issue the query cities(L), I want it to generate all lists of cities with a maximum length of 2 and no repetition. What it does now is return all possible lists and then keep trying lists that obviously don't meet the criteria.

?- cities(L).
L = [new_york] ;
L = [chicago] ;
L = [new_york, new_york] ;
L = [new_york, chicago] ;
L = [chicago, new_york] ;
L = [chicago, chicago] ;
ERROR: Out of global stack
?-

How do I tell Prolog not to try lists that are too long or have repeated items?

Josh R
  • 145
  • 3
  • 8

1 Answers1

3

Your definition of all_unique/1 is better based on :

all_unique([]).
all_unique([E|Es]) :-
   maplist(dif(E), Es),
   all_unique(Es).

Based on maplist/2 you can define cities/1 like this:

city_(new_york, 47).
city_(chicago, 100).

city(C) :-
   city_(C, _).

cities(List) :-
   length(Ref, 2),
   append(List, _, Ref),
   all_unique(List),
   maplist(city, List).

Sample query:

?- cities(Xs).
Xs = [] ;
Xs = [new_york] ;
Xs = [chicago] ;
Xs = [new_york, chicago] ;
Xs = [chicago, new_york] ;
false.                                    % terminates universally
Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166