0

Following code from http://htdp.org/2003-09-26/Book/curriculum-Z-H-38.html#node_chap_30 does'nt seem to be working (I have added println statements for debugging)

(define (neighbor a-node sg)
  (println "in neighbor fn")
  (cond
    [(empty? sg) (error "neighbor: impossible")]
    [else (cond
        [(symbol=? (first (first sg)) a-node)
         (second (first sg))]
        [else (neighbor a-node (rest sg))])]))

(define (route-exists? orig dest sg)
  (println "in route-exits? fn")
  (cond
    [(symbol=? orig dest) true]
    [else (route-exists? (neighbor orig sg) dest sg)]))

I also tried the second version (I have added contains fn):

(define (contains item sl)
  (ormap (lambda (x) (equal? item x)) sl)  )

(define (route-exists2? orig dest sg)
  (local ((define (re-accu? orig dest sg accu-seen)
            (cond
              [(symbol=? orig dest) true]
              [(contains orig accu-seen) false]
              [else (re-accu? (neighbor orig sg) dest sg (cons orig accu-seen))]))) 
    (re-accu? orig dest sg empty)))

Following example from that page itself creates infinite loop:

(route-exists? 'C 'D '((A B) (B C) (C E) (D E) (E B) (F F)))  

Following produces #f even though solution is clearly possible:

(route-exists2? 'C 'D '((A B) (B C) (C E) (D E) (E B) (F F)))  

Following tests (lists are mine) produce errors here also even though solution is clearly possible:

(route-exists?
 'A 'C
 '('('A 'B) '('B 'C) '('A 'C) '('A 'D) '('B 'E) '('E 'F) '('B 'F) '('F 'G) ) 
 )

(route-exists2?
 'A 'C
 '('('A 'B) '('B 'C) '('A 'C) '('A 'D) '('B 'E) '('E 'F) '('B 'F) '('F 'G) ) 
 )

Where is the problem and how can this be solved?


Edit:

Even after choosing the new function and remove excess quotes, following does not work (even though there is a direct path between A and D):

(route-exists2?
 'A 'D
 '((A B) (B C) (A C) (A D) (B E) (E F) (B F) (F G) ) )

It outputs an error:

neighbor: impossible
soegaard
  • 30,661
  • 4
  • 57
  • 106
rnso
  • 23,686
  • 25
  • 112
  • 234

1 Answers1

3

For the first case:

Following example from that page itself creates infinite loop:

(route-exists? 'C 'D '((A B) (B C) (C E) (D E) (E B) (F F)))

In the page you linked, ten lines after the definition of the function, it is clearly said:

The hand-evaluation confirms that as the function recurs, it calls itself with the exact same arguments again and again. In other words, the evaluation never stops.

So, it is exactly the behaviour that you have observed.

For the second case:

Following produces #f even though solution is clearly possible:

(route-exists2? 'C 'D '((A B) (B C) (C E) (D E) (E B) (F F)))

Four lines after the definition of the first function, it is clearly said:

Take another look at figure 85. In this simple graph there is no route from C to D.

So, the function must return correctly #f, as it does, since there is no route from C to D (remember that the arcs are oriented, in fact, before the example, it is clearly said: “... each node has exactly one (one-directional) connection to another node”).

Finally, in your last two examples:

Following tests (lists are mine) produce errors here also even though solution is clearly possible:

(route-exists? 'A 'C '('('A 'B) '('B 'C) '('A 'C) '('A 'D) '('B 'E) '('E 'F) '('B 'F) '('F 'G) ) )

(route-exists2? 'A 'C '('('A 'B) '('B 'C) '('A 'C) '('A 'D) '('B 'E) '('E 'F) '('B 'F) '('F 'G) ) )

Your are quoting too much, so that you are giving to the function a data which is different from what is required.

Remember that 'X is an abbreviation for (quote X). This means that your last parameter is not a correct graph, since it is equal to:

((quote (quote A) (quote B)) (quote (quote B) (quote C)) ...)

and not to

((A B) (B C) ...)

Added

This is the answer to the last question:

Even after choosing the new function and remove excess quotes, following does not work (even though there is a direct path between A and D):

(route-exists2? 'A 'D '((A B) (B C) (A C) (A D) (B E) (E F) (B F) (F G) ) )

It outputs an error:

neighbor: impossible

In the page that you linked, in the first paragraph of section “A Problem with Generative Recursion", it is clearly said:

Here we study the slightly simpler version of the problem of simple graphs where each node has exactly one (one-directional) connection to another node.

Since your graph has more than one connection from a node (for instance A is connected to B, C, and D, etc.), in this case the program does not work.

You can see immediately the reason if you consider the function neighbor: it finds the first node connected to a certain node, without considering all the other nodes. So, for instance, from A the only neighbor returned is B, which is not connect directly or indirectly to D, and so the function route-exists2? replies (correctly, according to the specification) that there is no such route.

Alexis King
  • 43,109
  • 15
  • 131
  • 205
Renzo
  • 26,848
  • 5
  • 49
  • 61
  • Please see my edit. The second function is not finding a direct route. – rnso Sep 16 '16 at 00:17
  • Can the function be improved? – rnso Sep 16 '16 at 05:57
  • @mso, if you mean to apply it to general graphs (in which each node can be connected to several nodes), a possibility is to enlarge the definition of `neighbor` to produce *all* the neighbors of a node (this is simple), and then, inside the recursive branch of `re-accu?` use something like `ormap` to recur on all of them (until a path is found or they are exhausted). – Renzo Sep 16 '16 at 06:16
  • Will it same as your earlier answer (http://stackoverflow.com/questions/39071077/finding-path-between-2-points-in-racket)? If not, it will be great if you can add these lines of code to your very illustrative answer. – rnso Sep 16 '16 at 06:26
  • @mso, yes, exactly, the answer is that that you linked. That answer find also all the routes, not only if a route exists or not. – Renzo Sep 16 '16 at 07:14