2012-01-08 29 views
1

我有以下代码:序言检查清单

check([],[]). 
check([X], [Y]) :- 
    X > 0, 
    Y is 1. 
check([X], [Y]) :- 
    X =:= 0, 
    Y is 0. 
check([L1|Tail], [L2|Tail2]) :- 
    L1 > 0, 
    L2 is 1, 
    check(Tail,Tail2). 
check([L1|Tail], [L2|Tail2]) :- 
    L1 =:= 0, 
    L2 is 0, 
    check(Tail,Tail2). 

谓词检查创建了一个表格替换所有的项目比0大到1。 这个谓词适用于这样一个简单的列表L = [3,4,5,6,0],并产生一个列表L1 = [1,1,1,1,0]

我需要进行谓词检查以接受列表作为项目列表。例如:L = [[2, 3, 4], [4, 0, 6], [5, 6, 3]]。列表中的项目与项目列表中的项目一样多。这意味着如果列表包含3个项目列表,则每个项目列表应包含3个项目。

+0

目前尚不清楚对我有什么你牛逼试图完成。您能否发布您的示例列表清单的预期输出结果? (在你原来的代码中,顺便说一句,第二和第三个谓词是多余的,可以删除) – mgibsonbr 2012-01-08 01:46:14

+0

负数呢?你的代码表明失败,你的文本表明它们保持原样。 – false 2012-10-07 22:46:43

回答

0

首先,你的第二个和第三个子句不需要,他们只是产生重复的解决方案,这里是一个更好的check/2断言:

check([],[]). 
check([L1|Tail], [L2|Tail2]) :- 
    L1 > 0, 
    L2 is 1, 
    check(Tail,Tail2). 
check([L1|Tail], [L2|Tail2]) :- 
    L1 =:= 0, 
    L2 is 0, 
    check(Tail,Tail2). 

然后,而不是使用is/2赋值给L2,您可以直接在您的条款的头部指定L2值,这样的:

check([],[]). 
check([L1|Tail], [1|Tail2]) :- 
    L1 > 0, 
    check(Tail,Tail2). 
check([L1|Tail], [0|Tail2]) :- 
    L1 =:= 0, 
    check(Tail,Tail2). 

然后,而不是使用=:=/2,你可以再次在您的第二个子句的头部直接指定的值:

现在你的check/2谓词已经看起来好多了!

让我们增加一个条款来处理列表嵌套:

check([],[]). 
check([L1|Tail], [L2|Tail2]) :- 
    L1 = [_|_], 
    check(L1, L2), 
    check(Tail, Tail2). 
check([L1|Tail], [1|Tail2]) :- 
    \+ L1 = [_|_], 
    L1 > 0, 
    check(Tail,Tail2). 
check([0|Tail], [0|Tail2]) :- 
    check(Tail,Tail2). 

正如你所看到的,我们还需要添加一个测试,L1是不是我们以前的子句中的列表,让列表不会走这条路,并产生奇怪的解决方案。

希望它有帮助。

5

对于那些在列表中的每个项目相同的关系,它往往是最好的形容关系为一个单一的元素,然后使用MAPLIST/3:

check(0, 0). 
check(N, 1) :- N > 0. 

样品查询:

?- maplist(check, [3,4,5,6,0], Ls). 
Ls = [1, 1, 1, 1, 0] ; 
false. 

现在嵌套列表的情况下转化为一个嵌套MAPLIST/3:

?- maplist(maplist(check), [[2, 3, 4], [4, 0, 6], [5, 6, 3]], Ls). 
Ls = [[1, 1, 1], [1, 0, 1], [1, 1, 1]] ; 
false.