1

数値の約数を見つける簡単な手順を作成しました (数値自体は含まれません)。それらを印刷する方法を理解しましたが、この関数が各除数を含むリストを返すようにしたいと思います。

(define (divisors n)

  (do ((i 1 (+ i 1)))    
    ((> i (floor (/ n 2))))
    (cond 
      ((= (modulo n i) 0)
       (printf "~a " i)))))

私のアイデアは、ローカル リストを作成し、printf 式がある場所に要素を追加してから、関数がそのリストを返すようにすることです。どうすればそれを行うことができますか?私はSchemeとLisp全般に不慣れです。

4

2 に答える 2

1

必ず使用する必要がありますdoか? ここに方法があります:

(define (divisors n)
  (do ((i 1 (add1 i))
       (acc '() (if (zero? (modulo n i)) (cons i acc) acc)))
    ((> i (floor (/ n 2)))
     (reverse acc))))

しかし、名前let付きの出力リストを作成すると理解しやすいと思います:

(define (divisors n)
  (let loop ((i 1))
    (cond ((> i (floor (/ n 2))) '())
          ((zero? (modulo n i))
           (cons i (loop (add1 i))))
          (else (loop (add1 i))))))

または、たまたま Racket を使用している場合は、次for/foldのように使用できます。

(define (divisors n)
  (reverse
   (for/fold ([acc '()])
     ([i (in-range 1 (add1 (floor (/ n 2))))])
     (if (zero? (modulo n i))
         (cons i acc)
         acc))))

上記の解決策はすべて関数型プログラミング スタイルで書かれていることに注意してください。これは、Scheme でプログラミングする慣用的な方法です - ミューテーション操作を使用しません。C のような言語でこの問題を解決する方法と同様に、手続き型のソリューション (@GoZoner の回答を参照) を作成することもできますが、それは慣用的ではありません。

于 2013-10-18T22:13:56.543 に答える
1

l印刷する代わりに、ローカル変数を作成して拡張するだけです。終わったら返却。このような:

(define (divisors n)
  (let ((l '()))
    (do ((i 1 (+ i 1)))    
        ((> i (floor (/ n 2))))
      (cond ((= (modulo n i) 0)
             (set! l (cons i l))))
    l))

それぞれiが の前に「consed」されているためl、 の順序はl高いものから低いものになることに注意してください。(reverse l)下位から上位への順序付けが必要な場合は、戻り値として使用します。

于 2013-10-19T01:16:27.453 に答える