我意识到我写的这个就像一个家庭作业问题,但那是因为这是我理解并试图传达问题的最简单方法。这是我想要为个人项目解决的问题。
我有一个网格布局,我从一个2x2网格的简单情况开始,但希望能够最终推断到更大的n×n网格。
卡片都朝下,打印在卡片的面上是:
我获得了每行得分总和,每行黑点数,每列得分总和以及每列黑点数的信息。
所以最上面一行的总分必须为1,而且其中一张牌就是黑点。
最右边的列必须具有2的总分,并且恰好其中一个卡是黑点。
等等。
当然我们可以看到上面的网格将“解决”到
现在我想创建一个输入给定信息的函数,并生成满足这些约束的卡片网格。
我想我可以使用类似元组的参数。
然后网格中的每个“单元格”或卡片本身就是一个元组,元组的第一个元素将是那里的卡片的分数(如果是黑点则为0),如果是黑色,则第二个元素将为1卡是黑点,否则为0。
所以网格必须类似于^^
通过求解这个方程组,我可以找出所有a
,b
变量是什么:
(也知道所有这些数字都是≥0的整数)。
我想把这个问题用作prolog的学习练习,我认为这似乎是一个问题Prolog会优雅地解决。
我做出了一个好的决定还是Prolog不是一个好的选择?
我想知道如何在Prolog中实现这一点。
Prolog非常适合这类问题。看看clp(fd),即有限域中的约束逻辑编程。
这个片段显示了如何解决SWI Prolog中的初始2x2示例的原始方法:
:- use_module(library(clpfd)).
test(Vars) :-
Vars = [TopLeft, TopRight, BottomLeft, BottomRight],
global_cardinality([TopLeft, TopRight], [0-1,1-_,2-_]), TopLeft + TopRight #= 1,
global_cardinality([TopLeft, BottomLeft], [0-1,1-_,2-_]), TopLeft + BottomLeft #= 1,
global_cardinality([BottomLeft, BottomRight], [0-1,1-_,2-_]), BottomLeft + BottomRight #= 2,
global_cardinality([TopRight, BottomRight], [0-1,1-_,2-_]), TopRight + BottomRight #= 2,
label(Vars).
查询:
?- test(Vars).
Vars = [1, 0, 0, 2].
您可以将此作为起点并进行概括。请注意,黑点表示为0,因为clp(fd)仅处理整数。