只是为了好玩 - 开始解决一个棘手的PHP逻辑问题

时间:2011-01-31 14:47:46

标签: php logic

作为提高我作为PHP开发人员的技能的一种方法,我经常挑战自己来自网站Programming Praxis的问题。 99%的时间我自己可以解决谜语,但是我对这个问题很困惑,需要一些关于如何开始的指导。这个谜语被称为“多重住宅”。这是问题所在:

Baker,Cooper,Fletcher,Miller和Smith住在一栋只有五层楼的公寓楼的不同楼层。贝克不住在顶楼。库珀不住在底层。弗莱彻不住在顶层或底层。米勒生活在比库珀更高的楼层。史密斯不住在弗莱彻附近的地板上。弗莱彻并不住在库珀附近的地板上。每个人住在哪里?

我的基本麻烦是:我不明白如何测试和评估不同的逻辑情况。例如,如果我们想测试Baker是否属于一楼,那么如何最好地“填写”其余四个人中每个人的测试位置?我(很多)的尝试都以大量的If / else if / else树的底部沮丧而告终。

这不是作业,金钱或名气 - 只是一个谜,我可以使用一点帮助开始!

已更新 - 这是我的解决方案!感谢大家的所有输入,不一定优化但至少现在我明白了:

<?php

    function testThisOne ($testList) {
        $MillerFloor = "";
        $CooperFloor = "";
        $SmithFloor = "";
        $FletcherFloor = "";

        foreach ($testList as $key => $person) if ($person == "Miller") $MillerFloor = $key;
        foreach ($testList as $key => $person) if ($person == "Cooper") $CooperFloor = $key;
        foreach ($testList as $key =>$person) if ($person == "Smith") $SmithFloor = $key;
        foreach ($testList as $key => $person) if ($person == "Fletcher") $FletcherFloor = $key;

        if ($testList[4] == "Baker") return false;
        if ($testList[0] == "Cooper") return false;
        if ($testList[0] == "Fletcher" || $testList[4] == "Fletcher") return false;
        if ($MillerFloor < $CooperFloor) return false;
        if (abs($SmithFloor - $FletcherFloor) == 1 || abs($CooperFloor - $FletcherFloor) == 1) return false;

        return true;
    }

    function puzzleSolve1() {
        $people = array("Baker","Cooper","Fletcher","Miller","Smith");
        do {
            shuffle($people);
        } while (!testThisOne($people));
        return $people;
    }

?>

3 个答案:

答案 0 :(得分:4)

有趣的问题。由于这是一项编程挑战,我认为最好的方法是生成所有可能的人员安排,并测试他们是否正确。

由于你只是想要一个起点,我不会写任何实际的代码,我只是概述我解决它的方法:

  1. 由于所有租户都住在不同楼层,因此您需要使用“置换”算法来生成所有不同的可能安排。也就是说,你开始使用像{1, 2, 3, 4, 5}这样的集合,每个元素代表一个人的楼层数,比如按Baker,Cooper,Fletcher,Miller,Smith的顺序排列。你需要找到所有其他可能的安排。 The algorithm on wikipedia非常简单,易于实施。
  2. 对于您生成的每个排列,您需要测试所有条件是否都为真。如果任何条件为假,请停止测试并继续下一个排列。如果满足所有条件,那么你就完成了。所有条件都相当容易测试,例如:

    “贝克不住在顶楼。” &GT;&GT; $baker != 5

    “米勒生活在比库珀更高的地板上。” &GT;&GT; $miller > $cooper

    等等。

答案 1 :(得分:1)

我猜你可以把它格式化为一组线性(in)方程式。

B < 5
C > 1
F < 5
F > 1
M > C
|S - F| > 1
|F - C| > 1

这些加号:B!= C!= F!= S!= M

现在将其提供给simplex algorithm,您就完成了:)

编辑:但是如果你想以编程方式解决这个问题,我想测试这些条件的所有排列都会简单得多 - 只有5个!他们。

答案 2 :(得分:1)

所以我们打电话给B C F M S。

基本上每个人都可以住在任何地方,所以我们有这个起点:

[BCFMS] [BCFMS] [BCFMS] [BCFMS] [BCFMS]

现在你说

  

Baker不住在顶层。

所以我们有

[BCFMS] [BCFMS] [BCFMS] [BCFMS] [CFMS]
  

库珀不住在底层。

所以我们最终得到:

[BFMS] [BCFMS] [BCFMS] [BCFMS] [CFMS]
  

弗莱彻不住在顶层或底层。

Ookay:

[BMS] [BCFMS] [BCFMS] [BCFMS] [CMS]
  

米勒住在比库珀更高的楼层上。

好的,所以M不能低于C:

[BS] [BCFS] [BCFMS] [BCFMS] [CMS]

而且,C不能在最后一层,因为M必须在他之上:

[BS] [BCFS] [BCFMS] [BCFMS] [MS]
  

(A):史密斯不住在弗莱彻附近的楼层。

     

(B):弗莱彻不住在库珀附近的楼层。

所以在相邻的“盒子”(地板)上没有S-F,F-S,F-C或C-F。

我们也知道

  

(C):住在公寓的不同楼层

符合(C),我们有两种可能的情况,第一层是B或S's

让我们来看第二种情况(因为我们知道(A)关于他)

[S] [BCFS] [BCFMS] [BCFMS] [MS]

根据(A):

[S] [BC] [BCF] [BCF] [M]

所以我们也知道M生活在C之上(前一步已经是真的,因为我们知道M肯定是在最后一层):

[S] [BC] [BCF] [BCF] [M]

根据(B),F和C都不能在3楼,并且在(C)的影响下,由于进一步减少(每层只有一个人),我们最终得到唯一可能的排列:< / p>

[S] [C] [B] [F] [M]

所以这是解决方案:

Smith,Cooper,Baker,Fletcher,Miller