[英]Solving a simple puzzle in prolog
我用 C 解决了一个难题,并尝试在 Prolog 中做同样的事情,但我在用这种语言表达事实和目标时遇到了一些麻烦。
这个问题的非常简化的版本是:一个房间里有两个杠杆。 每个杠杆控制一个可以在四个不同位置(我记为 0、1、2 或 3)向前或向后移动的机构。 如果你在同一个方向上移动一个机构四次,它会和以前一样处于相同的位置。
杠杆 n°1 将机构 n°1 向前移动两个位置。 杠杆 n°2 将机构 n°2 向前移动一个位置。
最初,机构 n°1 位于位置 2,机构 n°2 位于位置 1。问题是找到将两个机构移动到位置 0 的最快方法,并获得导致每个解决方案的杠杆顺序。
当然,这里的问题是微不足道的,您只需拉动 n°1 的杆一次和拉动 n°2 的杆 3 次即可得到解决方案。
这是 C 语言中的一个简单代码,它给出了拉动拉杆的顺序,通过拉动少于 5 个拉杆来解决这个问题:
int pos1 = 2, pos2 = 1;
int main()
{
resolve(0,5);
return 0;
}
void lever1(){
pos1 = (pos1 + 2) % 4;
}
void undolever1(){
pos1 = (pos1 - 2) % 4;
}
void lever2(){
pos2 = (pos2 + 1) % 4;
}
void undolever2(){
pos2 = (pos2 - 1) % 4;
}
void resolve(l, k){
if(k == 0){
return;
}
if(pos1 == 0 && pos2 == 0){
printf("Solution: %d\n", l);
return;
}
if(k>0){
k--;
lever1();
resolve(l*10+1,k);
undolever1();
lever2();
resolve(l*10+2,k);
undolever2();
}
}
到目前为止,我在 Prolog 中的代码如下所示:
lever(l1).
lever(l2).
mechanism(m1).
mechanism(m2).
position(m1,2).
position(m2,1).
pullL1() :- position(m1, mod(position(m1,X)+2,4)).
pullL2() :- position(m2, mod(position(m2,X)+1,4)).
solve(k) :- solve_(k, []).
solve_(0, r) :- !, postion(m1, p1), postion(m2, p2), p1 == 0, p2 == 0.
solve_(k, r) :- k > 0, pullL1(), k1 is k - 1, append(r, [1], r1), solve_(k1, r1).
solve_(k, r) :- k > 0, pullL2(), k1 is k - 1, append(r, [2], r2), solve_(k1, r2).
我很确定这段代码中存在多个问题,但我不确定如何解决它。 任何帮助将非常感激。
我认为这是一个非常有趣的问题。 我想你想要一个通用的解决方案 -> 一个杠杆可以移动多个机构。 如果问题与您的一样,一个杠杆只控制一种机制,那么解决方案就很简单了。 您只需移动每个杠杆一段时间,直到该机构处于状态零。
但我想提供一个更通用的解决方案,以便一个杠杆可以移动多个机构。 但首先是一点数学。 别担心,我最终也会做一个例子。
让我们定义
作为 n 个杠杆和
是 m 机制。 然后让我们用一个向量定义每个杠杆:
在哪里是步数
移动
向前。
对于我们定义的机制:
beeing机制的偏见->所以处于初始状态
和
是每个机制的状态数量。 所以现在我们可以这样描述我们的整个系统:
哪里是我们必须激活的次数
. 如果我们想将所有机制设置为零。 如果你不熟悉
符号这只是意味着 a%m = b%m。
我们可以改写为:
其中 k 可以是任何自然数。 所以我们可以将我们的系统重写为一个方程系统:
prolog 可以为我们解出这样一个方程组。 (解决丢番图方程系统有不同的解决方案,请参见https://en.wikipedia.org/wiki/Diophantine_equation )
好的,现在让我们举个例子:假设我们有两个杠杆和三个具有 4 个状态的机制。 拳头杠杆将 M1 向前移动一个,将 M3 向前移动两个。 第二个杠杆将 M2 向前移动一个,将 M3 向前移动一个。 M1 处于状态 2。M2 处于状态 3。M3 处于状态 3。所以我们的方程系统如下所示:
在 prolog 中,我们可以使用 clpfd 库解决这个问题。
?- [library(clpfd)].
然后像这样解决:
?- X1+(-4)*K1+2 #= 0, 1*X2+(-4)*K2+3 #= 0, 2*X1+X2+(-4)*K3+3 #= 0,Vs = [X1,X2], Vs ins 0..100,label(Vs).
这给了我们解决方案
VS = [2, 1]
-> 所以 X1 = 2 和 X2 = 1 这是正确的。 Prolog可以给你更多的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.