簡體   English   中英

Prolog - 遞歸地將數字附加到列表中

[英]Prolog - Recursively append numbers to a list

我剛剛開始學習 Prolog,並且在遞歸概念上遇到了麻煩。 現在,僅出於練習的目的,我正在嘗試編寫一個程序,將 10 個數字附加到一個列表中,然后打印出該列表。

這個程序的自我強加規則是必須在主謂詞中“聲明”列表(我不確定這是否是 Prolog 的正確詞),它調用另一個謂詞將數字附加到列表中。

到目前為止,這是我所擁有的,我知道它不會起作用,因為我試圖在addToList謂詞的末尾重新定義List ,這在語言中是不允許的。

% Entry point that declares a list (`List`) to store the 10 numbers
printList(List) :-
    addToList(0, List),
    writeln(List).

% Base case - once we hit 11 we can stop adding numbers to the list
addToList(11, _).

% First case - this predicate makes adding the first number easier for me...
addToList(0, List) :-
    append([], [0], NewList),
    addToList(1, NewList),
    append([],  NewList, List). % This is valid, but List will just be [0] I think..

% Cases 1-10
addToList(Value, List) :-
    append(List, [Value], NewList),
    NextVal is Value+1,
    addToList(NextVal, NewList),
    append([], NewList, List). % This is INVALID since List is already defined

該計划將開始於:

printList(List).

有沒有一種簡單的方法可以更改我編寫的損壞程序以使其正常工作? 我對如何獲取存儲在List的數字感到非常迷茫。

你在程序上思考,在序言中你不能改變變量。 您正在嘗試自己構建列表。 在 prolog 樣式中,您嘗試聲明所需列表的約束。 如果nlist/2是一個給出 N 個數字列表的謂詞,那么它的屬性究竟是什么? nlist(0, []). 如果nlist(N, Xs)nlist(N+1, [N+1 | Xs]) 因此,您只需編寫這些並讓 prolog 負責構建。

nlist(0, []).
nlist(N, [N | Xs]) :-
    N>0, N1 is N-1,
    nlist(N1, Xs).

如果您對遞歸調用的發生方式感到困惑,請嘗試使用trace/0trace/1 您可以在以下跟蹤中看到調用是如何完成的。 您可以通過調用trace(nlist)獲得此信息。

?- nlist(3, X).
 T Call: nlist(3, _78)
 T Call: nlist(2, _902)
 T Call: nlist(1, _1464)
 T Call: nlist(0, _2026)
 T Exit: nlist(0, [])
 T Exit: nlist(1, [1])
 T Exit: nlist(2, [2, 1])
 T Exit: nlist(3, [3, 2, 1])
X = [3, 2, 1]

更程序化風格的代碼如下

addToList(11, A, A).

% Cases 1-10
addToList(Value, List, NewList) :-
    Value < 11,  append(List, [Value], Temp),
    NextVal is Value+1,
    addToList(NextVal, Temp, NewList).

這給出了中間參數是累加器。 當您達到 11 時,累加器就是答案。

?- addToList(1, [], X).
X = [1, 2, 3, 4, 5, 6, 7, 8, 9|...] 

?- addToList(5, [], X).
X = [5, 6, 7, 8, 9, 10] 

查看示例跟蹤以及它們在nlistaddToList中的nlist 嘗試找出差異以及為什么會發生這些差異。

?- addToList(7, [], X).
 T Call: addToList(7, [], _33565254)
 T Call: addToList(8, [7], _33565254)
 T Call: addToList(9, [7, 8], _33565254)
 T Call: addToList(10, [7, 8, 9], _33565254)
 T Call: addToList(11, [7, 8, 9, 10], _33565254)
 T Exit: addToList(11, [7, 8, 9, 10], [7, 8, 9, 10])
 T Exit: addToList(10, [7, 8, 9], [7, 8, 9, 10])
 T Exit: addToList(9, [7, 8], [7, 8, 9, 10])
 T Exit: addToList(8, [7], [7, 8, 9, 10])
 T Exit: addToList(7, [], [7, 8, 9, 10])
X = [7, 8, 9, 10] 

這是我的解決方案:

printSeries(_,[],0):-!.
printSeries(S,[S|T],C):-
    S1 is S+1,
    C1 is C-1,
    printSeries(S1,T,C1).

?- printSeries(7,L,5).
L = [7, 8, 9, 10, 11]

謂詞可用於使用起始編號以及想要增加它的次數來打印任何系列。 一個非常簡單的方法是使用計數器。 第一個謂詞是說無論起始編號如何,也不管列表中的內容如何,​​如果計數器達到 0,程序應該停止(意味着停止)。 第二個謂詞我們有起始編號,以及我們告訴它必須以起始編號開始列表的列表,最后是計數器。 接下來,我們將起始數字加 1。將計數器減 1。然后通過為謂詞提供新值來重做所有事情。

?-printSeries(1,L,10).
L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM