挑战
作为Lambda指挥官的私人助理,你被分配了配置LAMBCHOP世界末日装置的轴向齿轮的任务。它应该非常简单 - 只需添加齿轮即可创建合适的旋转比率。但问题是,由于LAMBCHOP的布局以及支撑它的梁和管道的复杂系统,支撑齿轮的销钉固定到位。
LAMBCHOP的工程师为您提供了一系列清单,用于识别沿各种支撑梁的桩柱位置。您需要在每个挂钉上放置一个齿轮(否则齿轮会与未占用的挂钉碰撞)。工程师拥有大量不同尺寸的齿轮,因此您可以选择任意尺寸的齿轮,从半径为1。您的目标是建立一个系统,其中最后一个齿轮以第一档的速率(每分钟转数或转速)的两倍旋转,无论方向如何。每个齿轮(最后一个齿轮除外)接触并转动下一个挂钉的齿轮。
给定一个名为pegs的不同正整数列表,表示每个peg沿支撑梁的位置,写一个函数答案(pegs),如果有解,则返回两个正整数的列表a和b表示为了达到上述目标,半径= a / b,以最简单的形式表示第一档半径的分子和分母。比率a / b应大于或等于1.并非所有支持配置都必须能够创建正确的旋转比率,因此如果任务不可能,则函数answer(pegs)应返回列表[-1, -1]。
例如,如果钉位于[4,30,50],则第一个齿轮的半径可以为12,第二个齿轮的半径可以为14,最后一个齿轮的半径为6。因此,最后一个齿轮的旋转速度是第一个齿轮的两倍。在这种情况下,钉子将是[4,30,50]并且答案(钉子)应该返回[12,1]。
列表挂钩将按升序排序,并包含至少2个且不超过20个不同的正整数,所有正整数均在1和10000之间。
我的代码:
from fractions import Fraction
def answer(pegs):
odd = bool(len(pegs) % 2)
s = 2
e = rad_last(s, pegs)
if odd:
ans = s + (s - 2*e)
else:
ans = s + (2*e - s) / 3
if ans >= 1 and valid(ans, pegs):
f = Fraction(ans).limit_denominator()
return [f.numerator, f.denominator]
else:
return [-1, -1]
def rad_last(rad_first, pegs):
prev_rad = rad_first
for i in range(1, len(pegs)):
prev_rad = pegs[i] - pegs[i-1] - prev_rad
return prev_rad
def valid(rad_first, pegs):
prev_rad = rad_first
for i in range(1, len(pegs)):
prev_rad = pegs[i] - pegs[i-1] - prev_rad
if prev_rad < 1:
return False
return True
我一直在撕扯我的头发,因为我无法弄清楚为什么我的解决方案失败了四个测试用例。 我确定最后一个齿轮的半径需要是第一个齿轮半径的一半。根据是否有偶数或奇数的钉子,第一个半径的值可以通过代数确定。
f =正确的第一个半径,使其为2 *最后一个半径
s =第一个半径的任意值
e =如果第一档的半径为s
,则为最后一档的相应半径x =获得正确配置所需的偏移量
随着第一档的半径增加,最后一个档位的半径也增加。
f = s + x = 2(e + x)
s + x = 2e + 2x
x = s - 2e
f = s +(s - 2e)
随着第一档的半径增加,最后一个档位的半径减小
f = s + x = 2(e - x)
s + x = 2e - 2x
3x = 2e - s
x =(2e - s)/ 3
f = s +(2e - s)/ 3
我做错了什么?这只是我的实施问题还是我遗漏了一些关于这个问题的根本问题?
答案 0 :(得分:0)
我认为这个问题更像是二进制搜索,所以我写了一个版本。我不知道为什么它可以应用二进制搜索,但它看起来很完美。可能有所帮助。 我不认为这是一个MATH问题,因为它会失败。
from fractions import Fraction
def rad_last(rad_first, pegs):
prev_rad = rad_first
bad_answer = False
for i in range(1, len(pegs)):
prev_rad = pegs[i] - pegs[i-1] - prev_rad
if prev_rad < 1:
bad_answer = True
return (prev_rad, bad_answer)
def binary_search(low, high, pegs):
if low < high:
mid = (low+high) // 2
suppose = Fraction(mid/2)
ret, b = rad_last(mid, pegs)
if ret < suppose:
return binary_search(mid+1, high, pegs)
elif ret > suppose:
return binary_search(low, mid, pegs)
elif ret == suppose:
if b == False:
return ret
else:
return -1
else:
return -1
if __name__ == '__main__':
test_pegs = [[4, 30, 50],[40,300,500],[4,30,50,62],[1,5,8],[6,50,84],[5,50,83],[1,23,43],[123,342,324,546],[12,123,1232],[12,13,16]]
for pegs in test_pegs:
n = min(pegs[1]-pegs[0], 2*(pegs[-1]-pegs[-2]))
a = binary_search(1, n, pegs)
print(a)