8 瓶水 2 瓶有毒 6 个耗子 的解

2021-04-21 01:09:53 +08:00
 noe132

原帖: https://www.v2ex.com/t/771969

很抱歉在原帖 1 楼发了一个错误的答案,想的太快导致逻辑出了 bug 。

8 选 2 一共 28 种可能的组合。由于毒药混合只要有一瓶是毒药,结果则是毒药,属于逻辑或运算,不符合二进制与的条件,所以我们不混合 8 选 2,而是混合选出来后剩下的 6 瓶,8 选 6 。这样混合出来的 28 瓶里只有 1 瓶是无毒的,再根据 5 位 2 进制编码,给 5 只老鼠喝,就能找到哪一瓶有毒了。

下面是 js 写的一个验证。随机从 water 数组里投毒 2 瓶,然后根据上面的方式计算结果并 log 出来。可以直接在浏览器控制台运行。

(() => {
  let water = [
    [0, false],
    [1, false],
    [2, false],
    [3, false],
    [4, false],
    [5, false],
    [6, false],
    [7, false],
  ]

  // 随机投毒 2 瓶
  let pCount = 0;
  while (pCount < 2) {
    const index = Math.floor(Math.random() * 8)
    if (!water[index][1]){
      water[index][1] = true
      pCount += 1
    }
  }

  const poisonous = water.filter(v => v[1]).map(v => v[0]).join(', ')
  console.log('投毒了: ', poisonous)

  const mix = []
  
  for (let no = 0, i = 0; i < water.length; i += 1) {
    for (let j = i + 1; j < water.length; j += 1) {
      mix.push({
        no,
        bottle: [water[i], water[j]],
        harmless: water[i][1] && water[j][1],
      })
      no += 1;
    }
  }

  const mix2 = []

  for (let i = 0; i < 5; i += 1) {
    const key = 2 ** i
    const mix2Item = mix.filter(v => Boolean(key & v.no))
    const isHarmless = mix2Item.some(v => v.harmless)
    mix2.push({
      i,
      isHarmless,
    })
  }

  const resultNumber = mix2.filter(v => v.isHarmless).map(v => 2 ** v.i).reduce((p, c) => p + c)

  const resultPoisonous = mix[resultNumber].bottle.map(v => v[0]).join(', ')
  console.log('计算出来投毒了: ', resultPoisonous)
})()

题外,可以思考一下,如果不是固定 2 瓶毒药,而是可能是 0/1/2 瓶,这个应该如何解?

1396 次点击
所在节点    问与答
11 条回复
noe132
2021-04-21 01:10:38 +08:00
@zxCoder @yxt @hm20062006ok @AndyVerne @Elethom
抱歉又 @ 了一次~这次算是想明白了
mikeguan
2021-04-21 01:21:50 +08:00
123 -1
234 -2
345 -3
456 -4
567 -5
678 -6
这样应该可以判断那两瓶有问题
mikeguan
2021-04-21 01:24:44 +08:00
@mikeguan #2 想错了,这样不行
mikeguan
2021-04-21 01:26:27 +08:00
感觉又可以的样子,算了不看了
noe132
2021-04-21 01:26:30 +08:00
@mikeguan 这个不行的。简单的例子,13 有毒和 23 有毒按照你的混和后,结果都是 1 2 3 三瓶有毒。
snw
2021-04-21 02:29:04 +08:00
28 瓶中只有 1 瓶没毒,但 5 只老鼠每只至少要喝 2 瓶,那么结果总是全死啊,你怎么判断?
noe132
2021-04-21 02:38:46 +08:00
@snw 是的,这个解有问题。
iceheart
2021-04-21 08:13:24 +08:00
两只老鼠就够了吧,不死就继续用
z1113456051
2021-04-21 09:35:18 +08:00
算上自己就够了
mzlzero
2021-04-21 15:32:10 +08:00
@iceheart 要求单次出结果,就是只做一轮,6 只一起喝
iceheart
2021-04-22 09:09:44 +08:00
有两瓶有毒,这个条件信息量有两个 bit 吗?我觉得不太可能。
化简: 三个瓶子两个有毒,一只老鼠测一次

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/772034

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX