条件:现在有1千瓶水,其中有1瓶是毒药。不能通过外观和气味等外在特征来区分毒药和水。老鼠吃了毒药或毒药和水的混合体后,1周会死亡。
问题:现在给1周的时间,用10只老鼠找出1千瓶水中的那瓶毒药。
解答往下翻
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
解答
- 将1千瓶水编上从 1 到 1千的号。
- 将编号转化成 2 进制数。如 3 就是 11。
- 将转化成 2 进制数的编号的水分成10组。将所有编号第10位是1的分在第1组,编号第9位是1的分在第2组...编号个位是1的分在第10组。因为 2 的 10 次方是 1024,大于 1千,所以毒药肯定在上面分的若干组中。
- 将上面10组各组内的水混合。最后形成10瓶水。
- 给老鼠标编上从 1 到 10的号。标号1的老鼠吃第1组混合的水,标号2的吃第2组混合的,以此类推。
- 一周后观察结果。老鼠死了记为1,没死记为0。根据观察的结果可以得到类似这样的长度是10的数据: 1(标号1的死了)0(标号2的活着)01001010。 将这个数据转化成 2进制就是毒药的编号。原因是,如果标号为n的老鼠死了,那毒药一定在第n组中,即毒药的编号的2进制数第n位一定是1,否则为0。
JavaScript 实现如下:
const poisonIndex = Math.round(Math.random() * 1000) // 随机生产毒药编号
function getPoison() {
var mixsGroupRule = []// 混合规则:第1位是1,第2位是1,第3位是1...第10位是1
var mixsGroup = [] // 根据混合规则,计算出混合组合
for(var i = 0; i < 10; i++){
mixsGroupRule.push(Math.pow(2, i))
mixsGroup.push([])
}
for(var liquidIndex = 1; liquidIndex <= 1000; liquidIndex++) {
mixsGroupRule.forEach(function (rule, index) {
(function(liquidIndex, index) {
if(!!(rule & liquidIndex)) {
mixsGroup[10 - index - 1].push(liquidIndex)
}
})(liquidIndex, index)
})
}
var mouseStatus = mixsGroup.map(each=> {
return isDead(each)
})
var resBinaryStr = mouseStatus.map(each=>{
return each ? 1 : 0
}).join('')
var resIndex = parseInt(resBinaryStr, 2)
return resIndex
}
console.log(`毒药序号:${poisonIndex}`)
console.log(`算出的毒药序号: ${getPoison()}`)
// 老鼠吃了水后的状态
function isDead(mixs) {
return mixs.indexOf(poisonIndex) !== -1
}