この答えは、一連のです@ rnsoのコードの翻訳で、0123の代わりに再帰ヘルパー関数を使うように修正されました。再帰的ヘルパーのこの種の略記については
#lang racket
(define (cpermit sl)
;; n starts at (length sl) and goes towards zero
;; sl starts at sl
;; outl starts at '()
(define (loop n sl outl)
(cond [(zero? n) outl]
[else
(loop (sub1 n) ; the new n
(append (rest sl) (list (first sl))) ; the new sl
(cons sl outl))])) ; the new outl
(loop (length sl) sl '()))
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
、あなたはlet
という名前を使用することができます。これは、最初の値を上に持ち上げて理解しやすくします。 @rnsoする
#lang racket
(define (cpermit sl)
(let loop ([n (length sl)] ; goes towards zero
[sl sl]
[outl '()])
(cond [(zero? n) outl]
[else
(loop (sub1 n) ; the new n
(append (rest sl) (list (first sl))) ; the new sl
(cons sl outl))]))) ; the new outl
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
、あなたは「可変変数」と同じ目的を果たすようn
、sl
、およびoutl
と考えることができますが、これは本当に私は私のようにloop
を定義したとき前に書いたのと同じコードです再帰ヘルパー関数。
上記のパターンは、Scheme/Racketコードのアキュムレータで非常に一般的です。 (cond [(zero? n) ....] [else (loop (sub1 n) ....)])
は、このようなループが必要なたびに書き出すのに少し面倒です。その代わりに、for/fold
に2つのアキュムレータを使用することができます。
#lang racket
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (append (rest sl) (list (first sl))) ; the new sl
(cons sl outl)))) ; the new outl
outl)
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
あなたが外リストが最後
(list 1 2 3 4)
、持っていることに気づいたかもしれません
(list 2 3 4 1)
最後から2番目のなど、私たちはcons
とそれにプリ保留でバックツーフロントリストを構築しているためです。これを修正するには、最後にそれを元に戻すことができます。
#lang racket
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (append (rest sl) (list (first sl))) ; the new sl
(cons sl outl)))) ; the new outl
(reverse outl))
> (cpermit (list 1 2 3 4))
(list (list 1 2 3 4) (list 2 3 4 1) (list 3 4 1 2) (list 4 1 2 3))
そして最後には、(append (rest sl) (list (first sl)))
は、独自のヘルパー関数であることを値することは明確な目的を持っているので:一度周りのリストを回転させます。
#lang racket
;; rotate-once : (Listof A) -> (Listof A)
;; rotates a list once around, sending the first element to the back
(define (rotate-once lst)
(append (rest lst) (list (first lst))))
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (rotate-once sl) ; the new sl
(cons sl outl)))) ; the new outl
(reverse outl))
> (cpermit (list 1 2 3 4))
(list (list 1 2 3 4) (list 2 3 4 1) (list 3 4 1 2) (list 4 1 2 3))
ここでの問題は、あなたが実際に再配置しますlst' 'に何かをしないことですその要素。 'cpermitAux'を呼び出すだけではなく)実際に使用される場所は'(cons lst '()) 'です。単に' lst'をそのまま使用します。再帰呼び出しは 'lst'を変更せずに渡すだけなので、' replicate'関数を実装するだけです。 –
Thx!私は回転機能を追加し、今それは動作します。 – Gaulthier