(define min
(lambda (l m c)
(cond ((null? l) (print m))
(else ((c (car l))
if((< c m) (m c))
min((cdr l) m c))))))
末尾再帰法を使いたいのですが、うまくいきません。私はSchemeに非常に慣れていないので、助けていただければ幸いです。ありがとうございました!
(define min
(lambda (l m c)
(cond ((null? l) (print m))
(else ((c (car l))
if((< c m) (m c))
min((cdr l) m c))))))
末尾再帰法を使いたいのですが、うまくいきません。私はSchemeに非常に慣れていないので、助けていただければ幸いです。ありがとうございました!
これは宿題のように見えます。自分で解決できるように、いくつかの指針を示します。空欄を埋める:
(define (mymin lst minval)
(cond ((null? lst) ; If the list is empty
???) ; return the minimum value.
((< ??? minval) ; If current element < minimum value
(mymin ??? ???)) ; advance recursion, current element is new minimum.
(else ; If current element >= minimum value
(mymin ??? ???)))) ; advance recursion, keep the same minimum.
上記のコードでは、 と呼ばれる 2 つのパラメーターの末尾再帰プロシージャを実装してmymin
います ( name は使用しないでくださいmin
。これは組み込みプロシージャです)。最初のパラメーターはトラバースするリストです。2 番目のパラメーターは、これまでに見つかった最小値を格納し、再帰が終了すると、答えが保持されます。
次のように呼び出します。最初の呼び出しでは、2 番目の引数に非常に大きな数値を渡す必要があるため、他のすべての数値は小さいことに注意してください。
(mymin '(1 2 3 4 0 5) +inf.0)
> 0
Oscar のバージョンは機能しますが、文体についていくつか問題があります (これは、Oscar を批判するものではありません。Oscar は、ソリューションをわかりやすくするためにシンプルにしています)。これらの線に沿って動作するようになったら、いくつかの変更を加えることができるかどうかを確認してください。
スプリアスパラメータなし
あなたには 3 つのパラメーターがあり、Oscar には 2 つのパラメーターがありますが、これは 1 つの入力 (リスト) を取るリストです。間違った余分なシード パラメータを指定すると、失敗します。これを修正する 1 つの方法は、メイン関数内で再帰することです。それはこのように見えるかもしれません
(define (mymin lst)
(let ((minval ???))
(define (findmin lst testval)
(cond
(????)
(????)
(????))
(findmin lst minval)))
それがどのように機能するか分かりますか?Oscar が行ったように、minval を inf.0 に初期化することも、数値以外の特別な値に初期化することもできます (いくつかの適切な選択肢があり、一方が他方より優れています)。
しかし、本当に賢い人なら、毎回 2 つの値を渡す必要がないことに気付くでしょう。内部関数や初期化を必要とせずに、各再帰に 1 つの単純なオブジェクトを渡すことができます。開始時に必要なすべてのデータがあるのに、なぜ何かを無限値で初期化するのでしょうか?
これがどのように見えるかの手がかりです(オスカーのバージョンとほとんど同じように始まります):
(define (mymin lst)
(cond
((null? lst) ???)
((?????) (car lst))
(else (mymin (??????????????????????? lst)))))
???s の最後の行では、いくつかのことが行われています ;)
ただし、他の方法で動作させることができない場合を除き、動作するバージョンを入手してから、これらの改善を試みてください。それを機能させてから改善してください - あなたは二度学びます;)
途中で思うところもある...