2010-10-31 19 views
5

Kuyruk yinelemesi kullanarak C (n, k) bulmak için bir fonksiyon programlamak istiyorum ve yardımınızı çok takdir ediyorum.LISP'de Kuyruk Saptama Kullanarak Binom Katsayısı

bu ulaştık:

(defun tail-recursive-binomial (n k) 
    (cond ((or (< n k) (< k 0)) NIL) 
     ((or (= k 0) (= n k)) 1) 
     (T (* (tail-recursive-binomial (- n 1) (- k 1)) (/ n k))))) 

the following property of the binomial coefficients kullanma.

Ama sonuncusu ürün olduğu için, her örnek tarafından yürütülen son komut olarak nasıl yineleme çağrısının nasıl yapılacağını bilmiyorum. Tek bir yol olduğunu düşündüğüm yardımcı bir işlev kullanarak denedim ama bir çözüm bulamadım.

cevap

7

starblue anlaşılacağı gibi, özyinelemeli yardımcı fonksiyon kullanımı:

(defun binom (n k &optional (acc 1)) 
    (cond ((or (< n k) (< k 0)) NIL) 
     ((or (= k 0) (= n k)) acc) 
     (T (binom (- n 1) (- k 1) (* acc (/ n k)))))) 
: 1 bir varsayılan değer (özyinelemeli temel durum) ile ana fonksiyonu, bir optional akümülatör argüman vermek

(defun binom (n k) 
    (if (or (< n k) (< k 0)) 
    NIL ; there are better ways to handle errors in Lisp 
    (binom-r n k 1))) 

;; acc is an accumulator variable 
(defun binom-r (n k acc) 
    (if (or (= k 0) (= n k)) 
    acc 
    (binom-r (- n 1) (- k 1) (* acc (/ n k))))) 

ya da

İkinci seçenek, her özyinelemeli çağrıda hata durumu kontrol edildiği için biraz daha az verimlidir.

+0

Çok teşekkürler. Birincisine benzeyen bir çözüm arıyordum (yaptığım ya da gördüğüm diğer işlevlere daha çok benziyordu), ama ikincisini, gerçekten çok zarif. – jesusiniesta

3

Hesaplamak ve sonucu iletmek için kullandığınız fazladan bir argümana sahip bir yardımcı işleve ihtiyacınız vardır.

+0

Bu benim ilk yaklaşımımdı, çünkü bu şekilde bir işlevsel işlevi kodluyordum, ama ben bunu bir tane almadım. Teşekkürler zaten – jesusiniesta