[英]Prolog Predicate Solution
我正在為即將到來的Prolog考試解決一些過去的考試問題。
這是問題:
(a)編寫一個謂詞insert(Xs, Y, Zs)
,該謂詞在Zs
是通過將Y
插入列表Xs
中獲得的列表時成立。 查詢,例如:
? - insert([1,2,3], 4, Zs).
應該成功四次,並給出以下答案:
Zs = [4, 1, 2, 3]
Zs = [1, 4, 2, 3]
Zs = [1, 2, 4, 3]
Zs = [1, 2, 3, 4].
我有點擔心,因為我不知道從哪里開始。 在我需要示例解決方案來練習考試的過程中,有人可以提供幫助嗎?
非常感謝您的幫助。
我們從更改此謂詞的可怕名稱開始:謂詞應描述什么成立 , 而不是做什么。 名稱應反映出這一點。 我建議使用list_with_element/3
,並鼓勵您嘗試尋找更好的名稱,最好是明確每個參數的含義。
然后,我們要做我們打算做的事情:描述使這種關系成立的情況。
例如:
list_with_element([], E, [E]).
list_with_element([L|Ls], E, [E,L|Ls]).
list_with_element([L|Ls0], E, [L|Ls]) :-
...
我留在填寫...
作為一個簡單練習。 說明子句頭為真所必需的條件!
編輯 :我想說更多有關上述模式。 以我的經驗,推論描述列表的謂詞的一種好方法(絕對是在開始時)是考慮以下兩種基本情況:
[]
,表示空列表 '.'(E, Es)
術語,也寫為[E|Es]
,其中E
是列表的第一個元素, Es
也是列表。 這遵循列表的歸納定義。
在這種特定情況下的缺點是,這種方法導致情況再次需要將情況(2)分為兩個子情況,並且以某種方式意外地需要三個子句來處理這兩個基本情況。 顯然,這與我們直覺地期望兩個子句就足夠相反。 的確確實如此,但是我們需要注意不要意外丟失解決方案。 在這種情況下,上面的前兩個子句都包含在以下事實中:
list_with_element(Ls, E, [E|Ls]).
每個有經驗的Prolog編碼器都將以這種方式編寫謂詞,或者僅在這種情況下直接使用select/3
。 這就是@lurker的感知和暗示,而@tas正確地表明了一個不同的子句(很容易意外地想到)並沒有完全包含我們要表達的所有情況。
因此,我仍然發現首先明確考慮空列表,確保正確設置大小寫,然后繼續處理更復雜的情況,然后查看是否可以更緊湊地編寫現有程序,要容易得多。 這也是我用於此示例代碼的方式,但是我沒有使其盡可能短。 請注意,對於單調代碼,有多余的事實是完全可以的!
請注意,是專門為沒有確定,只是通過更換前兩個條款:
list_with_element([L|Ls], E, [E|Ls]).
因為此子句不包含上述情況(1)。
我猜想這個問題可能正在尋找的一個答案遵循以下思路:
insert(List, Element, NewList) :-
append(Front, Back, List), % split list in two
append(Front, [Element|Back], NewList). % reassemble list
如果您希望聲明式閱讀:
NewList在List的前后之間具有Element。
仔細檢查是否在先前的問題或學習材料中出現了append/3
或具有相同語義的謂詞。
並請注意,如果我正確理解的話,這實際上與@mat的建議完全相同 。 有關詳細信息,請查閱append/3
的教科書定義。 甚至更好的是,查看append/3
的教科書定義, append/3
其修改為在“插入”時使用。
盡管參數的順序不同,但內置的謂詞select/3
可以執行相同的操作。
請記住,(如果定義正確)謂詞可以在不同方向上工作。 例如,它可以告訴你一個列表看起來像移除元素后,它可以(盡管這也很簡單)告訴您從一個列表中刪除哪些因素再弄,也可以告訴你列出,有后給定元素被刪除,將類似於給定列表。
(提示:您可能要研究最后一個)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.