1

スキームに関する簡単な演習を1つ手伝ってください。

リスト内の各レベルのアトムの数を返す関数を記述します。例えば:

(a(b(c(de(f)k 1 5)e)))–>((1 1)(2 1)(3 2)(4 5)(5 1))

私の解決策:

(define (atom? x)
  (and (not (pair? x)) (not (null? x))))
(define (count L)
  (cond ((null? L) 0)
        ((pair? (car L))
         (count (cdr L)))
        (else
         (+ 1 (count (cdr L))))))
(define (fun L level)
  (cons 
   (list level (count L))
   (ololo L level)))
(define (ololo L level)
  (if (null? L)
      '()
      (if (atom? (car L))
          (ololo (cdr L) level)            
          (fun (car L) (+ level 1)))))
(fun '(a (b (c (d e (f) k 1 5) e))) 1)

正常に動作しますが、このリストに正しく答えないでください。

(a (b (c (d e (f) (k) 1 5) e)))

は:

((1 1) (2 1) (3 2) (4 4) (5 1))

ただし、1つのレベルで「f」と「k」を想定しているため、答えは次のようになります。

((1 1) (2 1) (3 2) (4 4) (5 2))

コードを正しく機能させるには、どのように編集すればよいですか?


UPD(29.10.12):私の最終的な解決策:

(define A '(a (b (c (d e (f) k 1 5) e))))

(define (atom? x)
  (and (not (pair? x)) (not (null? x))))

(define (unite L res)
  (if (null? L) (reverse res)
      (unite (cdr L) (cons (car L) res))))

(define (count-atoms L answ)
  (cond ((null? L) answ)
        ((pair? (car L))
         (count-atoms (cdr L) answ))
        (else
         (count-atoms (cdr L) (+ answ 1)))))

(define (del-atoms L answ)   
  (cond ((null? L) answ)
        ((list? (car L))
         (begin
         (del-atoms (cdr L) (unite (car L) answ))))
        (else
         (del-atoms (cdr L) answ))))

(define (count L)
(define (countme L level answ)
  (if (null? L)  (reverse answ)
      (countme (del-atoms L '()) (+ level 1) (cons (cons level (cons (count-atoms L 0) '())) answ))))
  (countme L 1 '()))

(count A)

これについてあなたは何を言うことができますか?

4

2 に答える 2

2

これを実行すると何が得られるか知っていますか?

(fun '(a (b (c (d e (f) k 1 5) e)) (a (b (c)))) 1)

あなたはこれを手に入れます:

((1 1) (2 1) (3 2) (4 5) (5 1))

右側に追加した余分なネストされた構造はすべて無視されています。これが理由です...

関数の各再帰は2つのことを行います。

  1. 現在の「レベル」ですべての原子を数える
  2. ペアであるs式が見つかるまでレベルを下げます(まあ、アトムではありません)

ネストされたペアが見つかると、それを呼び出します。等々

最初のネストされたペアから楽しみが戻ったとき、 oLoLoで何が起こりますか?なんで帰ってくる!別のものを見つけるためにリストを下に移動し続けることはありません。

関数は、どのレベルでも最初のリスト以上のものを見つけることはありません。もしそうなら、そのレベルの最初のリストから2番目のリストにカウントを追加するにはどうしますか?複数のネストされたリストを含むリストを完全に繰り返す方法と、各レベルで情報を保持する方法について慎重に検討する必要があります。それを行うには複数の方法がありますが、まだそれらのいずれにもヒットしていません。

于 2012-10-09T14:55:47.697 に答える
0

実装によっては、ここで使用するライブラリを他の方法でインポートする必要がある場合があることに注意してください。インポートする方法や、使用する関数の正確な名前を見つけるのは難しいかもしれません。filter代わりにそれを持っている人もいreduce-leftます。require-extensionGuile固有である場合とそうでない場合がありますが、私にはよくわかりません。

(require-extension (srfi 1))
(define (count-atoms source-list)
  (define (%atom? x) (not (or (pair? x) (null? x))))
  (define (%count-atoms source-list level)
    (if (not (null? source-list))
        (cons (list level (count %atom? source-list))
                (%count-atoms (reduce append '()
                       (filter-map
                        (lambda (x) (if (%atom? x) '() x))
                        source-list)) (1+ level))) '()))
  (%count-atoms source-list 1))

そしてもちろん、前に述べたように、これはハッシュテーブルを使用して行うのが最善です。リストを使ってそれを行うと、教訓的な効果が得られる可能性があります。しかし、私はあなたが本質的に悪いコードを書くようにする教訓的な効果に非常に強い反対を持っています。

于 2012-10-09T14:56:27.420 に答える