为什么这个递归的Prolog谓词会在列表中添加一些类似"_1508"的数字?



我的任务是将给定的排序列表(LSorted(拆分为其他几个列表,其中第一个列表将包含LSorted中小于第一个素数的值(1不被视为素数(,第二个将包含来自LSorted的小于第二素数但大于或等于第一素数的值,等等

ans(L, Res):-
max_list(L, X),             /*determine the max value X of L*/
listPrimes(X, Primes),      /*generate a list of primes up to X and the prime greater than X*/
msort(L, LSorted),          /*sort L*/
ans_recur(LSorted, Primes, Res),!.
ans_recur([], _, [[]|[]]).
ans_recur([InH|Input], [PrimeH|Primes], [[InH|Res]|ResT]):-
InH < PrimeH,
ans_recur(Input, [PrimeH|Primes], [Res|ResT]).
ans_recur([InH|Input], [_|Primes], [_|ResT]):-
ans_recur([InH|Input], Primes, ResT).

当我运行一个查询:ans([1,2,3,4], L).时,我得到的结果是:

L = [_1508, [1|_1522], [2|_1534], [3, 4]],而我期望[[1], [2], [3,4]]。该程序确实将数字"放入"正确"列表中,但添加了一些值,如_1508。据我所知,原因是Prolog试图在ans_recur谓词中为Res赋值,但它为什么要这样做
跟踪:

Call:ans([1, 1, 2, 2, 3, 4], _13636)
Call:lists:max_list([1, 1, 2, 2, 3, 4], _14050)
Exit:lists:max_list([1, 1, 2, 2, 3, 4], 4)
Call:listPrimes(4, _14080)
Exit:listPrimes(4, [1, 2, 3, 5])
Call:sort([1, 1, 2, 2, 3, 4], _14224)
Exit:sort([1, 1, 2, 2, 3, 4], [1, 2, 3, 4])
Call:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], _13636)
Call:1<1
Fail:1<1
Redo:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], _13636)
Call:ans_recur([1, 2, 3, 4], [2, 3, 5], _14156)
Call:1<2
Exit:1<2
Call:ans_recur([2, 3, 4], [2, 3, 5], [_14174|_14168])
Call:2<2
Fail:2<2
Redo:ans_recur([2, 3, 4], [2, 3, 5], [_14174|_14168])
Call:ans_recur([2, 3, 4], [3, 5], _14168)
Call:2<3
Exit:2<3
Call:ans_recur([3, 4], [3, 5], [_14204|_14198])
Call:3<3
Fail:3<3
Redo:ans_recur([3, 4], [3, 5], [_14204|_14198])
Call:ans_recur([3, 4], [5], _14198)
Call:3<5
Exit:3<5
Call:ans_recur([4], [5], [_14234|_14228])
Call:4<5
Exit:4<5
Call:ans_recur([], [5], [_14252|_14228])
Exit:ans_recur([], [5], [[]])
Exit:ans_recur([4], [5], [[4]])
Exit:ans_recur([3, 4], [5], [[3, 4]])
Exit:ans_recur([3, 4], [3, 5], [_14204, [3, 4]])
Exit:ans_recur([2, 3, 4], [3, 5], [[2|_14204], [3, 4]])
Exit:ans_recur([2, 3, 4], [2, 3, 5], [_14174, [2|_14204], [3, 4]])
Exit:ans_recur([1, 2, 3, 4], [2, 3, 5], [[1|_14174], [2|_14204], [3, 4]])
Exit:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], [_14154, [1|_14174], [2|_14204], [3, 4]])
Exit:ans([1, 1, 2, 2, 3, 4], [_14154, [1|_14174], [2|_14204], [3, 4]])
L = [_1282, [1|_1296], [2|_1308], [3, 4]]

提前谢谢。

ans_recur([InH|Input], [PrimeH|Primes], [[InH|Res]|ResT]):-
InH < PrimeH,
ans_recur(Input, [PrimeH|Primes], [Res|ResT]).
ans_recur([InH|Input], [_|Primes], [_|ResT]):-
ans_recur([InH|Input], Primes, ResT).

你想在这些条款中表达的内容是这样的:

  • 如果InH小于下一个素数,它应该是当前运行结果的一部分
  • 否则,它应该是稍后运行结果的一部分

但在最后一种情况下,"当前运行结果"已经完成,它没有更多元素。因此,它的尾巴,迄今为止是开放的,必须关闭。您需要相应地更改最后一个条款的标题:

ans_recur([InH|Input], [_|Primes], [[]|ResT]):-

现在的行为如下:

?- ans_recur([1,2,3,4,5,6,7,8,9,10], [2,3,5,7,11], Result).
Result = [[1], [2], [3, 4], [5, 6], [7, 8, 9, 10]] ;
Result = [[1], [2], [3, 4], [5], [6, 7, 8, 9|...]] ;
Result = [[1], [2], [3, 4], [], [5, 6, 7, 8|...]] ;
Result = [[1], [2], [3], [4, 5, 6], [7, 8, 9, 10]] .  % further incorrect answers

问题是,你没有明确地表达"否则"的条件,Prolog也不会隐含地猜测这就是你的意思。您可以将最后一个子句更改为:

ans_recur([InH|Input], [PrimeH|Primes], [[]|ResT]):-
InH >= PrimeH,
ans_recur([InH|Input], Primes, ResT).

只得到预期的答案:

?- ans_recur([1,2,3,4,5,6,7,8,9,10], [2,3,5,7,11], Result).
Result = [[1], [2], [3, 4], [5, 6], [7, 8, 9, 10]] ;
false.

正如您所看到的,我只处理了您对ans_recur/3的实现。代码的其余部分可能会有更多的错误。我们无法判断,因为您发布的代码不完整。以后,请只发布完整的程序。许多贡献者不会费心为你完成问题,你得到的答案也会更少。

最新更新