我为老虎机对DM的挑战::OJ编写了一个解决方案:
玛莎带着一罐硬币去赌场,目的是想变得富有。她轮流玩三台机器。她不知道这些机器是完全可以预测的。每出戏要花四分之一的钱。第一台机器每35次播放30节;第二台机器每100次播放一次支付60节;第三台每播放10次支付9节。输入规格你的程序应该作为输入,在玛莎的罐子中的25美分(将至少有一个和少于1000),以及每台机器自上次付款以来被播放的次数。输出规格你的程序应该输出玛莎播放的次数,直到她破产。样本输入48,3,10,4样本输出玛莎在破产前玩66次。
我想让它在2秒或更短的时间内运行。
money = int(input())
m1 = int(input())
m2 = int(input())
m3 = int(input())
turns = 0
while (money != 0):
#machine 1
money -= 1
m1 += 1
if (m1 == 35):
money += 30
m1 = 0
turns += 1
#machine 2
money -= 1
m2 += 1
if (m2 == 100):
money += 60
m2 = 0
turns += 1
#machine 3
money -= 1
m3 += 1
if (m3 == 10):
money += 9
m3 = 0
turns += 1
print ('Martha plays {} times before going broke.'.format(turns))发布于 2019-01-17 18:05:19
代码是一个单一的单块代码。重新组织一些事情可能是个好主意:让事情变得更清晰,更容易测试,更容易维护,等等。
第一个主要改进可能是编写一个具有明确输入(money、m1、m2、m3)的函数和一个清晰的输出,以解决我们关心的问题:计算循环数。处理输入/输出的逻辑与执行计算的逻辑分离- seel也是https://en.wikipedia.org/wiki/Separation_的_关切。
然后,这个函数可以与用户的输入一起使用,但我们也可以为它提供硬编码的值。这可以用于编写测试,以确保该函数运行正常(至少在dmoj提供的示例中如此)。
(在下面提供的代码中,我有一个简单的assert语句来编写测试,但这可能是一个阅读单元测试框架并开始使用它们的好机会)。
然后,您可以轻松地添加任意数量的测试。
现在我们有了单元测试,以防止我们破坏太严重,我们可以开始调整代码。
最后,可以使用if __name__ == "__main__":将代码中的定义与实际使用这些定义的代码分开。它使您的代码更容易通过导入机制重用。
Python有一个风格指南称为PEP 8。Python社区(或多或少严格地)遵循它。强烈建议阅读它,并在相关时尽量坚持下去。在您的例子中,您有多余的括号,缩进两个空格而不是4个多余的空白空间。
在现阶段,我们有:
def get_number_of_games(money, m1, m2, m3):
"""Return the number of games <to be continued>."""
turns = 0
while money != 0:
#machine 1
money -= 1
m1 += 1
if m1 == 35:
money += 30
m1 = 0
turns += 1
#machine 2
money -= 1
m2 += 1
if m2 == 100:
money += 60
m2 = 0
turns += 1
#machine 3
money -= 1
m3 += 1
if m3 == 10:
money += 9
m3 = 0
turns += 1
return turns
def interactive_main():
money = int(input())
m1 = int(input())
m2 = int(input())
m3 = int(input())
print('Martha plays {} times before going broke.'.format(get_number_of_games(money, m1, m2, m3)))
def unit_test():
"""Run unit-tests."""
assert get_number_of_games(48, 3, 10, 4) == 66
print("OK")
if __name__ == "__main__":
unit_test()代码中充满了幻数幻数,这使得逻辑难以理解。我们可以用有意义的名称将这些值存储到常量中。
更好的是,我们可以将这些数据存储到适当的数据结构中。对于一个简单的解决方案,我们可以决定使用名称。
from collections import namedtuple
Machine = namedtuple('Machine', ['winning_freq', 'profit'])
MACHINE1 = Machine(35, 30)
MACHINE2 = Machine(100, 60)
MACHINE3 = Machine(10, 9)
def get_number_of_games(money, m1, m2, m3):
"""Return the number of games <to be continued>."""
turns = 0
while money != 0:
money -= 1
m1 += 1
if m1 == MACHINE1.winning_freq:
money += MACHINE1.profit
m1 = 0
turns += 1
#machine 2
money -= 1
m2 += 1
if m2 == MACHINE2.winning_freq:
money += MACHINE2.profit
m2 = 0
turns += 1
#machine 3
money -= 1
m3 += 1
if m3 == MACHINE3.winning_freq:
money += MACHINE3.profit
m3 = 0
turns += 1
return turns代码不太健壮。一些情况可能会导致它误入歧途。
让我们举一个简单的例子:我们有1/4,机器还没有被使用。这可以写成:
print(get_number_of_games(1, 0, 0, 0))当我们运行这个,我们被困在一个无限循环中。我让你调查原因。
另一个例子--它可以被认为是无效的,但确实值得修复,因为它是如此简单:我们有很多钱,机器已经被大量使用了。例如,我们有:
print(get_number_of_games(1000, 36, 101, 11))假设我们解决了前一个问题:我们玩了多少回合?我们赢了多少次?
当我们修复行为时,您可以添加相应的单元测试,以确保以后不会陷入相同的问题。
代码依赖于重复的逻辑来处理不同的机器。一个更好的解决方案是通过同样的逻辑来处理它们。我们可以想象有一个机器列表。
此外,我们可以想象,在给定的机器上播放的旋转次数与Machine类中的其他信息一起存储。然后,get_number_of_games函数可以将一笔钱和一个定义正确的机器的列表作为输入。
https://codereview.stackexchange.com/questions/211709
复制相似问题