1

Given a set of routes a given station has, such us :

route(TubeLine, ListOfStations).

route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...

I am required to find names of lines that have a specific station in common. The result must be ordered, with non-repeated stations and must return an empty list, if there were no results. So, querying

| ?- lines(i, Ls).

Should give:

Ls = [blue,red,silver] ? ;
no

I tried doing the following:

lines(X, L) :- setof(L1, findall(W, (route(W, Stations),member(X, Stations)),L1), L).

However, it gives the following as an answer:

Is = [[blue,silver,red]];
no

So unordered with double braces. I tried using just findall, but the result is not ordered. I know I could then write sort function and pass that through, however I was wondering if it is possible to use just findall and setof in this instance?

false
  • 10,264
  • 13
  • 101
  • 209
qwerty
  • 321
  • 1
  • 5
  • 13

1 Answers1

2

Actually, it's easier than your attempt, but you need to grasp the peculiar setof' behaviour wrt free variables, and account for the eventuality that an unknown station was required (setof/3 fails if there are no solutions).

 lines(X, Ls) :-
   setof(L, Stations^(route(L, Stations), member(X, Stations)), Ls)
   -> true ; Ls = [].

An easier alternative, as you said, use findall/3 exactly as you're doing (without setof!), and sort the output.

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • I see! Thank you for your answer! Do you know any resources where I could practice such behaviour? – qwerty Jan 06 '17 at 16:22
  • the whole [chapter 11](http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlch11) of 'learn Prolog now' is worth to read, and specifically the [setof/3 section](http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse49) – CapelliC Jan 06 '17 at 16:29