0

所以我目前正在参加谷歌 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%,但我懒得去弄清楚为什么

4

1 回答 1

0

我的问题通过更改这些代码得到解决:

list.remove(tuple(coordinates))
.
.
.
.
denom = gcd(x,y)
x = x/denom
y = y/denom

至:

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)

我认为 denom 在不同版本中的工作方式没有任何不同,但结果现在正是我所期望的,所以我的旧代码中很可能有一个错误,导致旧列表编辑的正确答案

于 2021-06-23T07:11:03.323 回答