关于列表列表的谓词 [英] Predicate about a list of lists

查看:30
本文介绍了关于列表列表的谓词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个谓词,它接收一个列表列表并返回一个列表列表,该列表包含来自第一个列表的所有单一列表(长度为 1 的列表),但是它不起作用.这是我创建的:

I'm trying to create a predicate that receives a list of lists and returns a list of lists containing all the unitary lists (lists whose length is 1) from the first list, however it is not working. This is what I created:

elimina_listas_nao_unitarias_lista_de_listas([[A]|T],N_List):-
  length([A], 1),
  N_List is [H|N_List_T],
  elimina_listas_nao_unitarias_lista_de_listas(T, N_List_T).

elimina_listas_nao_unitarias_lista_de_listas([[A]|T], N_List):-
  length([A], X),
  X > 1,
  elimina_listas_nao_unitarias_lista_de_listas(T, N_List2).

这是它应该做的:

elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3]], [3])
elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3,4,5]], [])

当前每次都重新调整为false

It is retuning false currently everytime

推荐答案

让我们来看看你的第一条规则.第一个目标总是成功,因为您要问的是包含单个元素的列表的长度是否为 1.只需在提示符处尝试:

Let's take a look at your first rule. The first goal always succeeds, since you are asking if a list with a single element is of length 1. Just try it at the prompt:

   ?- length([A], 1).

true

相反,您可能希望在第一个列表的头部有一个没有括号的变量(例如 [L|Ls])并确保它是一个长度为 1 的列表:

Instead, you probably want to have a variable without the brackets in the head of the first list (e.g. [L|Ls]) and ensure that it is a list of length 1:

   ?- length(L,1).
L = [_A]

第二条规则头部的第一个列表及其第一个目标也是如此.在您的第二个目标中,您试图将 [H|N_List_T] 评估为带有 is/2 的算术表达式,以便 N_List 保存该值.除了这没有意义的事实之外,您可以在提示处尝试一下,看看这个目标如何不能成功:

The same goes for the first list in the head of your second rule and its first goal. In your second goal you are trying to evaluate [H|N_List_T] as an arithmetic expression with is/2 such that N_List holds the value. Besides the fact that this doesn't make sense, you can try that at the prompt and see how this goal can't succeed:

   ?- N_List is [H|N_List_T].
     ERROR!!
     TYPE ERROR- string must contain a single character to be evaluated as an arithmetic expression: expected evaluable term, got [_131245|_131246]

相反,您想统一这两个术语:

Instead, you want to unify the two terms:

   ?- N_List = [H|N_List_T].
N_List = [H|N_List_T]

但是,如果将 [H|N_List_T] 写为规则头部的第二个参数,则可以完全摆脱这个目标.此外,您可能希望在第二个列表的头部使用单一列表 L 而不是变量 H.此外,您还缺少一个案例,即第一个列表是 [].在那种情况下,第二个列表也是空的,因为空列表显然不包含任何单一列表.最后,我要指出,如果您选择一个更简单且更具声明性的名称,例如 listas_unitarias/2,它可能会增强您的代码的可读性.将所有这些放在一起,您可能会得到这样的谓词:

However, you can get rid of this goal entirely if you write [H|N_List_T] as the second argument in the head of the rule. Additionally, you might want the unitary list L in the head of the second list instead of the variable H. Furthermore you are missing a case, namely the first list being []. In that case the second list is empty as well, since the empty list clearly does not contain any unitary lists. Finally, I would note that it might enhance the readability of your code if you picked a somewhat simpler and more declarative name, say listas_unitarias/2. Putting all this together, you might end up with a predicate like this:

listas_unitarias([],[]).
listas_unitarias([L|Ls],[L|Ss]) :-
   length(L,1),
   listas_unitarias(Ls,Ss).
listas_unitarias([L|Ls],Ss) :-
   length(L,X),
   dif(X,1),
   listas_unitarias(Ls,Ss).

您的第二个示例查询产生了所需的结果

Your second example query yields the desired result

   ?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []

对于您的第一个示例查询,结果略有不同:

For your first example query the result is slightly different:

   ?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]] ? ;
no

唯一的单一列表在列表本身中.这会更有意义,因为第一个参数可能包含多个这样的列表.考虑以下情况:

The only unitary list is in a list itself. That would make more sense, since the first argument might contain more than one such list. Consider the following case:

   ?- listas_unitarias([[1],[2,3],[4],[]],U).
U = [[1],[4]] ? ;
no

但是,如果您打算一次获取一个单一列表,则谓词看起来会略有不同:

However, if you meant to get the unitary lists one at a time, the predicate would look slightly different:

listas_unitarias2([L|_Ls],L) :-
   length(L,1).
listas_unitarias2([_L|Ls],U) :-
   listas_unitarias2(Ls,U).

与查询结果一样:

   ?- listas_unitarias2([[1,2],[1,2,3],[3]], U).
U = [3] ? ;
no
   ?- listas_unitarias2([[1],[2,3],[4],[]],U).
U = [1] ? ;
U = [4] ? ;
no

特别是您的第二个示例查询:它会失败而不是生成空列表作为解决方案:

Especially your second example query: It would fail instead of producing the empty list as a solution:

   ?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],U).
no
   ?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],[]).
no

正如@false 在评论中指出的,第三条规则中 length/2 和 dif/2 的组合使用不会终止 [_,_|_] 所以查询

As pointed out by @false in the comments the combined use of length/2 and dif/2 in the third rule doesn't terminate for [_,_|_] so the query

   ?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]] ? ;
U = [[1],[2]] ? ;
... 

也不会终止.然而,在这种情况下期望终止是合理的,因为以两个元素为首的列表肯定不能是单一的.因此,您可以考虑描述涵盖所有可能性的四种情况,而不是使用 length/2.1) 如果第一个列表是空的,那么第二个列表也是空的.2) 如果第一个列表的头部是 [] 则它不在第二个列表中.3) 如果第一个列表的头部是[A],则它在第二个列表中.4) 如果第一个列表的头部至少有两个元素,则它不在第二个列表中.

does not terminate as well. However, it is reasonable to expect termination in this case, since a list headed by two elements certainly can't be unitary. So, instead of using length/2 you might consider describing the four cases that cover all possibilities. 1) If the first list is empty so is the second list. 2) If the head of the first list is [] it's not in the second list. 3) If the head of the first list is [A] it is in the second list. 4) If the head of the first list has at least two elements it's not in the second list.

listas_unitarias([],[]).                    % case 1)
listas_unitarias([[]|Ls],Ss) :-             % case 2)
   listas_unitarias(Ls,Ss).
listas_unitarias([[A]|Ls],[[A]|Ss]) :-      % case 3)
   listas_unitarias(Ls,Ss).
listas_unitarias([[_,_|_]|Ls],Ss) :-        % case 4)
   listas_unitarias(Ls,Ss).

使用此版本,上述查询在找到唯一解决方案后终止:

With this version the above query terminates after finding the only solution:

   ?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]]

上面的其他查询产生相同的结果:

The other queries from above yield the same results:

   ?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
   ?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]]
   ?- listas_unitarias([[1],[2,3],[4],[]],S).
S = [[1],[4]]

这篇关于关于列表列表的谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆