Consider this data definition for a pipe:

;; a pipe is either:
;;  - 'faucet
;;  - (make-copper pipe)
;;  - (make-iron pipe)
;;  - (make-joint pipe pipe)

(define-struct copper (next))
(define-struct iron (next))
(define-struct joint (left right))

Pipes are terminated by faucets. The make-copper constructor builds a slightly bigger pipe by adding a copper length to an existing pipe. Similarly, make-iron adds an iron length to an existing pipe. The make-joint constructor combines two sections of pipe.

As any homeowner soon learns, plumbing is a black art. For example, if you have copper and iron piping right next to each other in the same hot-water line, the pipe will leak (the copper and iron expand and contract at different rates). Pipe joints, however, are specially designed to be able to connect to either copper or iron pipes safely (without causing any leaks).

To help homeowners everywhere, write a function that takes a description of a hot water pipe and determines if it would leak. Here are some example uses of that function:

(equal? (will-leak? 'faucet) false)
(equal? (will-leak? (make-copper 'faucet)) false)
(equal? (will-leak? (make-iron 'faucet)) false)
(equal? (will-leak? (make-copper (make-iron 'faucet))) true)
(equal? (will-leak? (make-iron (make-copper 'faucet))) true)
(equal? (will-leak? (make-iron (make-joint (make-copper 'faucet)
                                           (make-copper 'faucet))))
        false)
(equal? (will-leak? (make-joint (make-copper 'faucet)
                                (make-iron 'faucet))))
        false)

Solution

;; will-leak? : pipe -> boolean
(define (will-leak? pipe)
  (will-leak?/a pipe false))

;; will-leak?/a : pipe prev-section or false -> boolean
(define (will-leak?/a pipe prev-section)
  (cond
    [(symbol? pipe) false]
    [(copper? pipe)
     (cond
       [(iron? prev-section) true]
       [else (will-leak?/a (copper-next pipe) pipe)])]
    [(iron? pipe) 
     (cond
       [(copper? prev-section) true]
       [else (will-leak?/a (iron-next pipe) pipe)])]
    [(joint? pipe)
     (or (will-leak?/a (joint-left pipe) pipe)
         (will-leak?/a (joint-right pipe) pipe))]))