0

リスト内の偶数番号の要素を返す関数を作成しようとしています。

例えば:

(evens '(a b c d)) 

戻るべき

(b d)

以下のコードは、要素数が奇数のリストでも動作するように見えますが、要素数が偶数のリストを指定すると正しくありません。

例えば:

(evens '(a b c d e))

戻ります

(b d)

しかし:

(evens '(a b c d))

戻ります

(a c)

何かご意見は?

私のコードを次のように変更しました:

(DEFINE (evens lis)
(cond
    ((null? lis) '())   
    (else (cons (cadr lis) (evens (cdr lis))))
    ))

safe-car に渡されたオブジェクトがペアではないというエラーが表示されますか?

4

4 に答える 4

0

この同じ質問が、過去数日間にわたって何聞かれました。今回は、まっすぐに設定するために直接答えます。

(define (evens lst)
  (if (or (null? lst)             ; if the list is empty 
          (null? (cdr lst)))      ; or the list has a single element
      '()                         ; then return the empty list
      (cons (cadr lst)            ; otherwise `cons` the second element
            (evens (cddr lst))))) ; and recursively advance two elements

そして、最初にエラーチェックを行う方法は次のとおりです。

(define (find-evens lst)
  (if (list? lst)
      (evens lst)
      (error "USAGE: (find-evens [LIST])")))
于 2012-11-14T11:11:38.197 に答える
0

あなたのコードにはチェック漏れがほとんどなく、ロジックが少し間違っています。

(define (evens lis)
(cond
    ((null? lis) '())   
    ((eq? (cdr lis) '()) '()) ;missing condition
    (else (cons (cadr lis) (evens (cddr lis)))))) ; it is cddr not cdr
于 2012-11-14T09:47:05.590 に答える
0

問題は、リストに偶数の要素がある場合、moduloブランチが一致し、リストの から始まるconsことcarです...したがって、この例では、 などを取得しますa

しかし、もっと重要なことは、この関数に を使用する必要がないことですlength... 使用すべきではありません。lengthevens

提案: プログラムは、各再帰ステップで「奇数」または「偶数」の場所にあるかどうかを「記憶」する必要があります...どうすればこれを行うことができますか (いくつかの方法があります)?

于 2012-11-14T05:49:12.567 に答える
0

機能するコードが提供されるだけでなく、実際に何かを学ぶことができることを願って、コメント付きの例を使用して質問に答えます。実際、あなたがスキームに慣れていないと仮定すると、いくつかのコードを見ることはより啓発的かもしれません。

元の定義は次のようになりました。

(define (evens lis)
  (cond (;; Check: Recursion stop condition
         (null? lis)
         '())
        (;; Wrong: Calling length at each step => O(n^2)
         ;; Wrong: Assuming even element if list has even number of elements
         (= (modulo (length lis) 2) 0) 
         ;; Wrong: Recursing with the rest of the list, you'll get odds
         (cons (car lis) (evens (cdr lis)))) 
        (else
         ;; Wrong: Recursing with the rest of the list with cdr, you'll get odds
         (evens (cdr lis)))))

その後、質問を編集して、次のように更新しました。

(define (evens lis)
  (cond (;; Check: Recursion stop condition
         (null? lis)
         '())   
        (else
         ;; Check: Building list with second element
         ;; Wrong: If lis only has 1 element,
         ;;        (cdr lis) is null and (car (cdr list)) is an error.
         (cons (cadr lis)
               ;; Wrong: Recursing with cdr, you'll get odds
               (evens (cdr lis))))))

解決策は、リストに少なくとも 2 番目の要素があるかどうかを確認することです。

(define (evens lis)
  (cond (;; Check: Recursion stop condition 1
         (null? lis)
         '())
        (;; Check: Recursion stop condition 2: list of length = 1
         (null? (cdr lis))
         '())
        (else
         ;; Check: Building list with second element
         ;; The previous cond clauses have already sorted out
         ;; that lis and (cdr lis) are not null.
         (cons (cadr lis)
               ;; Check: Recurse "the rest of the rest" of lis with cddr
               (evens (cddr lis)))))

演習:ifとを使用しorて、このソリューションを単純化して 2 つの分岐のみを持たせます。

于 2012-11-14T11:16:11.277 に答える