简体   繁体   English

涉及算术运算和计数元素的列表上的递归?

[英]Recursion on a list involving arithmetic operations and counting elements?

I'm struggling to really grasp the understanding of Prolog lists and recursive calls.我正在努力真正掌握对 Prolog 列表和递归调用的理解。 I've been working on a program to keep track of how many items are greater than the head of the list and then recursively call this relation to check greater than the next element and so on.我一直在开发一个程序来跟踪有多少项大于列表的头部,然后递归调用这个关系来检查大于下一个元素等等。 I've gotten my program working to the point where it can count the number of elements greater than the head but once it reaches the end and tries to recursively call the relation on the next element it fails.我已经让我的程序工作到可以计算大于头部的元素数量的地步,但是一旦它到达末尾并尝试递归调用下一个元素上的关系,它就会失败。 From the research I've done here's what I have and how I think it's supposed to work:从我在这里所做的研究来看,我所拥有的以及我认为它应该如何工作:

Input - List = [7,2,4,3,6,9,8,10,12,5].

testHead(List).

testHead([H|T]) :-
    greaterThan(H,T,0),
    teastHead(T).

^My understanding is this relation takes the head element from the list and calls greaterThan using the head and the rest of the list. ^我的理解是这种关系从列表中获取头部元素并使用头部和列表的其余部分调用greaterThan。 After the greaterThan finishes, it should recursively call testHead(T) to test the next element and so on.在greaterThan 完成后,它应该递归调用testHead(T) 来测试下一个元素等等。

greaterThan(H,[X|T],C) :-
    H > X ->
    C2 is C+1,
    greaterThan(H,T,C2);
    greaterThan(H,T,C).

^My understand here is the greaterThan reads in the head element, the rest of the list, and a variable for counting. ^我的理解是在头元素、列表的其余部分和一个用于计数的变量中读取的值更大。 If the head is greater than the next element, increase the count and recursively call greaterThan with the Tail and new count;如果 head 大于下一个元素,则增加计数并使用 Tail 和新计数递归调用greaterThan; else recursively call greaterThan without incrementing count.否则递归调用greaterThan而不增加计数。

My expected output would be C2 = 12 .我的预期输出C2 = 12 ( 7 is greater than 5 elements, 2 is greater than 0 elements, 4 is greater than 1 element, and so on) 7大于5元素, 2大于0元素, 4大于1元素,以此类推)

The actual output currently is 5;当前实际输出为5; then false .然后是false
My program seems to be correctly evaluating and incrementing for the head element but when it finishes greaterThan for that element the program returns false.我的程序似乎正确地评估和递增 head 元素,但是当它完成该元素的 GreaterThan 时,程序返回 false。 I've tried researching and understanding lists and recursive calls in prolog but I've been hitting a wall.我试过研究和理解序言中的列表和递归调用,但我一直在碰壁。 I'm not sure if it fails because you can't recursively run the increment relation or if there's some other issue with my list relation.我不确定它是否失败,因为您无法递归运行增量关系,或者我的列表关系是否存在其他问题。 Any clarification on how to tackle this issue and how prolog functions here would be helpful.关于如何解决这个问题以及 prolog 在这里如何运作的任何澄清都会有所帮助。

Lets start with your first code snippet:让我们从您的第一个代码片段开始:

testHead(List).  
testHead([H|T]) :-
    greaterThan(H,T,0),
    teastHead(T).

You got the idea of recursion but I see four problems.你有递归的想法,但我看到了四个问题。

First : there is only one attribute for testHead , which means (besides true and false ) you get nothing back.第一testHead只有一个属性,这意味着(除了truefalse )你什么也得不到。 So it should look more like this: testHead([H|T], L) ... .所以它应该看起来更像这样: testHead([H|T], L) ...

Second : you need to know when to stop.第二:你需要知道什么时候停止。 This is normally the first line of a predicate.这通常是谓词的第一行。 Yours states: anything matches .你说:任何匹配 But it should say something like: if there is no element left, I can "return" an empty list.但它应该是这样的:如果没有元素了,我可以“返回”一个空列表。 testHead([],[]).

Third : You call greaterThan(H,T,0) with the fixed value 0 , which means you want to test if the "output" value is zero.第三:您使用固定值0调用greaterThan(H,T,0) ,这意味着您要测试“输出”值是否为零。 Which is not the case, you want to count stuff.事实并非如此,您想计算东西。 So put a variable here: N所以在这里放一个变量: N

Fourth : If you have calculated a value N you have to forward it to the outputlist.第四:如果您计算了一个值N您必须将其转发到输出列表。 Since you will get the list Nlist from your recursive call, you can create a new list with N as the head element and Nlist as the tail and "return" this new list.由于您将从递归调用中获得列表Nlist ,因此您可以创建一个以N作为头元素、 Nlist作为尾元素的新列表,然后“返回”这个新列表。

Conclusion:结论:

testHead([],[]).
testHead([H|T],[N|Nlist]) :-
    greaterThan(H,T,N),
    testHead(T,Nlist).

Sadly we can not test it yet, we have to have a look at greaterThan/3 .遗憾的是,我们还不能测试它,我们必须看看greaterThan/3 Your snippet is the following:您的代码段如下:

greaterThan(H,[X|T],C) :-
    H > X ->
    C2 is C+1,
    greaterThan(H,T,C2);
    greaterThan(H,T,C).

And also here are some parts odd.还有一些奇怪的部分。

First : You need to tell when to stop.第一:你需要告诉什么时候停止。 Usually you stop with the empty list [] or if the list has only one element left [A] .通常你会看到空列表[]或者列表只剩下一个元素[A] If you are not interested in the content of A you use a "throw away variable" which starts with an underscore _ .如果您对A的内容不感兴趣,则可以使用以下划线_开头的“丢弃变量”。 This results in: greaterThan(_,[],0) .这导致: greaterThan(_,[],0) Which means: if my list is empty, there are 0 numbers greater in my list, no matter what the refence value was.这意味着:如果我的列表为空,则无论参考值是多少,我的列表中都会有 0 个更大的数字。 Also since the order of rules matters you put this on top of your recursion rule.此外,由于规则的顺序很重要,因此您将其置于递归规则之上。

Second : You got the cases right, so if H is larger than the head X of the list do something , otherwise "ignore" X by just calling the same predicate without X .第二:你的情况是正确的,所以如果H大于列表的头部X一些事情,否则“忽略” X通过只调用没有X的相同谓词。 The problem appears in the something part: since the value of C2 is unificated before C you need to calculate C depending on C2 and not vice versa.这个问题出现在什么部分:因为价值C2之前unificated C你需要计算C取决于C2 ,而不是相反。 C is C2+1 means: I know the value C2 from the recursion call and since H>X I want to add one to its value and "return" it. C is C2+1意味着:我从递归调用中知道值C2并且由于H>X我想为其值加一并“返回”它。

Third : You know the value of C2 just after asking greaterThan(H,T,C2) , so put the C is C2+1 after it.第三:在询问greaterThan(H,T,C2)之后你就知道C2的值,所以在它后面加上C is C2+1

Ok, now we got:好的,现在我们得到了:

greaterThan(_,[],0).
greaterThan(H,[X|T],C) :-
    H > X ->
    greaterThan(H,T,C2),
    C is C2+1;
    greaterThan(H,T,C).

testHead([],[]).
testHead([H|T],[N|Nlist]) :-
    greaterThan(H,T,N),
    testHead(T,Nlist).

Lets test it!让我们测试一下!

?- testHead( [7,2,4,3,6,9,8,10,12,5],L).
L = [5, 0, 1, 0, 1, 2, 1, 1, 1, 0] ;
false.

Looks good besides that you don't want a list but a total number.看起来不错,除了你不想要一个列表而是一个总数。 Ok, here you go:好的,给你:

testHead([],0).
testHead([H|T],New) :-
    greaterThan(H,T,N),
    testHead(T,NN),
    New is NN+N.

?- testHead( [7,2,4,3,6,9,8,10,12,5],N).
N = 12 ;
false.

Explanation: if your input list is empty, there is nothing to be done, "return" the neutral element for addition: 0 .说明:如果您的输入列表为空,则无事可做,“返回”要添加的中性元素: 0
If your inputlist has a head element H , calculate the "greater as N remaining elements" through greaterThan(H,T,N) .如果您的输入列表有一个头元素H ,则通过greaterThan(H,T,N)计算“大于N剩余元素”。 Assume your code works so you can call testHead(T,NN) for your tail list T and get the sum value NN .假设您的代码有效,因此您可以为尾列表T调用testHead(T,NN)并获得总和值NN If both values N and NN are known, add them and state it as the "return".如果值NNN都已知,则添加它们并将其声明为“返回”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM