0

I'm currently trying to answer a segment for a piece of coursework. As the title indicates I need to create a rule to state which stations are on a particular line. I've already inputted the data needed in previous pieces of the script and have been trying to make use of the findall function. Clearly something has gone wrong, can you guide me as to where I'm going wrong?

Please don't give me a complete answer.

Here is the segment of code.

station(kennington,northern).
station(embankment,northern).
station(tottenhamcourtroad,northern).
station(warrenstreet,northern).
station(euston,northern).

/*Q3 which stations are on a particular Underground line? */

line(Line, ListOfStations) :-
    findall(Line,X),
    findall(X,ListOfStations).
false
  • 10,264
  • 13
  • 101
  • 209
  • Related question: [How can I write rules for the following questions and facts in Prolog?](http://stackoverflow.com/q/41742556/1243762) – Guy Coder Jan 19 '17 at 18:18
  • Related question: [Prolog Tube Line Task](http://stackoverflow.com/q/41706982/1243762) – Guy Coder Jan 19 '17 at 18:18
  • Related question: [Using a list from a fact within Prolog rules](http://stackoverflow.com/q/41698790/1243762) – Guy Coder Jan 19 '17 at 18:19
  • 2
    From the tag I see you are using `SWI-Prolog` and in the question you mention the `findall` function, which leads me to think [findall/3](http://www.swi-prolog.org/pldoc/man?predicate=findall/3) but your `findall` has only two arguments. Can you provide the code for your `findall`. For an example of what I am was expecting with `findall` see [WikiBooks](https://en.wikibooks.org/wiki/Prolog/Bagof,_Setof_and_Findall). – Guy Coder Jan 19 '17 at 18:25
  • 1
    @GuyCoder: I think it is obvious that the OP wanted to use a `findall/3` but forgot to query for stations, etc. – Willem Van Onsem Jan 19 '17 at 19:18

1 Answers1

2

The usage of findall you are looking for is findall(+Template, :Goal, -Bag) (as Guy Coder said: findall/3).

What this means is find each set of variables that satisfy :Goal as written (in this instance, you are looking for station(X,Line)), then place them in the -Bag list (which you call ListOfStations) using the +Template (which, for you, is presumably X, to create [X1,X2,X3|...]).

Put them all together and you get (spoiler warning, I guess?):

findall(X, station(X,Line), ListOfStations).

Which will output:

[kennington, embankment, tottenhamcourtroad, warrenstreet, euston]

Where the list is ordered by the order of the facts.

Additional Information:

If your template looks like [X] instead of just X:

findall([X], station(X,Line), ListOfStations).

Your output looks like this:

[[kennington], [embankment], [tottenhamcourtroad], [warrenstreet], [euston]]

And you could even make it look like (station,X) to get:

findall((station,X), station(X,Line), ListOfStations).

Giving you:

[(station,kennington), (station,embankment), (station,tottenhamcourtroad), (station,warrenstreet), (station,euston)]

And if you want to find every combination of stations on a line, the :Goal can be compound as well, like so:

findall((X,Y), (station(X,Line),station(Y,Line),X\=Y), ListOfStations).

Giving you something silly like this:

[(kennington,embankment), (kennington,tottenhamcourtroad), (kennington,warrenstreet), (kennington,euston), (embankment,kennington), (embankment,tottenhamcourtroad), (embankment,warrenstreet), (embankment,euston), (tottenhamcourtroad,kennington), (tottenhamcourtroad,embankment), (tottenhamcourtroad,warrenstreet), (tottenhamcourtroad,euston), (warrenstreet,kennington), (warrenstreet,embankment), (warrenstreet,tottenhamcourtroad), (warrenstreet,euston), (euston,kennington), (euston,embankment), (euston,tottenhamcourtroad), (euston,warrenstreet)]

Which I hope gives you a good idea of how powerful findall is.

Jim Ashworth
  • 765
  • 6
  • 17