Google foobar挑战gearing_up_for_destruction

时间:2017-11-01 04:48:10

标签: python algorithm google-foobar

  

挑战

     

作为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

我做错了什么?这只是我的实施问题还是我遗漏了一些关于这个问题的根本问题?

1 个答案:

答案 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)