簡體   English   中英

Prolog:比較列表元素和總和

[英]Prolog: compare list elements and sum

Prolog的新增功能,並嘗試實現以下包含3個列表的功能:

  • 如果列表長度相同,則為真
  • 如果第三個列表的元素是兩個列表的和,則為True

示例: fn([1,2,3],[4,5,6],[5,7,9])返回true 注意,總和是逐元素加法。

這是我到目前為止的內容:

fn([],[],[]).
fn([_|T1], [_|T2], [_|T3]) :-
    fn(T1,T2,T3),         % check they are same length
    fn(T1,T2,N1),         % check that T3=T1+T2
    N1 is T1+T2,
    N1 = T3.

據我了解,該錯誤是由於基本情況造成的(它具有空列表,這會導致加法評估出錯?)

感謝您的幫助和解釋!

除了@GuyCoder的答案,我還指出,在修改列表的所有元素時,值得考慮使用來自library(apply)的maplist謂詞之一。 您可以使用謂詞來描述三個數字之間的關系...

:- use_module(library(apply)).   % for maplist/4

num_num_sum(X,Y,S) :-
   S is X+Y.

...,然后使用maplist / 4將其應用於整個列表:

fn(X,Y,Z) :-
   maplist(num_num_sum,X,Y,Z).

如果前兩個列表被完全實例化,則該謂詞將產生所需的結果:

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

但是,由於使用了is / 2,如果前兩個列表包含變量,則會出現實例化錯誤:

   ?- fn([1,A,3],[4,5,6],[5,7,9]).
     ERROR at  clause 1 of user:num_num_sum/3 !!
     INSTANTIATION ERROR- X is _+B: expected bound value
   ?- fn([1,2,3],[4,5,A],[5,7,9]).
     ERROR at  clause 1 of user:num_num_sum/3 !!
     INSTANTIATION ERROR- X is A+B: expected bound value

如果只想對整數列表使用謂詞,則可以使用CLP(FD)使謂詞更通用:

:- use_module(library(apply)).
:- use_module(library(clpfd)).   % <- use CLP(FD)

int_int_sum(X,Y,S) :-
   S #= X+Y.                     % use CLP(FD) constraint #=/2 instead of is/2

fnCLP(X,Y,Z) :-
   maplist(int_int_sum,X,Y,Z).

有了這個定義,以前有問題的查詢也可以工作:

   ?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
A = 2
   ?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
A = 6

即使是最一般的查詢,使用此版本也會產生結果:

   ?- fnCLP(X,Y,Z).
X = Y = Z = [] ? ;
X = [_A],
Y = [_B],
Z = [_C],
_A+_B#=_C ? ;
X = [_A,_B],
Y = [_C,_D],
Z = [_E,_F],
_A+_C#=_E,
_B+_D#=_F ? ;
.
.
.

由於上述答案中的數字不是唯一確定的,因此您將獲得剩余目標而不是實際數字。 為了獲得答案中的實際數字,您必須限制兩個列表的范圍並對其進行標記(請參閱文檔以獲取詳細信息),例如,生成包含第一個列表中的數字3、4、5和6的列表。 ,7,8在第二個列表中,您可以查詢:

                                             label the lists
                    restrict the domain         |        |
                       v           v            v        v
   ?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
X = Y = Z = [] ? ;
X = [3],
Y = [6],
Z = [9] ? ;
X = [3],
Y = [7],
Z = [10] ? ;
.
.
.
X = [3,4],
Y = [6,7],
Z = [9,11] ? ;
X = [3,4],
Y = [6,8],
Z = [9,12] ? ;
.
.
.

另外需要注意的是:還有一些可能有趣的布爾值( CLP(B) ),有理數和實數( CLP(Q,R) )的clp庫。

據我了解,該錯誤是由於基本情況造成的。

我不這樣認為。

我看到的第一個問題是,您正在嘗試處理導致使用DCG的列表,但是由於您是新手,所以我會避免使用該方法。

在處理列表時,通常會處理列表的頭部,然后使用遞歸將尾部傳遞回謂詞。

例如,對於列表長度

ln([],N,N).
ln([_|T],N0,N) :-
   N1 is N0+1,
   ln(T,N1,N).

ln(L,N) :-
    ln(L,0,N).

謂詞ln/2用於將初始計數設置為0,而謂詞ln/3使用遞歸進行工作。 請注意,列表的開頭如何從列表的前面移開,列表的結尾如何又遞歸地傳遞到謂詞上。 當列表為空時,謂詞ln([],N,N). 在這種情況下,請考慮將副本從第二個位置轉換為第三個位置的中間計數,然后將其與ln/2一起傳回。

現在回到您的問題。

基本情況很好

fn([],[],[]).

一共有三個列表,每個列表都以[H|T]

fn([H1|T1],[H2|T2],[H3|T3])

而在尾部進行遞歸的調用是

fn(T1,T2,T3) 

剩下的就是處理頭部

H3 is H1 + H2

放在一起給我們

fn([],[],[]).
fn([H1|T1], [H2|T2], [H3|T3]) :-
   H3 is H1 + H2,
   fn(T1,T2,T3).

和快速檢查。

?- fn([],[],[]).
true.

?- fn([1],[1],[2]).
true.

?- fn([1,2],[3,4],[4,6]).
true.

?- fn([1,2],[3,4,5],[4,6,5]).
false.

關於這兩個條件。 當我查看邏輯編程的練習題時, True if lists are the same length或返回true的其他條件,則有時會給出諸如True if lists are the same length條件。 我傾向於一開始就忽略這些內容,而是專注於首先完成另一部分,在這種情況下elements of third list is sum of the two lists然后檢查其他條件是否正確。 對於大多數簡單的課堂練習,它們都是如此。 我有時認為老師會嘗試給出這些額外的條件來使學生感到困惑,但實際上,僅僅是為了闡明代碼應如何工作。

暫無
暫無

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

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