1

我需要编写一个 Prolog 谓词来检查:

  1. 如果行上的所有矩阵元素都是奇数,程序应该在行的末尾添加1
  2. 如果行中有 1 个或多个偶数,程序应在行尾添加0
?- f([[1,2,3],[5,5,5],[4,4,4]], Xss).
Xss = [[1,2,3,0],[5,5,5,1],[4,4,4,0]].  

这就是我现在所拥有的:

f([],[]).
f(matrix,Xss).
f([Xs|T],Xss):-
    Xs=[X|T2],
(X mod 2 =:= 0 ->
add2end(0,[X|T2],[X|Result]):-
add2end(0,T2, Result),
add2end(0,[],[0]), Xss=[Xs|T] ;
   add2end(1,[X|T2],[X|Result]):-
add2end(1,T2,Result),
    add2end(1,[],[1])), Xss=[Xs|T]..
4

2 回答 2

2

clpfd和Prolog lambdas问题!

:- use_module(library(lambda)).
:- use_module(library(clpfd)).

我们f/2基于 maplist/3sum/3(#=)/2和定义append/3

f(Xss,Yss) :-
   maplist(\Xs^Ys^(sum(Xs,#=,S),P #= S mod 2,append(Xs,[P],Ys)), Xss, Yss).

示例查询:

?- f([[1,2,3],[5,5,5],[4,4,4]], Xss)。
Xss = [[1,2,3, 0 ], [5,5,5, 1 ], [4,4,4, 0 ]]。% 确定性地成功   
于 2015-08-19T10:01:34.593 回答
0

你可以这样做:

f([], []).
f([Row|Matrix], [NRow|NMatrix]):-
  f(Row, 1, NRow),
  f(Matrix, NMatrix).

f([], LastElem, [LastElem]).
f([Elem|Row], CurLastElem, [Elem|NRow]):-
  Elem mod 2 =:= 0 -> f(Row, 0, NRow) ; f(Row, CurLastElem, NRow).

过程f/2将递归计算(并添加)每行的最后一个元素的行。第一个子句是结束递归的基本情况。第二个子句将调用一个辅助过程f/3,其中第一个参数将是要计算的行,第二个参数是最后一个元素的当前值,第三个参数将保存结果。

辅助过程的第一个子句f/3处理每一行的基本情况。它将当前 LastElement 添加到行中。第二个子句测试行首,看它是偶数还是奇数。如果是偶数,则当前 LastElement 设置为零并继续递归。如果元素是奇数,那么它将继续递归,保持当前 LastElement 不变。

如果您注意到当您在一行中看到一个偶数元素时,则可以优化此过程,那么实际上不需要继续递归,f/3因为您知道最后一个元素将为 0...但是该优化保留为锻炼 ;)

于 2012-08-20T15:53:46.207 回答