sicp-ex-2.17



<< Previous exercises (2.14-2.15-2.16) | Index | Next exercise (2.18) >>


  
 ;; ex-2.17 
  
 (define (last-pair items) 
   (let ((rest (cdr items))) 
     (if (null? rest) 
         items 
         (last-pair rest)))) 
  
 ;; Testing 
 (last-pair (list 23 72 149 34)) ; (34) 

jz

  
 ;; ex 2.17 
 (define (last-pair items) 
   (let ((rest (cdr items))) 
     (if (null? rest) 
         items 
         (last-pair rest)))) 
  
 ;; Test: 
 (last-pair (list 1 2 3 4)) 
  

asb

 solution which doesn't fail for '() 
  
 (define (last-pair items) 
   (define (iter items result) 
     (if (null? items) 
         result 
         (iter (cdr items) items))) 
   (iter items items)) 

A lot of people here concern such a conner case that the list is empty, but the exercise dictates conversely:

> Define a procedure last-pair that returns the list that contains only the last element of a given (**nonempty**) list:

Speaking of it, I cannot imagine what the last element is while the list is empty exactly. It is contradictory that an empty list contains an empty list as its latest element inside.



EcsCodes

 A simple but ingenious code 
  
 (define(lastPair L) 
  (if(=(length L)1) (car L) 
     (lastPair (cdr L)))) 
 same as EcsCodes, but passes test for empty list 
  
 (define (last-pair items) 
  (if (< (length items) 2) items 
   (last-pair (cdr items)))) 
 ;; ex 2.17 
 (define(lastPair L)  
   (define (ref lst x) 
   (if(= x 0) (car lst) 
      (ref (cdr lst) (- x 1)))) 
 (if(=(length L)1) (car L)  
      (cons (ref  L (- (length_ L) 2)) 
            (cons (ref L (- (length_ L) 1)) '()) 
            ) 
      ) 
   ) 
  


I think using (length L) repeatadly is not a good idea (unless your length is O(1), but the implementation in the book is O(n)) because it makes lastPair do n! length-iter on the list, its rest, the rest of the rest... where n is the size of the items list.



AMS

The answer was meant to return the last item of a list as a list. So you must modify the return value to return a list.

 (define (last-pair l) 
   (cond ((null? l) l) 
         ((null? (cdr l)) (list (car l))) 
         (else (last-pair (cdr l))))) 
 ;; test 
 (last-pair (list 23 72 149 34)) ;;= (34) 
 (last-pair '()) ;;= () 

Without error checking though.

 (define (last-pair s) 
   (if (null? (cdr (cdr s))) 
     (cdr s) 
     (last-pair (cdr s)))) 


Daniel-Amariei

Regarding the first solution. We need to return a list, not a particular element. 1 != '(1)

 ;; returns the list that contains the last element  
 ;; of a given non-empty list 
  
  
 (define (last-pair L) 
   (if (null? (cdr L)) 
       L 
       (last-pair (cdr L)))) 
  
  
 (last-pair (list 1))  ;; '(1) 
 (last-pair (list 1 2))  ;; '(2) 
 (last-pair (list 1 2 3))  ;; '(3) 
 (last-pair (list 1 2 3 4))  ;; '(4) 

Anonymous coward

Does the solution have to be recursive?

 (define (last-pair inlist) 
       (list (list-ref inlist (- (length inlist) 1)))) 

anon

racket with contracts

  
 (define/contract (last-pair items) 
   (->i ([items list?]) 
        #:pre (items) (not (null? items)) 
        [_ list?]) 
   (if (null? (cdr items)) 
       items 
       (last-pair (cdr items)))) 
  
  
 (check-equal? (last-pair (list 23 72 149 34)) '(34)) 
  
 (last-pair '()) ; contract violation 

bmm

  
 ;; ex 2.17 
  
 (define nil '()) 
  
 ;; procedure for length of list 
  
 (define length (lambda (list) 
               (if (null? list) 0 
                   (+ 1 (length (cdr list)))))) 
  
 ;; list-ref 
 (define list-ref (lambda (list n) 
               (if (= n 0) (car list) 
                   (list-ref (cdr list) (- n 1))))) 
  
 ;; last-pair procedure 
 (define last-pair (lambda (list) 
                     (if (null? list) nil 
                         (let ((s (- (length list) 1))) 
                           (cons (list-ref list s) nil))))) 
  
  
 ;; Testing 
 (last-pair (list 1 2 3 4 5 6 7 8 9)) ;; '(9)