太好玩了,用JS求解趣味数学题!

386 阅读3分钟

今天看到一道趣味数学题:

在数字 123456789 之间填加减号(也可以不填,这个时候就任务相邻的数字拼成了多位数),使得运算结果等于100。例如:

  • 12 + 3 - 4 + 5 + 67 + 8 + 9 = 100
  • 1 + 2 + 3 - 4 + 5 + 6 + 78 + 9 = 100
  • 1 + 23 - 4 + 56 + 7 + 8 + 9 = 100

你能找出多少个这样的等式?

看完之后,真心觉得这道题有点意思,好奇心和好胜心马上就上来了。作为一名程序员,这种问题怎么可能难得住我呢!经过深入思考,觉得这道题完全可以用 JS 进行暴力枚举,因为:

1~9 之间总共有8个位置,可以填入+号,-号,或者空字符串,也就是说最多有 3 的 8 次方种可能性。

用 JS 算了一下:

console.log(Math.pow(3, 8)) // 用内置的 Math 库提供的函数计算得到 6561
console.log(3 ** 8) // 用 ** 运算符计算得到 6561

心想:总数才这么一点大,简直不要太简单,我只要拼好公式字符串,然后用强大的 eval函数计算一下不就行了么?如下图所示:

说干就干!首先定义两个数组变量:

const numbers = '123456789'.split('') // 保存数字序列
const symbols = ['+', '-', ''] // 保存数字之间的连接符号

再定义一个全局 formulas 数组保存所有的计算公式:

let formulas = [] // 保存公式

然后从 1 开始逐步累加到 9,什么意思呢?例如 formulas 的初始值是 ['1'] ,那么下一步就会变成:

  • ['1+2']
  • ['1-2']
  • ['12']

那再下一步就会变为:

  • ['1+2+3']
  • ['1+2-3']
  • ['1+23']
  • ['1-2+3']
  • ['1-2-3']
  • ['1-23']
  • ['12+3']
  • ['12-3']
  • ['123']

第 1 步数组里面是 1 个元素,第 2 步就是 3 个,第 3 步就是 9 个元素,以此类推,第 N 步就是 3^(N-1) 个元素,我们只需要走 8 步就行了,也就是 3^8 = 6561 个元素,打印结果如下:

控制台打印数组的时候,默认最多打印 100 个元素,剩下的在点点点(…)里面

按照上面的解题思路,最终的代码如下:

const numbers = '123456789'.split('')
const symbols = ['+', '-', '']
let formulas = []

function increase(number) {
  if (number === '1') return (formulas = ['1'])
  let arr = []
  for (let i = formulas.length; i; i--) {
    const lastFormula = formulas[i - 1]
    for (let j = symbols.length; j; j--) {
      let symbol = symbols[j - 1]
      arr.push(lastFormula + symbol + number)
    }
  }
  formulas = arr
}
numbers.forEach((number) => increase(number))
// 打印全部公式
// console.log(formulas)
// 打印和为100的公式
console.log(formulas.filter((it) => eval(it) === 100))

最后得到 11 个这样的等式:

  • 1 + 23 - 4 + 5 + 6 + 78 - 9
  • 1 + 23 - 4 + 56 + 7 + 8 + 9
  • 1 + 2 + 3 - 4 + 5 + 6 + 78 + 9
  • 1 + 2 + 34 - 5 + 67 - 8 + 9
  • 123 + 45 - 67 + 8 - 9
  • 123 + 4 - 5 + 67 - 89
  • 123 - 45 - 67 + 89
  • 123 - 4 - 5 - 6 - 7 + 8 - 9
  • 12 - 3 - 4 + 5 - 6 + 7 + 89
  • 12 + 3 + 4 + 5 - 6 - 7 + 89
  • 12 + 3 - 4 + 5 + 67 + 8 + 9

是不是很有意思呢?大家自己动手试一下吧,如果有更简单优雅的代码,可以直接分享到评论里面!

本文正在参加「金石计划 . 瓜分6万现金大奖」