所以我目前正在参加谷歌 Foobar 挑战,事实证明最新的是 Python 2.7 而不是 3.8。我没有读到这个,真丢脸,所以我在 3.8 中开发,现在遇到了一些我不确定它们来自哪里的异常。我已经发现整数和浮点除法之间可能存在差异,但我不知道这是否真的是我问题的根源。(顺便说一句,我不能使用 from_future_)
上代码:
import math
from math import gcd
def findmultiples(coordinates, list, dim):
coords = coordinates[:]
while (coordinates[0] <= dim[0] and coordinates[1] <= dim[1]) and (coordinates[0] >= -dim[0] and coordinates[1] >= -dim[1]):
if tuple(coordinates) in list:
list.remove(tuple(coordinates))
coordinates[0] = coordinates[0] + coords[0]
coordinates[1] = coordinates[1] + coords[1]
return list
def solution(dim, your_position, trainer_position, distance):
coordinate = [(x,y) for x in range(-dim[0] , dim[0]+1) for y in range(-dim[1] , dim[1]+1)]
coordinate.sort()
result = []
for i in range(1):
for x,y in coordinate:
y_position = your_position[:]
t_position = trainer_position[:]
beam_position = your_position[:]
distancetraveled = 0
if x == 0 and y == 0:
continue
denom = gcd(x,y)
x = x/denom
y = y/denom
while True:
distancetraveled += math.sqrt((x * x) + (y * y))
if(distancetraveled > distance):
break
beam_position[0] += x # add x coordinate
beam_position[1] += y
if (beam_position[0] > dim[0] or beam_position[0] <0 ): # Check if out of bounds along x-axis
t_position[0] = dim[0] - t_position[0] # Mirror the t_position along the y-axis
y_position[0] = dim[0] - y_position[0] # Mirror y_position along the y-axis
beam_position[0] = (beam_position[0] + dim[0]) % (2*dim[0])
if (beam_position[1] > dim[1] or beam_position[1] <0 ): # Check if out of bonds along y-axis
t_position[1] = dim[1] - t_position[1] # Mirror the t_position along the x-axis
y_position[1] = dim[1] - y_position[1] # Mirror y_position along the x-axis
beam_position[1] = (beam_position[1] + dim[1]) % (2*dim[1])
if (beam_position[0] == t_position[0] and beam_position[1] == t_position[1]):
coordinate = findmultiples([x,y], coordinate, dim)
count = 1
result.extend((x,0) for x in range(count))
break
if(beam_position == y_position):
coordinate = findmultiples([x,y], coordinate, dim)
break
return len(result)
它相当短,为了能够在 Python 2.7 上运行它,我必须做的唯一区别(至少我是这么认为的)是将第二个导入更改为,from fractions import gcd
但显然这不起作用,因为由于某种原因,程序需要永远第 10 行coordinates[0] = coordinates[0] + coords[0]
。到目前为止,我无法完成我正在运行的 cProfile 测试,所以我目前假设程序被卡在那里。现在我可以观察到的差异(因为程序完成)是这样solution([3,2], [1,1], [2,1], 4)
,结果在 Python 2.7 中返回为 7(顺便说一句正确的结果),在 3.9 中返回为 6。第二个测试solution([300,275], [150,150], [185,100], 500)
还没有完成。我尝试使用 cProfile 测量时间,但第一次测试完成得太快,以至于我看不到任何有用的东西。(0.000 秒与 0.001 秒)
我试着用谷歌搜索,我只能找到不同之处,而不是深入研究 Python 2.7.13 文档的 6.5k 页。
我希望有一个人可以帮助我。干杯
编辑:cProfile 实际上完成了,但没有告诉我很多(编辑:它确实告诉我 findmultiples 在这个版本中被称为更多,而不是在其他版本中:
ncalls tottime percall cumtime percall filename:lineno(function)
1 3.905 3.905 1417.093 1417.093 4.1.py:16(solution)
689 1408.263 2.044 1412.459 2.050 4.1.py:5(findmultiples)
26 0.000 0.000 0.000 0.000 4.1.py:51(<genexpr>)
1 0.012 0.012 1417.105 1417.105 <string>:1(<module>)
330463 0.208 0.000 0.208 0.000 fractions.py:18(gcd)
1 0.000 0.000 0.000 0.000 {len}
3638301 0.499 0.000 0.499 0.000 {math.sqrt}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
13 0.000 0.000 0.000 0.000 {method 'extend' of 'list' objects}
687 4.197 0.006 4.197 0.006 {method 'remove' of 'list' objects}
1 0.015 0.015 0.015 0.015 {method 'sort' of 'list' objects}
616 0.007 0.000 0.007 0.000 {range}
它花费的时间是 Python 3.8 的近 40 倍。1417s 与 37s 的主要区别在于 find multiples 被调用的频率大约是 30 倍。这将解释差异的冲击。我能够找到问题(至少我认为我做到了)。出于某种原因,list.remove() 和 gcd() 函数的工作方式有些不同。我将它们更改为:
index = list.index(tuple(coordinates))
list.pop(index)
list.insert(index, (0,0))
.
.
.
.
denom = gcd(x,y)
x = x/abs(denom)
y = y/abs(denom)
现在,代码在 Python3.x 和 Python 2.x 中的工作方式似乎相同。有趣的是,在 2.x 中它现在快了大约 20%,但我懒得去弄清楚为什么