2016-02-15 24 views
3

我很難學會在計劃中編程。我的教授說我一直陷入程序思維的陷阱。我知道他是對的。我想學習如何做到這一點,然而,閱讀書對我來說變得不直觀,因爲這些應該是簡單的項目,不應該需要大量的閱讀和研究。如果我知道如何跟蹤輸出,我該如何開始創建我的功能? (Scheme)

概念上,我明白我的跟蹤函數應該是什麼樣子。 (雖然我可能是錯的) 在這裏,我正在研究一個名爲ndelete的程序,它接收一個列表並返回刪除每個第n個元素的列表。

下面我追溯了我認爲我的功能應該是什麼樣子。

ndelete('(a b c d e) 2) 
(a b c d e) 
> (b c d e) 
> > (c d e) 
> > > (d e) 
> > > > (e) 
> > > > > () 
< < < < < () ; return null 
< < < < (e) ; return e 1 
< < < (e) ; return 'd 2 removed 'd, 
< < (c e); return 'c 3 
< (c e) ; return 'b 4 removed'b 
(a c e) ; return 'a 5 

我覺得我應該知道這件事很容易,而且很令人沮喪。也許,有人可以指引我走向正確的方向,或向我展示如何利用我理解的概念。

這是我的企圖代碼。我有點隨意地用一些我認爲可以從我的教授的例子中使用的示例代碼組合在一起。

(define x '(1 2 3 4 5 6 7 8 9 10)) 

(define ndelete(lambda (alist n) 
       (if '() 
        (car alist) 
        (ndelete (cdr alist) 
           (- n 1)) 
        ))) 

(ndelete x 10) 
+2

你不能只用2個變量。您需要第三個變量來保持元素的數量,同時保留跳躍計數。下面是一個示例解決方案:http://stackoverflow.com/a/35366463/13 –

回答

2

它是一種常見的做法,試圖從一個例子來概括,提供:

  1. 你例子是不是太限制。你想確保涵蓋所有的功能案例。跟蹤對此很有幫助,因爲不同的情況通常發生在遞歸函數的不同深度。另外,您可能需要嘗試多個示例來信任您的解決方案。

  2. 您確信軌跡表示實際可能的執行,並且不只是嚴重製造(例如跳過步驟或突然返回不同的結果)。你必須記住,痕跡可能形成不好。你最終會仔細檢查它是否屬實,並將你的功能與你的例子對照。

不要試圖一下子寫的一切,從你所看到的,可以推斷出構建功能一步一步的。我相信大多數經驗豐富的函數程序員仍然會執行下面的步驟,但也許只能在他們的腦海中(隨着時間的推移,模​​式將開始出現)。

在這裏,你知道給你一個清單和一個數字:你叫他們lstn,因爲這是其他人在計劃中的做法。你也知道該函數應該返回一個列表。

(a b c d e) 
> (b c d e) 
... 
< (c e) 
(a c e) 
  • 從頂部第二行告訴你,你應該遞歸調用函數與(cdr lst),爲列表參數。
  • 最後一行顯示您必須在結果值之上缺點(car lst)

你可以寫第一稿:

(define ndelete 
    (lambda (lst n) 
    (cons (car lst) (ndelete (cdr lst) n)))) 

但這是不夠的,因爲你的函數不解釋跟蹤的其他部分,像這樣:

> > > > > () 
< < < < < () 

顯然有應該是空列表的基本情況。 我們更新功能:

(define ndelete 
    (lambda (lst n) 
    (if (null? lst) 
     '() 
     (cons (car lst) (ndelete (cdr lst) n))))) 

這裏是另一個矛盾:

> > > (d e) 
> > > > (e) 
.... 
< < < < (e) 
< < < (e) 

你並不總是cons。實際上,只有在跟蹤中偶數爲<時纔會這樣做,這在調用函數時對應於偶數號>。你明白2應該被推廣到n,你必須添加一個計數器。

您可能想重用現有的n,但對於初稿,添加另一個參數。如果真的可以從n中派生出來,您將有機會稍後重寫。 計數器必須從一個等級傳遞(並修改)到另一個等級。我不會在這裏複製粘貼,但結果是Chris Jester-Young's answer。他使用本地函數,但這是可以在之後完成的那種重構。

+1

謝謝,這真的是內容豐富 – tisaconundrum

相關問題