挑战暴力方法的谜题?
我买了一张空白 DVD 来录制我最喜欢的电视节目。它带有 20 位数字的贴纸。 “0”-“9”各 2 个。
我认为用数字标记我的新 DVD 收藏是个好主意。我把“1”贴纸贴在我的第一张刻录 DVD 上,并将剩下的 19 张贴纸放在抽屉里。
第二天,我又买了一张空白 DVD(收到了 20 张新贴纸),录制完节目后,我将其标记为“2”。
然后我开始想:贴纸什么时候会用完,我将无法再为 DVD 贴标签?
几行Python,不是吗?
您能提供在合理的运行时间下解决此问题的代码吗?
编辑:暴力破解将需要太长时间来运行。请改进您的算法,以便您的代码在一分钟之内返回正确的答案?
额外加分:如果 DVD 上每个数字都有 3 个贴纸怎么办?
I bought a blank DVD to record my favorite TV show. It came with 20 digit stickers. 2 of each of '0'-'9'.
I thought it would be a good idea to numerically label my new DVD collection. I taped the '1' sticker on my first recorded DVD and put the 19 leftover stickers in a drawer.
The next day I bought another blank DVD (receiving 20 new stickers with it) and after recording the show I labeled it '2'.
And then I started wondering: when will the stickers run out and I will no longer be able to label a DVD?
A few lines of Python, no?
Can you provide code that solves this problem with a reasonable run-time?
Edit: The brute force will simply take too long to run. Please improve your algorithm so your code will return the right answer in, say, a minute?
Extra credit: What if the DVDs came with 3 stickers of each digit?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这是旧的解决方案,全新的解决方案速度快了 6 亿倍位于底部。
解决方案:
代码:
证明'1'会先用完:
This is old solution, completely new 6 bajillion times faster solution is on the bottom.
Solution:
Code:
Prove that '1' will run out first:
这里是存在解决方案的证据:
假设您达到了 21 位数字,您将开始丢失购买的每张 DVD 和标签上的贴纸 (
(+20) + (-21)
)。到目前为止,您积累了多少贴纸并不重要。从这里开始,你的贴纸收藏就开始走下坡路,你最终会用完。
Here is proof that a solution exists:
Assuming you ever get to 21 digit numbers, you will start losing a sticker with every DVD you purchase and label (
(+20) + (-21)
).It doesn't matter how many stickers you have accumulated until this point. From here on it is all downhill for your sticker stash and you will eventually run out.
全新的解决方案。比第一个快 6 亿倍。
代码:
Completely new solution. 6 bajillion times faster than first one.
code:
这是一个快速而肮脏的 python 脚本:
但我不知道它是否会产生正确的结果。如果您发现逻辑错误,请使用调试
输出注释结果:
here's a quick and dirty python script:
i don't know if it yields the correct result though. if you find logical errors, please comment
result with debug output:
对于任何基数 N 和每张 DVD“S”的每个数字的贴纸数量,结果都是:
我看不到任何图案。
或者,如果标签从 0 而不是 1 开始,
我们假设是“1”标签先用完 - 对于大多数其他计算信息来说确实是这种情况。
假设我们的基数为 N,每张 DVD 的每个数字都有 S 个新贴纸。
在 DVD #X 中,将总共有 X×S 个“1”贴纸,无论是否使用过。
所使用的“1”贴纸的数量只是N基数扩展中从1到X的数字中“1”的数量。
这样我们只需要找到X×S与总“1”位数的交叉点即可。
所有这些序列似乎都不存在闭集,因此循环比例 X 次迭代是必要的。可以在 log X 时间内提取数字,因此原则上该算法可以在 O(X log X) 时间内完成。
这并不比其他算法更好,但至少可以删除很多计算。 C 代码示例:
The results for any base N and number of stickers per digit per DVD "S" are:
I can't see any patterns.
Alternatively, if the sticker starts from 0 instead of 1,
Let's assume that it's the “1” sticker running out first — which is indeed the case for most other computed info.
Suppose we are in base N and there will be S new stickers per digit per DVD.
At DVD #X, there will be totally X×S “1” stickers, used or not.
The number of “1” stickers used is just the number of “1” in the digits from 1 to X in base N expansion.
Thus we just need to find the cross-over point of X×S and the total “1” digit count.
there does not seem to be a closed for all these sequences, so a loop proportional X iterations is necessary. The digits can be extracted in log X time, so in principle the algorithm can finish in O(X log X) time.
This is no better than the other algorithm but at least a lot computations can be removed. A sample C code:
以下是 @Tal Weiss:
第一个 21 位数字是
10^20
,此时我们将最多20 * 10^20
贴纸。随后的每张 DVD 将花费我们至少 1 个网络贴纸,因此我们肯定会用完10^20 + 20 * 10^20
,这等于21 * 10^20
。因此,这是解的上限。 (无论如何,这不是一个特别严格的上限!但很容易建立)。将上述结果推广到基
b
:2b
贴纸,b ^ (2b)
,此时我们最多会有2b 。 b ^ (2b)
贴纸b ^ (2b) + 2b 。 [b ^ (2b)]
,等于(2b + 1)[b ^ (2b)]
因此,例如,如果我们使用基数 3,则此计算给出的上限为5103;以 4 为基数,它是 589824。使用这些数字进行暴力/数学求解会更容易。
Here's some thoughts on the upper bound demonstrated by @Tal Weiss:
The first 21-digit number is
10^20,
at which point we will have at most20 * 10^20
stickers. Each subsequent DVD will then cost us at least 1 net sticker, so we will definitely have run out by10^20 + 20 * 10^20
, which equals21 * 10^20
. This is therefore an upper bound on the solution. (Not a particularly tight upper bound by any means! But one that's easy to establish).Generalising the above result to base
b
:2b
stickersb ^ (2b)
, at which point we will have at most2b . b ^ (2b)
stickersb ^ (2b) + 2b . [b ^ (2b)]
, which equals(2b + 1)[b ^ (2b)]
So for example if we work in base 3, this calculation gives an upper bound of 5103; in base 4, it is 589824. These are numbers it is going to be far easier to brute-force / mathematically solve with.