Prolog:计算列表列表的索引

时间:2017-11-22 02:41:12

标签: prolog

我是初学者。我想实现一个名为high / 3的预测。此预测支持两种情况:一种是返回列表列表中一个字符的索引,例如:

high([[a,b,c],[d,e,f], [g,h]], b, X) returns X = 1
high([[a,b,c],[d,e,f], [g,h]], f, X) returns X = 2

第二种情况是,如果您提供索引,它还应返回该索引位置的所有字符。
e.g。

high([[a,b,c],[d,e,f], [g,h]], X, 1) returns X = b; X= e; X= h
high([[a,b,c],[d,e,f], [g,h]], X, 2) returns X = c; X= f.

我写了以下预告:

high([[X|_]|L], X, 0).
high([[Head|Tail]|L], X, H):- member(X, Tail), high([Tail|L], X, H1),H is H1 + 1.
high([[Head|Tail]|L], X, H):- not(member(X, Tail)), high(L, X, H).

此预测仅适用于第一种情况,但对于第二种情况不起作用。

如果我运行high([[a,b,c],[d,e,f], [g,h]], X, 1),它只返回X = b,但我希望它一个接一个地返回b,e,h。

为什么它只返回b而失败?

2 个答案:

答案 0 :(得分:2)

在不同列表中存在相同元素的情况下,它应该做些什么有点不清楚。不过,这是我使用library(clpfd)

的解决方案
:- use_module(library(clpfd)).

high([H|_], X, I) :-
    high_(H, X, I, 0).
high([_|T], X, I) :-
    high(T, X, I).

high_([X|_], X, I, I).
high_([_|T], X, I, J) :-
    J #>= 0,
    J #=< I,
    J1 #= J + 1,
    high_(T, X, I, J1).

这有以下行为:

?- high([[a,b,c],[d,e,f],[g,h]], b, I).
I = 1 ;
false.

?- high([[a,b,c],[d,e,f],[g,h]], f, I).
I = 2 ;
false.

?- high([[a,b,c],[d,e,f],[g,h]], X, 1).
X = b ;
X = e ;
X = h ;
false.

?- high([[a,b,c],[d,e,f],[g,h]], X, 2).
X = c ;
X = f ;
false.

但是当有重复时也有效:

?- high([[a,a],[b,a]], a, X).
X = 0 ;
X = 1 ;
X = 1 ;
false.

有未知的子列表:

?- high([A,B], X, 2).
A = [_4552, _4558, X|_4566] ;
B = [_4552, _4558, X|_4566] ;
false.

列出未知列表:

?- high(L, X, 2).
L = [[_4518, _4524, X|_4532]|_4514] ;
L = [_4512, [_4524, _4530, X|_4538]|_4520] ;
L = [_4512, _4518, [_4530, _4536, X|_4544]|_4526] ;
…

答案 1 :(得分:1)

只返回一个结果,因为只要not(member(X, Tail))未与任何内容统一(X不为空),Tail将永远不会为真。换句话说,由于第二个子句成功,第三个子句不能,并且递归不会继续处理以下列表。

但是,我会说你的方式错了。如果多个子列表中存在元素,则当前代码也会给出错误的输出。

您可以将问题分解为更小的部分:您需要能够在单个简单列表中将其索引与元素相关联;并且您需要能够对总列表中的所有子列表进行评估。

首先要做的事情是:将索引与元素联系起来:

index([X|_], X, 0).
index([_|T], X, I) :- index(T, X, I2), I is I2 + 1.

非常简单易懂,对吧?

现在递归所有列表并匹配其中的所有元素/索引:

high([H|_], X, I) :- index(H, X, I).
high([_|T], X, I) :- high(T, X, I).

这将给出所有预期的输出:

?- high([[a,b,c],[d,e,f], [g,h]], b, X)
X = 1;
false.

?- high([[a,b,c],[d,e,f], [g,h]], f, X)
X = 2;
false.

high([[a,b,c],[d,e,f], [g,h]], X, 1).
X = b;
X = e;
X = h;
false.

high([[a,b,c],[d,e,f], [g,h]], X, 2).
X = c;
X = f;
false.