按除数查找开关

时间:2018-10-26 14:27:56

标签: python python-3.x algorithm

有N个开关(从1到N)和N个灯泡(从1到N)。

只能按一次该开关,它可以打开/关闭灯泡。 一个开关可以打开/关闭1个以上的灯泡。

例如: 开关编号12可以打开/关闭灯泡{1, 2, 3, 4, 6, 12} (因为{1, 2, 3, 4, 6, 12}是12的除数)

所以我们有一个函数main(N,setON)

  • N是灯的数量
  • SetOn是从一开始就打开的灯泡的集合

该功能必须返回用于打开所有灯泡的开关的列表

例如给出的N=6setON = {2,4},返回列表[2,5,6]

  • 按下按钮2后,{1,4}个灯泡将点亮
  • 按下按钮5后,{4,5}个灯泡将点亮
  • 按下按钮6后,{1,2,3,4,5,6}个灯泡将点亮

我开始了这个问题,但是我不知道如何解决这个问题。 我这样做的方式是调用一个函数除数,该函数将为每个数字找到除数,然后它返回数字N的除数列表,然后为每个列表运行循环以查看其在ON或OFF的位置并将其放入切换到新列表。 但是我实际上没有得到想要的结果,而且我没有主意。

我想在这里提出您的建议,我不是要您解决我的问题,请给我一个提示:)或如果您要纠正我。

import math
def main(N, setON):
    newList= []
    acces = set(range(1,N+1))
    turnOFF = set()
    for number in range(N,1,-1):
        divs = divisors(number)                    
        for i in divs:
            if i in setON:
                turnOFF.add(i)
                setON.remove(i)
            else:
                setON.add(i)
                if i in turnOFF:
                    turnOFF.remove(i)
        newList.append(divs[-1])
        if len(setON) == N-1:
            print(newList)


def divisors(n):
    divs = [x for x in range(1, int(math.sqrt(n))+1) if n % x == 0]
    opps = [int(n/x) for x in divs]
    return list(set(divs + opps))


N=6
setON={2,4}
main(N, setON)

它给了我[6,5,4]

2 个答案:

答案 0 :(得分:2)

从编号最高的开关开始,然后逐步下降。

如果开关X是您可以切换的最高开关,则它是唯一可以改变灯泡X的开关,因此请看一下灯泡X,看看该开关是必须打开还是关闭。

然后确定开关X –如果必须打开,则切换其除数的灯泡并转到下一个最小的开关,因为该开关现在是您可以更改的最高开关。

继续操作,直到没有开关为止。所有灯泡都亮了,或者没有答案。

答案 1 :(得分:0)

您的密码大部分是正确的,但是您在灯泡开着的时候就在换灯泡,这将导致错误的答案。您也没有检查灯泡1,并且所有的检查也都错了。这是您的固定版本:

for number in range(N,0,-1):
    if number in setON:
        continue
    #your previous code
    if len(setON) == N:
        print(newList)

这是一个更快的方法(避免使用集合),并且实现起来更加简洁:

import math
def main(N, setON):
    isOn = [False] * (N + 1)
    for bulb in setON:
        isOn[bulb] = True

    answer = []

    for x in range(N, 0, -1):
        if not isOn[x]:
            for num in divisors(x):
                isOn[num] = not isOn[num]
            answer.append(x)

    if sum(isOn) == N:        
        return list(reversed(answer))            



def divisors(n):
    divs = [x for x in range(1, int(math.sqrt(n))+1) if n % x == 0]
    opps = [int(n/x) for x in divs]
    return list(set(divs + opps))


N=6
setON={2,4}
print(main(N, setON))