2014-09-11 79 views
1

我需要建立一个Prolog的谓词这Books2009返回发表在2009年的一年书单列出,并在Books2014,书出版于2014年序言 - 添加元素的递归谓词

setbooks:只会用于“创建”将在谓词booksList_2009_2014中使用的书籍列表。
booksList_2009_2014(L,Books2009,Books2014):这是我们试图创建和运行的谓词(“L”是先前在setbook中设置的书籍列表)。

我的代码解释:我试图让谓语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). 

林不知道,但我想代码的心不是某个地方纠正递归代码:

​​

当我键入setbooks(L ),booksList_2009_2014(L,Books2009,Books2014),该程序正在返回我刚刚列出的最后一本书。例如:

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

有人能帮助我吗? Pleeeasse ???

回答

1

如何解释? 您正在逆转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 
). 

但硬编码数据导入逻辑它在任何语言错误的做法,并在序言等等。不管现在你的任务如何简单,一个更好的方法都可以避免将特定年份的书籍和书籍绑定在一起。保持它声明:

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))]. 
+0

你能帮忙吗?当使用'books_of_year'时,出现错误''findall'中的自由变量只能在'findall'Book'内使用。不明白原因。 – Aliaxander 2016-12-04 23:34:15

+0

@Aliaxander:也许你应该发表一个关于你的问题的问题。我不清楚细节,因为我从未见过这样的警告...... – CapelliC 2016-12-05 08:39:21

1

规则

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

保持在你的规则timeuntil剥落的一本书时,有列表

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元素进行调用,因此自2009年以来,它将Books2009与一个呼叫统一为insertAtEnd。

您需要

  • 东西与你剥离头元素(可能做出不同的谓词接受单个书)
  • 可能使累加器是传递了你的书2009年和2014年
+1

蓄电池是有用的,但越是这样,当你需要将信息传递给递归调用。看来,这不是必要的。 – 2014-09-11 05:40:06

+1

加入@Boris评论:累加器会使OP'代码(已经复杂)更加复杂,并且会颠倒顺序,给这样的基本任务增加更多的复杂性...... – CapelliC 2014-09-11 05:51:17

1

所以,你试图从满足两个条件之一的输入列表中的元素在两个结果列表中选择一个,并把它们:

% 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, 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, [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, 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))] . 

可以更改这对于不是相互排斥的条件下正常工作?如果你跳过最后一个条件中的条件满足的条件,会发生什么?你如何参数化条件评估的方式?你如何参数化条件数和结果列表?