我编写了一个prolog程序来解决和显示类似数独的谜题的解决方案。起初,如果网格是例如4x4:,我会使用这样的东西
main:-
Matrix = [[_,_,_,_],[_,_,_,_],[_,_,_,_],[_,_,_,_]],
solve_puzzle(Matrix),
display_matrix(Matrix).
但我希望能够设置矩阵的大小,所以我写了这样的:
generate_list(N, [ ]) :-
N =< 0, !.
generate_list(N, [_ | T]) :-
N > 0,
N2 is N - 1,
generate_list(N2, T).
generate_matrix(_, N, []) :-
N =< 0, !.
generate_matrix(M, N, [R|T]) :-
generate_list(M,R),
N2 is N - 1,
generate_matrix(M, N2, T).
然后我可以做:
main:-
Rows = 4, Columns = 4,
generate_matrix(Columns,Rows,Matrix),
solve_puzzle(Matrix),
display_matrix(Matrix).
但这似乎减慢了我的程序。有没有更好的方法来生成一个N x M矩阵?
length/2
和maplist/2
的组合在这里运行良好:
length_list(N, List) :- length(List, N).
generate_matrix(Cols, Rows, Matrix) :-
length_list(Rows, Matrix),
maplist(length_list(Cols), Matrix).
我定义了length_list/2
,将长度参数放在第一位,以便在maplist/2
中使用它。
length/2
是关系型的,所以当您使用实例化的长度(比如N
)调用length/2
,但使用列表参数作为变量时,它会产生带有N
元素的[_,_, ..., _]
。因此,第一个length_list
创建了一个列表Matrix
,看起来像是长度为Rows
的[_, _, _, ..., _]
。然后,对于Matrix
的每个元素(行R
),下面的maplist/2
将调用length_list(Cols, R)
,其产生长度为Cols
的列表[_, _, ..., _]
来代替每个_
。
maplist/2
将调用第一个参数作为第二个参数(列表)的每个元素的谓词。由于我们给它length_list(Cols)
,它正在为[_, _, ..., _]
中的每个元素调用call(length_list(Cols), _)
,相当于call(length_list(Cols, _))
,它将用[_, _, ..., _]
实例化_
,一个长度为Cols
的匿名变量列表。
我使用SWI-Prolog的time/1
进行了一些快速计时检查,上面的方法看起来明显更快。