2016-07-14 36 views
1

我有以下數據:如何打印出搜索的數量有限,在序言

item(one, 50, 40). 
item(two, 80, 70). 
item(three, 100, 55). 
item(four, 50, 45). 
item(five, 50, 40). 
item(six, 80, 70). 
item(seven, 100, 55). 
item(eight, 50, 45). 

我用下面的命令來顯示所有的值:

findall((A,B,C), item(A,B,C), L). 

然而,它會顯示所有項目。如果有一百個這樣的條目,這可能是一個問題。我如何顯示有限數量的項目,比如上面的情況3?

我看到這裏有一些帖子:Prolog: "findall" for limited number of solutionsFinding up to N unique solutions of a goal in PrologProlog: "findall" for limited number of solutions但我無法適應那些我的問題。

我想下面的代碼,但它不拾取列表的長度:

head(N):- 
    findall((A,B,C), item(A,B,C),L), 
    writeln(L), 
    writeln("------ 1 ---------"), 
    length(L, N), 
    writeln(N), 
    writeln("------ 2 ---------"), 
    head2(L, N, 0). 

head2(L, N, M):- 
    M < N, 
    nth0(M, L, Item), 
    writeln(Item), 
    X is M+1, 
    head2(L, N, X). 

輸出:

?- head(3). 
[ (one,50,40), (two,80,70), (three,100,55), (four,50,45), (five,50,40), (six,80,70), (seven,100,55), (eight,50,45)] 
------ 1 --------- 
false. 

回答

1

有一件事我在下面發現:

head(N) :- 
    findall((A,B,C), item(A,B,C),L), 
    writeln(L), 
    writeln("------ 1 ---------"), 
    length(L, N), 
    ... 

考慮到基本的Prolog原則:只有在以下情況下才能成功findall/3產生一個列表L長度爲L正好是N。如果查詢head(3),並且findall/3會生成一個長度不是3的列表,那麼length(L, N)將會失敗,並且永不會調用以下語句(...)。當然,由於您在失敗前有writeln,因此writeln將執行,顯示您的結果。

作爲一般性評論,您應該嘗試使用變量作爲結果,而不是writeln語句。 writeln非常適合提示用戶或追蹤特定部分的代碼,但不適用於生成稍後可用的結果。

的另一種方法:

find_n_items(MaxCount, Items) :- 
    findall((A,B,C), item(A,B,C), AllItems), 
    length(AllItems, AllItemsCount), 
    ItemsCount is min(AllItemsCount, MaxCount), 
    length(Items, ItemsCount), % Constrain the length of Items 
    append(Items, _, AllItems). % Select ItemCount items from front of AllItems 

在這裏,我們限制的Result長度爲什麼findall/3產生最小和請求的長度限制,並採取數目的元件從AllResults使用append/3前面。

1
:- dynamic limitcount/1. 

maxbacktrack :- 
    retract(limitcount(Current)), 
    Current > 0, 
    Next is Current-1, 
    assert(limitcount(Next)). 

firstN(N,Pred) :- 
    retractall(limitcount(_)), 
    asserta(limitcount(N)), 
    Pred, 
    maxbacktrack. 

findN(N,Term,Pred,List) :- 
    findall(Term,firstN(N,Pred),List). 

例如:

?- findN(3,(A,B,C),item(A,B,C),L). 
L = [ (one, 50, 40), (two, 80, 70), (three, 100, 55)]. 
+0

好的解決方案。謝謝。 – rnso