繁体   English   中英

在序言中解决一个简单的难题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM