2016-07-07 44 views
1

在這個問題上Can be this lisp function be implemented recursively?延伸的所有成員,是有可能在Prolog的所有組合,如果列表中表示類似以下內容:排列組合包括序言

items1(1, 2, 3). 
items2(4, 5). 

我能得到的答案與下面的數據格式:

items1(1). 
items1(2). 
items1(3). 

items2(4). 
items2(5). 

?- findall((A,B), (items1(A), items2(B)), L). 
L = [ (1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)]. 

我檢查了http://www.swi-prolog.org/pldoc/man?predicate=permutation/2的置換謂詞,但這是爲了不同的目的。

回答

1

你似乎已經很好地解決了你的問題,通過規範你的數據庫。將代表[I_1, I_2, ..., I_n]列爲事實items(I_1, I_2, ..., I_n).是不方便的。列表是指具有0個或更多元素的(可能是有序的)集合;事實通常用於具有預設列數的表格,每行一個事實。而這兩種表示:

  1. [a, b, c](列表),並
  2. item(a). item(b). item(c).(事實表)

其實非常相似。選擇一個或另一個是你想要如何使用它的問題,在你的程序中從一個轉換到另一個是很容易的(也是常見的)。例如,當(2)定義時,?- member(X, [a, b, c]).?- item(X).大致相同。的the question you linked序言列表版本將是:

combo(L1, L2, X-Y) :- 
    member(X, L1), 
    member(Y, L2). 

然後:

?- combo([1,2,3], [4,5], R). 
R = 1-4 ; 
R = 1-5 ; 
R = 2-4 ; 
R = 2-5 ; 
R = 3-4 ; 
R = 3-5. 

少一點不方便(但仍是不必要的)是寫items([a, b, c]).,讓你有一個說法,名單所有項目。然後,你可以這樣做:

?- items(Is), 
    member(X, Is). 

如果真有這樣的事items(a, b, c).你知道你究竟有三個項目,你仍然可以這樣做:

?- items(A, B, C), 
    member(X, [A, B, C]). 

如果你不這樣做在編譯時知道items的屬性,您需要在運行時檢查程序。如果你的程序看起來你的問題:

items1(1, 2, 3). 
items2(4, 5). 

然後,你可以,例如做:

?- current_predicate(items1/N), % figure out the arity of items1 
    length(Is, N),    % make a list of that length 
    Fact =.. [items1|Is],  % create a callable term 
    Fact,      % call the term to instantiate Is 
    member(X, Is).    % enumerate the list 

正如你看到的,很圓的。

還有一點意見:在Prolog中使用(A,B)作爲「元組」是不常見的。對於一對,通常你會寫A-B,如果你不知道有多少元素,通常只是一個列表,例如[A,B|Rest]。有關更多詳細信息,請參見this answer及其下方的註釋。

+0

重要的答案。謝謝。 – rnso

+0

@rnso我仍然有點驚訝,這個Lisp版本是如此迂迴。必須有一個更簡單的方法來做到這一點.... – 2016-07-07 08:15:21

+0

像您這樣的更有經驗的人可以對Prolog vs Lisp發表評論。你早些時候已經發布過嗎? – rnso