如何对序言中的列表列表执行算术运算 [英] How to perform arithmetic operations on a list of lists in prolog

查看:38
本文介绍了如何对序言中的列表列表执行算术运算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个函数,该函数接受一个列表列表,并获取列表中的头元素,并将其与列表列表中的每个其他元素进行比较.我知道使用递归是如何在列表上执行大多数操作,但我在尝试将其转换为列表列表时遇到了一些困难.到目前为止,这是我想出的:

I'm writing a function that takes in a list of lists and takes the head element in the list and compares it to every other element in the list of lists. I know using recursion is how to perform most actions on a list but I've been coming across some difficulties trying to translate this onto a list of lists. This is what I've come up with so far:

compareElements([H|T]) :-
    compareHeadList(H,T).

compareHeadList([H|T],RestOfList) :-
    compare(T,H,GreaterList,LesserList),
    compareRestList(RestOfList,H).

compareRestList(X,[HA|TA]) :-
    compare(HA,X,GreaterList,LesserList),
    compareRestList(X,TA).

compare([HA|TA],X,GreaterList,LesserList) :-
    X @> HA -> GreaterList = [HA|GreaterTail],
    compare(TA,X,GreaterTail,LesserList);
    LesserList = [HA|LesserTail],
    compare(TA,X,GreaterList,LesserTail).
compare([_|TA],X,GreaterList,LesserList) :-
    compare(TA,X,GreaterList,LesserList).

例如:

    compareElements(LoL).
    Where Lol = [[6,4,8],[7,9,2],[1,3,0]]
    My Goal is to compare 6 with every other element in the Lol, 
    so that GreaterList = [8,7,9], and LesserList = [4,2,1,3,0]

我对代码应该如何运行的想法是 compareElements() 接收一个列表列表,然后调用 compareHeadList() 将第一个列表的头部与该列表中的其余元素进行比较.最后, compareRestList() 应该接受要比较的 Head 元素和列表的其余部分,调用 compare 函数,并返回 true.

My idea of how the code should run is compareElements() takes in a list of lists, then calls compareHeadList() to compare the head of the first list with the rest of the elements in that list. Finally, compareRestList() is supposed to take in the Head element to be compared and the rest of the list of lists, call the compare function, and return true.

我的问题是当我 writeLn() 列表来检查它输出序列的元素时,如9c78";这似乎是一个内存地址.我想知道我是否正确比较了元素并将它们正确地推到了列表中,或者是否有其他部分导致这种情况发生.

My problem is when I writeLn() the lists to check the elements it's outputting sequences like "9c78" which seems like a memory address. I'm wondering if I'm comparing the elements properly and pushing them onto the list correctly or if there is another piece causing this to happen.

推荐答案

您的方法可以奏效.有关缺少什么的提示,请参阅 Prolog 发出的这些警告:

Your approach can be made to work. For a hint on what is missing, see these warnings emitted by Prolog:

Warning: /home/isabelle/lol.pl:4:
    Singleton variables: [GreaterList,LesserList]
Warning: /home/isabelle/lol.pl:8:
    Singleton variables: [GreaterList,LesserList]

单例变量警告严重.他们告诉您,您犯了一种通常会使程序变得毫无意义的错字,或者(如本例)您尚未将计算的某些部分与其他部分连接起来.在您的程序中,即使您计算嵌套列表之一的较大/较小列表,也永远不会将其与其他嵌套列表的较大/较小列表相关联——因此您永远无法得到完整的答案.

Singleton variable warnings are serious. They tell you that you have made the kind of typo that typically makes a program meaningless, or (as in this case) that you have not yet connected some parts of the computation with others. In your program, even when you compute the greater/lesser lists for one of the nested lists, you never relate this to the greater/lesser lists for the other nested lists -- so you can never get a complete answer.

如果其中一个列表的较大列表是 [8],而另一个列表是 [7, 9],那么我们想以某种方式构造总数[8, 7, 9] 的更大列表.Prolog 中的一种常见方法是实际上只计算 部分 列表:尾部不是 [] 而是变量的列表.在示例中,如果我们计算部分列表 [8 |Tail],然后要求下一个计算与Tail统一,我们得到[8, 7, 9 | 的组合部分列表Tail2].将 Tail2[] 统一将最终关闭列表.

If the greater list for one of the lists is [8], and for another list it's [7, 9], then we somehow want to construct the total greater list of [8, 7, 9]. A common way in Prolog is to actually only compute partial lists: Lists where the tail is not [] but a variable. In the example, if we compute the partial list [8 | Tail], and then ask for the next computation to be unified with Tail, we get a combined partial list of [8, 7, 9 | Tail2]. Unifying Tail2 with [] will then close the list in the end.

这是您的代码适应这种方法,并使用更明确的名称:

Here is your code adapted to this approach, and using somewhat more explicit names:

list_element_greater_smaller([], _Y, GreaterTail, GreaterTail, SmallerTail, SmallerTail).
list_element_greater_smaller([X | Xs], Y, Greater, GreaterTail, Smaller, SmallerTail) :-
    (   X > Y
    ->  Greater = [X | Greater1],
        list_element_greater_smaller(Xs, Y, Greater1, GreaterTail, Smaller, SmallerTail)
    ;   Smaller = [X | Smaller1],
        list_element_greater_smaller(Xs, Y, Greater, GreaterTail, Smaller1, SmallerTail) ).

lists_element_greater_smaller([], _Y, GreaterTail, GreaterTail, SmallerTail, SmallerTail).
lists_element_greater_smaller([Xs | Xss], Y, Greater, GreaterTail, Smaller, SmallerTail) :-
    list_element_greater_smaller(Xs, Y, Greater, GreaterTail1, Smaller, SmallerTail1),
    lists_element_greater_smaller(Xss, Y, GreaterTail1, GreaterTail, SmallerTail1, SmallerTail).

lists_greater_smaller([[Y | Xs] | Xss], Greater, Smaller) :-
    lists_element_greater_smaller([Xs | Xss], Y, Greater, [], Smaller, []).

花点时间了解 Tail 变量如何通过所有计算线程化,然后以 [] 结束.

Take the time to understand how the Tail variables are threaded through all the computations and then closed off with [].

行为如下:

?- lists_greater_smaller([[6,4,8],[7,9,2],[1,3,0]], Greater, Smaller).
Greater = [8, 7, 9],
Smaller = [4, 2, 1, 3, 0].

只要列表的嵌套深度是固定的,还有一种更简单的方法来编写所有这些:您可以在 嵌套 列表上编写一个递归谓词,非常类似于您如何执行平面"上的递归列表.您将需要区分三种情况:

As long as the nesting depth of the lists is fixed, there is also a simpler way to write all this: You can write a single recursive predicate over nested lists very similarly to how you do a recursion over a "flat" list. You will have three cases to distinguish:

  • 整个外部列表为空
  • 第一个嵌套列表为空
  • 第一个嵌套列表有一些头部和尾部

这种方法看起来像这样:

This approach can look like this:

lists_greater_smaller2([[Y | Xs] | Xss], Greater, Smaller) :-
    lists_element_greater_smaller2([Xs | Xss], Y, Greater, Smaller).

lists_element_greater_smaller2([], _Y, [], []).
lists_element_greater_smaller2([[] | Xss], Y, Greater, Smaller) :-
    lists_element_greater_smaller2(Xss, Y, Greater, Smaller).
lists_element_greater_smaller2([[X | Xs] | Xss], Y, Greater, Smaller) :-
    (   X > Y
    ->  Greater = [X | Greater1],
        lists_element_greater_smaller2([Xs | Xss], Y, Greater1, Smaller)
    ;   Smaller = [X | Smaller1],
        lists_element_greater_smaller2([Xs | Xss], Y, Greater, Smaller1) ).

再说一遍:

?- lists_greater_smaller2([[6,4,8],[7,9,2],[1,3,0]], Greater, Smaller).
Greater = [8, 7, 9],
Smaller = [4, 2, 1, 3, 0] ;
false.

这篇关于如何对序言中的列表列表执行算术运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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