【问题标题】:Math Algorithm Challenge数学算法挑战
【发布时间】:2019-07-20 00:53:27
【问题描述】:

为什么这个解决方案有效? 大多数人都在做循环来解决这个问题,我做了递归, 但这很容易,对于计算机,我很困惑为什么会这样?

说明: 一个孩子在高楼的n层玩球。该楼层的高度 h 是已知的。

他把球扔出窗外。球弹跳(例如)到其高度的三分之二(弹跳 0.66)。

他的母亲从距离地面 1.5 米的窗户向外看。

妈妈会看到多少次球从她的窗前经过(包括它下落和弹跳的时候?

一个有效的实验必须满足三个条件: 以米为单位的浮点参数“h”必须大于 0 浮点参数“bounce”必须大于 0 且小于 1 浮点参数“window”必须小于 h。 如果以上三个条件都满足,则返回一个正整数,否则返回-1。

注意: 只有反弹球的高度严格大于窗口参数才能看到球。

export class G964 {
    public static bouncingBall(h: number, bounce: number, window: number): any {
        if (h <= 0 || bounce >= 1 || bounce <= 0 || window >= h) {
          return -1
        }

        return 1 + 2 * (Math.ceil(Math.log(window / h) / Math.log(bounce)) - 1)
  }
}

【问题讨论】:

  • 尽管它来自代码,但这看起来更像是一道数学题。你能解释一下这个网站的主题是实际计算机编程中的一个问题吗?
  • 在代码大战上,它们只是给出你需要编码和解决的问题,这是我一直在努力解决的问题,只是想学习,所以如果我冒犯了任何人
  • 你的问题还不错,只是你问错了网站。这个特定的站点是关于实用的计算机编程的。像这样的问题更适合Mathematics Stack Exchange 网站。我看到您已经是多个 Stack Exchange 站点的成员——只需加入数学站点并在那里提问即可。数学和计算机编程问题之间的分界线有时很模糊,但就目前而言,这更像是一个与编程稍微相关的数学问题。

标签: javascript algorithm typescript math logarithm


【解决方案1】:

这确实更像是一道数学题,但是……

每次反弹时,您的球会反弹之前反弹的一小部分。所以为了方便起见,想象一下反弹参数是 0.5。每次反弹都是之前反弹高度的一半。如果您的窗口为 1.0,则反弹将是:

1/2, 1/4, 1/8, 1/16...

另一种说法是反弹的高度是bounce_rate ** n,其中n是反弹的次数。第三次反弹是0.5 ** 31/8

现在,如果给您一个高度并且您询问该高度对应于哪个弹跳,您需要解方程 height = bounce_rate ** nn。求解n 需要一个日志——在这种情况下n = log(base bounce_rate)height. 日志基数bounce_rate 不方便,但您可以将其重写为log(height)/log(bounce_rate)。具体来说,要计算哪个反弹到达1/16 窗口高度,您只需计算log(1/16)/log(0.5) 并得到4

因此,您应该能够开始了解这与您的等式有何相似之处。但由于我们的等式使用高度作为窗口高度的一部分,我们需要将该高度转换为相对于母窗口的高度。因此,与其计算球何时会反弹到落窗高度的 1/16,我们想知道球何时达到不同的比率——落窗与母亲的——window/h——如果母亲的窗口为 5,球从 20 处落下,这将计算 1/4,正如我们之前显示的那样,将是 log(1/4)/log(bounce_rate)log(window/h)/log(bounce)

这就是它的核心。方程的其余部分处理的是窗口不一定是对数方程的精确解,所以我们用Math.ceil 进行四舍五入,并且球在下降的过程中出现在窗口前面一次,但每次两次它反弹超过窗口高度的时间。

【讨论】:

  • 伙计,我将标记为正确,但我仍然不明白,我通常可以弄清楚我遇到的大多数事情,所以这真的让我很烦。所以当你说log(base bounce_rate) height. 你是在说log of height base bounce_rate
  • @Lpc_dark 我个人觉得日志令人困惑,我想大多数人都会这样做。但问题的症结在于,您正在求解一个指数变量——求解 x^n 中的 n 要做到这一点,您需要记录 X 的日志。
  • 日志允许您在知道结果和指数应用于的数字的情况下求解指数?对吗?
  • 我对此很着迷的原因是每个人的代码都超时了,试图递归地执行它并且没有通过测试,而一个家伙只是在一行中得到了它。正是疯狂的数字迫使计算机进行大量计算,但他能够在一行中完成。
  • @Lpc_dark 正确。所以解决16 = 2 ^ n 你计算n = log2(16) 并得到4。2^4 = 16。在您的示例中它变得更加混乱,因为基数不是 2 - 基数是跳出率。