簡體   English   中英

Prolog - 在遞歸謂詞中向List添加元素

[英]Prolog - Add element to List in a recursive predicate

我需要建立一個Prolog謂詞,它在Books2009中返回了2009年出版的書籍列表,以及2014年出版的Books2014書籍。

setbooks :僅用於“創建”將在謂詞booksList_2009_2014中使用的書籍列表。
booksList_2009_2014(L,Books2009,Books2014) :這是我們試圖創建和運行的謂詞(“L”是以前在setbooks中設置的書籍列表)。

我的代碼解釋 :我試圖使謂詞insertAtEnd (稍后將在booksList_2009_2014中使用 )將在列表的末尾插入一個元素。
然后我為最簡單的情況編寫了謂詞booksList_2009_2014 (收到一個空的書籍清單),然后收到一個只有1個元素的書籍列表,然后是一個遞歸案例,無論如何都可以完成一系列書籍的工作很久了。

這是我的代碼文件:

setbooks([book('Name 5', 'Publisher ABC', date(12, 2014)), book('Name 4', 'Publisher ABC', date(05, 2009)), book('Name 3', 'Publisher ABC', date(02, 2009)), book('Name 6', 'Publisher ABC', date(03, 2013)), book('Name 2', 'Publisher ABC', date(12, 2014)), book('Name 1', 'Publisher ABC', date(06, 2009))]).

insertAtEnd(X,[ ],[X]).
insertAtEnd(X,[H|T],[H|Z]) :- insertAtEnd(X,T,Z).

booksList_2009_2014([],_,_).

booksList_2009_2014([book(Name,Publisher,date(M1,Y1))],Books2009, Books2014):-
    Y1=2014 -> insertAtEnd(book(Name,Publisher,date(M1,Y1)),_,Books2014);
    Y1=2009 -> insertAtEnd(book(Name,Publisher,date(M1,Y1)),_,Books2009).

booksList_2009_2014([H|T],Books2009, Books2014):-
    booksList_2009_2014(T,Books2009, Books2014).  

我不確定,但我認為代碼在遞歸代碼中的某處是不正確的:

booksList_2009_2014([H|T],Books2009, Books2014):-
        booksList_2009_2014(T,Books2009, Books2014).  

當我輸入setbooks(L),booksList_2009_2014(L,Books2009,Books2014)時 ,程序只返回列表的最后一本書。例如:

Books2009 = [book('Name 1', 'Publisher ABC', date(06, 2009))] 

有人能幫我嗎? Pleeeasse ???

規則

booksList_2009_2014([H|T],Books2009, Books2014):-
booksList_2009_2014(T,Books2009, Books2014).  

當列表中有一個項目時,只要你達到規則,就可以一次剝掉一本書

booksList_2009_2014([book(Name,Publisher,date(M1,Y1))],Books2009, Books2014):-
    Y1=2014 -> insertAtEnd(book(Name,Publisher,date(M1,Y1)),_,Books2014);
    Y1=2009 -> insertAtEnd(book(Name,Publisher,date(M1,Y1)),_,Books2009).

這當然與列表中的最后一本書結合在一起,因為它不斷地消除了頭部。 然后,由於您沒有使用第一個前述規則中的head元素進行呼叫,因此它將Books2009與insertAtEnd的一次調用統一起來,因為這一年是2009年。

你需要

  • 使用你剝離的頭部元素做一些事情 (也許制作一本不同的謂詞,只需要一本書)
  • 可能會使累加器傳遞給您的書籍2009年和2014年

因此,您嘗試從滿足兩個條件之一的輸入列表元素中進行選擇,並將它們放在兩個結果列表中的一個中:

% list_c1_c2_r1_r2(List, Condition1, Condition2, Result1, Result2)

基本情況:您的輸入列表為空; 所以結果也是空的。 條件可以忽略。

list_c1_c2_r1_r2([], _, _, [], []).

列表的頭部滿足條件1:

list_c1_c2_r1_r2([X|Xs], C1, C2, [X|Ys], Zs) :-
    satisfies(X, C1),
    list_c1_c2_r1_r2(Xs, C1, C2, Ys, Zs).

列表的頭部滿足條件2:

list_c1_c2_r1_r2([X|Xs], C1, C2, Ys, [X|Zs]) :-
    satisfies(X, C2),
    list_c1_c2_r1_r2(Xs, C1, C2, Ys, Zs).

頭部不滿足以下兩個條件中的任何一個:

list_c1_c2_r1_r2([X|Xs], C1, C2, Ys, Zs) :-
    \+ satisfies(X, C1),
    \+ satisfies(X, C2),
    list_c1_c2_r1_r2(Xs, C1, C2, Ys, Zs).

對於您的情況,您可以編寫satisfies(X, Condition) ,例如:

satisfies(book(_, _, date(_, Year)), Year).

那么,您可以查詢:

?- books(Books), list_c1_c2_r1_r2(Books, 2009, 2014, Book2009, Books2014).
Books = [book('Name 5', 'Publisher ABC', date(12, 2014)),
         book('Name 4', 'Publisher ABC', date(5, 2009)),
         book('Name 3', 'Publisher ABC', date(2, 2009)),
         book('Name 6', 'Publisher ABC', date(3, 2013)),
         book('Name 2', 'Publisher ABC', date(12, 2014)),
         book('Name 1', 'Publisher ABC', date(6, 2009))],
Book2009  = [book('Name 4', 'Publisher ABC', date(5, 2009)),
             book('Name 3', 'Publisher ABC', date(2, 2009)),
             book('Name 1', 'Publisher ABC', date(6, 2009))],
Books2014 = [book('Name 5', 'Publisher ABC', date(12, 2014)),
             book('Name 2', 'Publisher ABC', date(12, 2014))] .

你可以改變它,以便在不相互排斥的條件下正常工作嗎? 如果你跳過最后一句中既不滿足條件的要求,會發生什么? 您如何參數化評估條件的方式? 如何參數化條件數和結果列表?

如何解釋 ? 你正在逆轉CONS操作WRT控制流...而insertAtEnd無論如何它都是Prolog中的錯誤方法,因為它是一個帶有不可變 (賦值一次)變量的語言。

你可以寫

booksList_2009_2014([], [], []).
booksList_2009_2014([Book|Books], L2009, L2014) :-
  booksList_2009_2014(Books, L2009_t, L2014_t), % note: construct the tail(s) first
  Book = book(_,_,date(_,Year)),
  (  Year == 2009
  -> L2009 = [Book|L2009_t], L2014 = L2014_t
  ;  Year == 2014
  -> L2009 = L2009_t, L2014 = [Book|L2014_t]
  ;  % did you forgot year 2013 ?
     L2009 = L2009_t, L2014 = L2014_t
  ).

但是將數據硬編碼到邏輯中它是任何語言中的錯誤方法,而在Prolog中則更多。 無論你的任務如何簡單,一個更好的方法將避免將vars綁定到特定的年份書。 保持聲明:

books_of_year(AllBooks, Year, Result) :-
  Book = book(_,_,date(_,Year)),
  findall(Book, member(Book, AllBooks), Result).

現在

?- setbooks(L), books_of_year(L,2009,Books2009), books_of_year(L,2014,Books2014).
% L = ... not interesting
Books2009 = [book('Name 4', 'Publisher ABC', date(5, 2009)), book('Name 3', 'Publisher ABC', date(2, 2009)), book('Name 1', 'Publisher ABC', date(6, 2009))],
Books2014 = [book('Name 5', 'Publisher ABC', date(12, 2014)), book('Name 2', 'Publisher ABC', date(12, 2014))].

暫無
暫無

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

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