An airline wants to maintain information about the routes that it
flies.  At a minimum, for each city that it services, the airline
wants to store the names of other cities that it operates flights to.
What should we use a data representation for this scenario?

  A city is a symbol.

  The info for a city is a structure
    (make-city-info c n)
  where c is a city and n is (listof symbol)

  (define-struct city-info (name fly-to))

  A route-map is (listof city-info)

  (define routes
     (list (make-city-info 'Houston (list 'Dallas 'NewOrleans))
           (make-city-info 'Dallas (list 'LittleRock Memphis))
           (make-city-info 'NewOrleans (list 'Memphis))
           (make-city-info 'Memphis (list 'Nashville))))
	   
We want to write a program that consumes a route map and returns a
sequence of cities (though perhaps not the shortest sequence) by which 
we can fly from a starting city to an ending city.  If no such
sequence exists, the program should return false.

;; find-flights : city city route-map -> (listof city) or false
;; creates a path of flights from start to finish
(define (find-flights start finish rm) ...)

Here are some examples from our routes defined above:

  (find-flights 'Houston 'Houston)
= (list 'Houston)

  (find-flights 'Houston 'Dallas)
= (list 'Houston 'Dallas)

  (find-flights 'Dallas 'Nashville) 
= (list 'Dallas 'LittleRock 'Memphis 'Nashville)

How might we write this program?  If there is a direct flight from the 
starting city to the destination city, the route is easy.  What if
there is no direct flight?  We know which cities we can fly to from
the starting city.  We could then look for a flight to the destination 
city from any of these cities, and build a sequence of flights from
there. 

Based on this description, do we need structural or generative
recursion to write find-flights?  Generative.  If there is no direct
flight between our two cities, we generate new problems based not on
the structure of the route map, but on the understanding of how to
look for a flight path.

Since the program needs generative recursion, we must answer the four
questions that make up the template for generative recursion:

1. What is the trivially solvable case?

   When the starting and destination cities are the same.

2. What's the solution in the trivial case?

   A list containing the starting city.

3. How do we generate new problems?

   Find all cities that we can fly to from the starting city and look
   for a route from one of these cities to the destination.

4. How do we combine the solutions?

   If we found at least one route, we keep one and add the starting
   city to that route.  Otherwise we return false.

We're now ready to write the program.

;; find-flights : city city route-map -> (listof city) or false
;; creates a path of flights from start to finish
(define (find-flights start finish rm)
  (cond [(symbol=? start finish) (list start)]
	[else (local [(define possible-route
			(find-flights/list (direct-cities start rm)
					   finish rm))]
   	        (cond [(boolean? possible-route) false]
		      [else (cons start possible-route)]))]))

;; direct-cities : city route-map -> (listof city)
;; return list of all cities in route map with direct flights from given city
(define (direct-cities from-city rm)
  (local [(define from-city-info
	    (filter (lambda (c) (symbol=? (city-info-name c) from-city))
		    rm))]
    (cond [(empty? from-city-info) empty]
	  [else (city-info-fly-to (first from-city-info))])))
	  
;; find-flights/list :
;;        (listof city) city route-map -> (listof city) or false
;; finds a flight route from some city in the input list to the destination,
;;   or returns false if no such route exists
(define (find-flights/list loc finish rm)
  (cond [(empty? loc) false]
	[else (local [(define possible-route
			(find-flights (first loc) finish rm))]
		(cond [(boolean? possible-route)
		       (find-flights/list (rest loc) finish rm)]
		      [else possible-route]))]))