美文网首页PHP经验分享
用php暴力破解一个逻辑推理题

用php暴力破解一个逻辑推理题

作者: 小牛_6666 | 来源:发表于2019-09-25 20:28 被阅读0次

这是一个无聊的事情
由于很无聊,就刷牛客网的智力题,遇到一个逻辑推理题,然后我就和这个题杠上了。

请看题:

前提:

1 有五栋五种颜色的房子
2 每一位房子的主人国籍都不同
3 这五个人每人只喝一种饮料,只抽一种牌子的香烟,只养一种宠物
4 没有人有相同的宠物,抽相同牌子的香烟,喝相同的饮料

提示:

1  英国人住在红房子里
2  瑞典人养了一条狗
3  丹麦人喝茶
4  绿房子在白房子左边
5  绿房子主人喝咖啡
6  抽PALL MALL烟的人养了一只鸟
7  黄房子主人抽DUNHILL烟
8  住在中间那间房子的人喝牛奶
9  挪威人住第一间房子
10 抽混合烟的人住在养猫人的旁边
11 养马人住在抽DUNHILL烟的人旁边
12 抽BLUE MASTER烟的人喝啤酒
13 德国人抽PRINCE烟
14 挪威人住在蓝房子旁边
15 抽混合烟的人的邻居喝矿泉水
问题是:谁养鱼???
浪费了我几张纸,累死无数脑细胞,推到吐血,也没推出来,没办法只能使出我的杀手锏(世界上最好的语言)

分析:

5栋房子,5个国籍,5种颜色,5种饮料,5种香烟,5种宠物
暴力破解的第一步就是要把所有的组合列出来吧,也可以大概估算出电脑能不能抗的住
5栋房子就简单的用1,2,3,4,5来顺序排列吧
5种颜色的全组合有多少种呢?初中老师教过,是5的阶乘,也就是5 * 4 * 3 * 2 * 1=120
房子是固定的,剩余有5个变量,也就是一共有120的5次方个组合,也就24883200000组合,我那用了八年的破电脑还是能抗住的。
把所有组合列出来之后,就循环,按照提示进行排除

代码分析

1,生成120种排列组合

function create()
{
    $arr = [];
    $range = [1, 2, 3, 4, 5];
    for ($i = 12345; $i <= 54321; $i++) {
        $tmp = str_split($i);
        if (count(array_diff($range, $tmp)) == 0) {
            $arr[] = $tmp;
        }
    }
    return $arr;
}

这里用的是最简单暴力的方法,就不多解释了
2,怎么来标记这些组合呢,先来组合一下颜色

$arr = create();
foreach ($arr as $k => $v) {
    $color['红'] = $v[0];
    $color['白'] = $v[1];
    $color['绿'] = $v[2];
    $color['黄'] = $v[3];
    $color['蓝'] = $v[4];
   ...
}

这个是把颜色作为键名,房子的位置作为键值,生成的$color大概就是这个样子

$color=[
  '红'=>2, 
  '白'=>1,
  '绿'=>3,
  '黄'=>5,
  '蓝'=>4,
];

其他几个变量也用这种来标记
3,逻辑判断,这里是比较关键的一步,由于用排除法来判断,所以条件都要取返,不符合条件的就continue,换下一种组合

1,英国人住在红房子里

 if ($county['英国'] != $color['红']) {
            continue;
 }

如果英国人房子的位置和红色房子的位置不一样,就排除,跳过去

4,绿房子在白房子左边

 if ($color['白'] - $color['绿'] != 1) {
            continue;
  }

房子从左往右排的,绿的在白的左边,也就是绿的位置比白的位置小1

8,住在中间那间房子的人喝牛奶

 if ($drink['牛奶'] != 3) {
          continue;
}

这就比较简单了,中间的房子位置编号是3,所以喝牛奶的房子位置必须是3

10,抽混合烟的人住在养猫人的旁边

旁边的话要么是位置大1,要么是位置小1,但肯定位置差的绝对值是1

if (abs($smoke['混合'] - $pet['猫']) != 1) {//10
                    continue;
 }

抽混合烟的人与养猫人的位置相差1
大概就是这几种判断了
到这里思路应该就清晰了,剩下的只是敲键盘了,代码如下:

/**
 * 生成排列组合
 */
function create()
{
    $arr = [];
    $range = [1, 2, 3, 4, 5];
    for ($i = 12345; $i <= 54321; $i++) {
        $tmp = str_split($i);
        if (count(array_diff($range, $tmp)) == 0) {
            $arr[] = $tmp;
        }
    }
    return $arr;
}

$arr = create();
foreach ($arr as $k1 => $v1) {
    $county['英国'] = $v1[0];
    $county['瑞典'] = $v1[1];
    $county['丹麦'] = $v1[2];
    $county['挪威'] = $v1[3];
    $county['德国'] = $v1[4];
    if ($county['挪威'] != 1) {//9
        continue;
    }
    foreach ($arr as $k2 => $v2) {
        $color['红'] = $v2[0];
        $color['白'] = $v2[1];
        $color['绿'] = $v2[2];
        $color['黄'] = $v2[3];
        $color['蓝'] = $v2[4];
        if ($county['英国'] != $color['红']) {//1
            continue;
        }
        if ($color['白'] - $color['绿'] != 1) {//4
            continue;
        }
        if (abs($county['挪威'] - $color['蓝']) != 1) {//14
            continue;
        }
        foreach ($arr as $k3 => $v3) {
            $pet['鱼'] = $v3[0];
            $pet['狗'] = $v3[1];
            $pet['鸟'] = $v3[2];
            $pet['猫'] = $v3[3];
            $pet['马'] = $v3[4];
            if ($county['瑞典'] != $pet['狗']) {//2
                continue;
            }
            foreach ($arr as $k4 => $v4) {
                $smoke['混合'] = $v4[0];
                $smoke['pall'] = $v4[1];
                $smoke['dunh'] = $v4[2];
                $smoke['blue'] = $v4[3];
                $smoke['prin'] = $v4[4];
                if ($smoke['pall'] != $pet['鸟']) {//6
                    continue;
                }
                if ($color['黄'] != $smoke['dunh']) {//7
                    continue;
                }
                if (abs($smoke['混合'] - $pet['猫']) != 1) {//10
                    continue;
                }
                if (abs($pet['马'] - $smoke['dunh']) != 1) {//11
                    continue;
                }
                if ($county['德国'] != $smoke['prin']) {//13
                    continue;
                }
                foreach ($arr as $k5 => $v5) {
                    $drink['矿泉水'] = $v5[0];
                    $drink['茶'] = $v5[1];
                    $drink['咖啡'] = $v5[2];
                    $drink['牛奶'] = $v5[3];
                    $drink['啤酒'] = $v5[4];
                    if ($county['丹麦'] != $drink['茶']) {//3
                        continue;
                    }
                    if ($color['绿'] != $drink['咖啡']) {//5
                        continue;
                    }
                    if ($drink['牛奶'] != 3) {//8
                        continue;
                    }
                    if ($smoke['blue'] != $drink['啤酒']) {//12
                        continue;
                    }
                    if (abs($smoke['混合'] - $drink['矿泉水']) != 1) {//15
                        continue;
                    }
                    print_arr(compact('county', 'color', 'pet', 'smoke', 'drink'));
                }
            }
        }
    }
}

/**
 * 打印结果
 */
function print_arr($arr)
{
    foreach ($arr as $k => $v) {
        $sort = array_flip($v);
        ksort($sort);
        $tmp[] = $sort;
    }
    foreach ($tmp as $k => $v) {
        for ($i = 1; $i <= 5; $i++) {
            echo $tmp[$k][$i], "\t";
        }
        echo "\n\r";
    }
}

答案就不放了,可以自己试一下

相关文章

网友评论

    本文标题:用php暴力破解一个逻辑推理题

    本文链接:https://www.haomeiwen.com/subject/xrtvyctx.html