【问题标题】:Mathematical algorithm failing but seems correct数学算法失败但似乎正确
【发布时间】:2016-09-20 15:03:57
【问题描述】:

我遇到了一个问题,其中在 A 和 B 中输入了一个函数。这些是 1、1 中的目标数字,其中 B 只能增加 A,A 只能增加 B(例如,1 1 - > 2 1 或 1 2. 2 1 -> 3 1 或 2 3. 2 3 -> 5 3 或 2 5)。这将创建一个二叉树。在问题中,给定目标数字,我需要找到达到该数字的“最小”代数,或者该数字是否可能达到(例如,2 4 不可能达到)。这是我想出的解决方案,它通过了我扔给它的每个测试用例:

import math

def answer(M, F):
    m = int(M)
    f = int(F)
    numgen=0
    if f==1 and m==1:
        return "0"
    while f>=1 and m>=1:
        if f > m:
            m, f = f, m
        if f==1:
            return str( numgen + m - 1 )
        if m>f:
            numgen += math.floor( m / f )
            m = m % f
    return "impossible"

我正在半代码打高尔夫球,我觉得我的解决方案非常优雅且相当高效。我在十代之内扔给它的所有东西都是正确的,如果我扔大量数字(上限被规定为输入的 10^50),这些也可以正常工作。当提交并针对未知测试用例运行时,五个中有三个失败。本质上,我的问题是更想知道什么样的案例在这里失败。

我有一些假设我无法证明,但可以肯定是准确的:

  • 二叉树中没有重复项。我没有找到任何案例,我怀疑这在数学上是可以证明的。
  • 可以在不影响世代数的情况下对树的左右两半进行镜像 - 这实际上已经得到很好的证明。
  • 只有一条路径可以到达任何给定的组合(二叉树的一种属性,其中没有重复项) - 这依赖于假设 1,但如果假设 1 为真,那么这也必须为真。
  • 两个数中的一个始终是质数。这并没有真正影响算法,我也没有证明它,但似乎总是如此。一个有趣的花絮。

这个解决方案哪里错了?

【问题讨论】:

  • 会不会像 int(M) 返回 TypeError 一样愚蠢?
  • 不幸的是,没有。输入始终是包含在字符串中的正整数,并保证有效。他们并没有向它抛出错误的输入。此外,如果抛出异常并且没有异常被击中,它们会通知我。
  • 打印他们输入的内容以查看失败的情况如何?
  • 试过了,不行。除非测试用例通过或失败,或者抛出异常,否则不会向我显示任何内容。或者,当然,如果程序超时 - 时间限制是十秒。以前在我的解决方案的早期版本中存在问题,现在很容易通过。
  • 你有一个链接,我们可以从中查看问题描述,因为我还不太明白......

标签: python algorithm math binary-tree primes


【解决方案1】:

您没有说您使用的是 Python 2 还是 Python 3,但 math.floor( m / f ) 仅在 Python 3 中才有意义。m / f 是一个浮点数,这是不精确的。你最好简单地使用整数除法:numgen += m // f。一个重要的例子是M, F = str(10**30), '3',你计算333333333333333316505293553666,但使用整数除法你会得到333333333333333333333333333335

【讨论】:

  • 这确实成功了。我不知道这是 Python 中的一个差异,假设 math.floor() 总是返回一个 int,但更改这一行修复了我之前失败的所有测试用例。
  • @Bioniclegenius 在 Python 3 中,math.floor 总是返回一个 int。但问题是除法,所以math.floor输入 已经是错误的。如果误差超过 0.5,你就有问题了。
  • 以什么方式? int(float) 不应该和浮点数小数点后截断一样吗?这就是我对差异感到有些困惑的地方。
  • @Bioniclegenius 因为浮点数没有任意精度。前 15 位左右的数字应该是正确的,但之后是“随机的”。例如,10**30 // 3 是 333333333333333333333333333333 但10**30 / 3 是 333333333333333316505293553664。
  • @Bioniclegenius 是的,通常。如果您还不知道,请参阅stackoverflow.com/questions/588004/…
【解决方案2】:

在我看来,您的解决方案太复杂了。看看这个:

def answer(M, F):
    my_bombs = [int(M), int(F)]
    my_bombs.sort()
    generations = 0
    while my_bombs != [1, 1]:
        if my_bombs[0] == 1:
            return str(generations + my_bombs[1] - 1)
        if my_bombs[0] < 1 or my_bombs[0] == my_bombs[1]:
            return "impossible"
        print(my_bombs, generations)
        n = my_bombs[1] // my_bombs[0]
        my_bombs[1] -= my_bombs[0] * n
        generations += n
        my_bombs.sort()
    return str(generations)

【讨论】:

  • 超出时间限制,抱歉。
  • 现在怎么样?添加了一些短路
  • 测试用例1失败,2-5通过。
  • 在最新的编辑中,所有的测试用例都通过了,干得好。我选择了另一个解决方案,因为它更完整地说明了问题所在和原因,尽管您的也是正确的。
猜你喜欢
  • 2013-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-14
  • 2019-03-07
  • 2022-10-06
  • 2017-03-06
  • 1970-01-01
相关资源
最近更新 更多