放置n条DNA链的方法有几种

时间:2019-01-03 12:07:12

标签: python recursion backtracking

问题在于使用DNA链可以形成多少完整的结构。规则是,新零件的第一个字母必须与上一个链的最后一个字母相同。

在第一行上给您一个整数:链数。接下来的n行是字符串:链。

示例:

5

ACGA

ACGA

ACAC

CCCC

CTAC

输出: 4

我尝试了递归回溯解决方案,但有时会得到错误的答案。我似乎无法找出问题所在。

ans = 0
used = {}

def place(howmanyplaced, allowedletter):
    global ans
    if howmanyplaced == num:
        ans += 1
        return ans

    for i in range(0, len(mylist)):
        if mylist[i][0] == allowedletter and used[i] == False:
            allowedletter = mylist[i][-1]
            used[i] = True
            place(howmanyplaced+1, allowedletter)
            used[i] = False


num = int(input())
mylist = []
for l in range(0, num):
    i = input()
    used[l] = False
    mylist.append(i)

for k in range(0, len(mylist)):
    used[k] = True
    place(1, mylist[k][-1])
    used[k] = False  
print(ans)

2 个答案:

答案 0 :(得分:1)

我对您代码的主要关注是如何在此循环中修改allowedletter

    if mylist[i][0] == allowedletter and used[i] == False:
        allowedletter = mylist[i][-1]
        used[i] = True
        place(howmanyplaced+1, allowedletter)

由于您是通过递归而不是迭代来链接序列,因此allowedletter不应在此循环中进行修改。使用其他变量。以下是我对您的程序的修复,以解决此问题并重新考虑了代码样式:

def place(how_many_placed=0, allowed_letter=None):

    if how_many_placed == number:
        return 1

    answer = 0

    for i, sequence in enumerate(sequences):
        if not used[i] and (allowed_letter is None or sequence[0] == allowed_letter):
            used[i] = True
            answer += place(how_many_placed + 1, sequence[-1])
            used[i] = False

    return answer

number = int(input())

sequences = []

used = []

for _ in range(number):
    sequences.append(input())
    used.append(False)

print(place())

看看这对您是否更好。

答案 1 :(得分:0)

如果可以使用numpy,这是向量化的解决方案。 np.roll移动列表,以便您可以将下一个元素的第一个字母与上一行的最后一个字母进行比较。

import numpy as np

l = ['ACGA', 'ACGA', 'ACAC', 'CCCC', 'CTAC']    
a = np.array(l)    
last_letter= np.roll(a,1)[1:].view('<U1')[::len(a[-1])]
first_letter = a.view('<U1')[::len(a[0])][:-1]
sum(last_letter==first_letter)
#returns 4