Prolog:以声明方式创建列表的 DRY 方式

发布于 2024-12-09 21:27:34 字数 660 浏览 0 评论 0原文

我正在使用 Prolog 进行一些实验,但遇到以下规则的困难:

row(Row, Matrix, [R1,R2,R3,R4]) :-
  cell(1, Row, Matrix, R1),
  cell(2, Row, Matrix, R2),
  cell(3, Row, Matrix, R3),
  cell(4, Row, Matrix, R4).

该规则根据给定的行号从矩阵中提取一行。例如,

row(2, [1,2,3,4,5,6,7,8], X)
 X = [5,6,7,8]

让我烦恼的是该代码中有很多重复。处理完 4x4 矩阵后,我将不得不处理 9x9 矩阵。而且代码可能会变得非常不干燥。

有没有办法提取重复的内容?

谢谢。

编辑:给我带来麻烦的完整代码在这里: https://github.com/kikito/7-languages-in-7-weeks/blob/master/3-prolog/day-3/sudoku-refactor.pl

I'm doing some experiments with Prolog and having difficulties with the following rule:

row(Row, Matrix, [R1,R2,R3,R4]) :-
  cell(1, Row, Matrix, R1),
  cell(2, Row, Matrix, R2),
  cell(3, Row, Matrix, R3),
  cell(4, Row, Matrix, R4).

This rule extracts one row from a matrix, given its row number. For example,

row(2, [1,2,3,4,5,6,7,8], X)
 X = [5,6,7,8]

What nags me is that there is lots of repetition in that code. After finishing with 4x4 matrices, I will have to deal with 9x9 ones. And the code can get very non DRY.

Is there a way to extract that repetition out?

Thanks.

Edit: The complete code giving me trouble is here: https://github.com/kikito/7-languages-in-7-weeks/blob/master/3-prolog/day-3/sudoku-refactor.pl

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

断桥再见 2024-12-16 21:27:34

写完第一个答案后,我意识到您还可以使用 findall 简化您的程序

 row(Row, Matrix, L) :- findall(X,cell(_,Row,Matrix,X),L).

After writing my first answer, I realized that you can also simplify your program using findall

 row(Row, Matrix, L) :- findall(X,cell(_,Row,Matrix,X),L).
独﹏钓一江月 2024-12-16 21:27:34

我会考虑将表示形式更改为列表列表而不是平面列表,然后选择一行变得非常容易。您可以只使用内置的 nth1/3:

 :- use_module(library(lists)). % I use Sicstus Prolog
 row(N,M,X) :- nth1(N,M,X).
 cell(R,C,M,X) :- nth1(R,M,Y), nth1(C,Y,X).
 column(N,M,X) :- findall(Y,(nth1(_,M,Z), nth1(N,Z,Y)),X).

 m([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]).
 example(Row,Cell,Column) :- m(M), row(2,M,Row), cell(2,3,M,Cell), column(2,M,Column).

 %| ?- example(A,B,C).
 %A = [5,6,7,8],
 %B = 7,
 %C = [2,6,10,14] ? ;
 %no

I would think about changing the representation to a list of lists rather than a flat list, then selecting a row becomes very easy. You can just use the built-in nth1/3:

 :- use_module(library(lists)). % I use Sicstus Prolog
 row(N,M,X) :- nth1(N,M,X).
 cell(R,C,M,X) :- nth1(R,M,Y), nth1(C,Y,X).
 column(N,M,X) :- findall(Y,(nth1(_,M,Z), nth1(N,Z,Y)),X).

 m([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]).
 example(Row,Cell,Column) :- m(M), row(2,M,Row), cell(2,3,M,Cell), column(2,M,Column).

 %| ?- example(A,B,C).
 %A = [5,6,7,8],
 %B = 7,
 %C = [2,6,10,14] ? ;
 %no
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文