我有很多事实代表一个单元格,其中包含行,列和某个单元格中的数字。我想检查这些事实,就像检查正常数组一样。
我试过这个功能,但它似乎不起作用,我认为我没有检查所有的事实。
allcolored(X,Y) :-
cell(X,Y,_),
X1 is X - 1,
Y1 is Y - 1,
allcolored(X1,Y1).
答案 0 :(得分:0)
如果我理解正确,你想检查一对X / Y坐标,这些坐标所跨越的网格中的所有位置都被cell/3
个事实所覆盖。为了论证,让我们考虑目前存在以下事实:
cell(1,1,100).
cell(1,2,200).
cell(1,3,300).
cell(2,1,110).
cell(2,2,120).
cell(2,3,130).
查看您对递归规则的尝试,尝试检查对于给定对,是否说2/2,对于2/2对是否有事实cell/3
1/1。但是你可能想要来检查是否覆盖了以下对:2 / 2,1 / 2,2 / 1和1/1。正如您在此序列中所看到的,X坐标减少到1,然后Y坐标减小,而X坐标再次从2开始。所以你需要以某种方式保留X的原始值。这可以通过带有附加参数的辅助谓词来完成。您的谓词allcolored/2
将成为此类谓词的调用谓词,我们称之为allcolored_/3
:
allcolored(X,Y) :-
allcolored_(X,Y,X).
正如@lurker已经指出的那样,你的谓词缺少一个基本情况,递归可以停止。一个显而易见的候选者是1/1:
allcolored_(1,1,_) :-
cell(1,1,_).
然后需要一条规则来描述X和2之间的所有值必须由cell/3
覆盖:
allcolored_(X,Y,Max) :-
cell(X,Y,_),
X > 1,
Y >= 1,
X0 is X-1,
allcolored_(X0,Y,Max).
当X达到1时,还有一个额外的规则来描述下一个较低Y坐标的变化:
allcolored_(1,Y,Max) :-
cell(1,Y,_),
Y > 1,
Y0 is Y-1,
allcolored_(Max,Y0,Max).
现在,您可以测试由您提供的坐标跨越的网格是否被事实cell/3
覆盖:
?- allcolored(2,2).
true ;
false.
?- allcolored(2,3).
true ;
false.
?- allcolored(3,3).
false.
请注意,上面的代码假设网格中的最小坐标是1.要更改它,例如0,您必须将目标X >1
,Y >= 1
和Y > 1
中的1替换为0。另请注意,由于目标的排序(首先是cell/3
目标),您还可以提出问题,例如 cell/3
的事实涵盖哪些网格? :
?- allcolored(X,Y).
X = Y, Y = 1 ;
X = 2,
Y = 1 ;
X = Y, Y = 2 ;
X = 2,
Y = 3 ;
X = 1,
Y = 2 ;
X = 1,
Y = 3 ;
false.
答案 1 :(得分:0)
不检查范围内每个索引对的事实是否存在,而是检查某些对不存在的事实是否存在范围内的指数:
allcolored(X,Y) :-
\+ (between(1,X,A), between(1,Y,B), \+ cell(A,B,_)).
这说明:allcolored(X,Y)
在允许范围(A, B
,1..X
)中没有索引1..Y
的情况下成立cell(A,B)
存在。
换句话说,“给定区域中没有空单元格”与相同,“给定区域中的所有单元格都已满”。