2013-09-27 66 views
1

我有一個問題,需要有人糾正我:Prolog的列表操作

store(wyoming, [evan, sandra], [storybook, fiction, general]).
store(brooklyn, [haas, maria], [fiction, schoolbook, religion]).
store(oakland, [rich, walker, dina, vince], [storybook, schoolbook, fiction]).

,如果我徵詢?-locations(storybook).答案必須返回true,因爲故事書,可在多個商店。我寫這樣的謂詞:

locations(Book) :- store(_, [_], [Books]), member(Book, Books). 

當我諮詢時,無論我輸入什麼類型的書,我都會返回false。如何解決這個問題?

+2

嘗試'store(_,_,Books)'而不是'store(_,[_],[Books])''。 '[書籍]'只會與一個原子匹配一個列表,並用這個原子實例化'Books'。並且'[_]'也將只與單個原子而不是任何列表匹配。這兩者都會導致與您的所有事實不匹配。 – lurker

+0

每當答案匹配時它都會返回true。例如,對於故事書,「真實」答案出現2次 – Man

回答

0

應用mbratch建議後,您仍然需要檢查何時在多個商店有Book。最簡單的方式,效率低下,因爲如果 '分析' 所有DB:

locations(Book) :- 
    findall(Book, (store(_,_,Books), memberchk(Book, Books)), L), 
    length(L, N), N > 1. 

我們可以讓它更簡潔:

locations(Book) :- 
    findall(_, (store(_,_,Books), memberchk(Book, Books)), [_,_|_]). 

注意我用,而不是成員/ 2 memberchk/2。它的速度更快,並且作爲副作用,在只有商店匹配的情況下避免回答真實,但是該書目前不止一次。

要避免掃描整個數據庫,一個連接會做:

locations(Book) :- 
    store(X,_,BooksX), memberchk(Book,BooksX), 
    store(Y,_,BooksY), Y \= X, memberchk(Book,BooksY), 
    !. 

晉級決賽防止多個無用的答案爲同一Book

+0

你能解釋這一行嗎:findall(_,(store(_,_,Books),memberchk(Book,Books)),[_,_ | _] )。尤其是這部分---> [_,_ | _] – Man

+0

簡單統一:'[_,_ | _]'匹配長度> 1的任何*列表 – CapelliC