我有一个RNA序列,看起来像这样。每个字符代表一个核苷酸(程序员可以忽略它,你可以将它们视为元素):
(((((((..((((.....(..)))).((((.........)))).....(((((..)....))))))))))))....
我将使用这个术语来表达问题:
( = lhb
) = rhb
. = dot
所以基本上具有lhb的元素连接到具有rhb的元素,并且所有点都是自由区域。它们的连接方式很复杂。为方便起见,我很难说出单词,我会将数字放在某些元素之下,这些元素是连接的:
(((((((..((((.....(..)))).((((.........)))).....(((((..)....))))))))))))....
1 2 2 3 3 45 5 4 1
我认为这会让你了解它们是如何连接的。我有兴趣找出连接元素的位置和免费的区域。
(例如,元素1连接到元素72,元素8到9是空闲的)。
我 选择C进行编码,但我并不接近逻辑。
此外,使用C语言进行编程变得越来越困难。我觉得可以使用正则表达式在python中轻松完成此操作,或者可能是perl,但我对这些语言没有太多经验。所以,如果任何人都可以提供一个更容易的方法,将是一个巨大的帮助。也欢迎改进C代码的想法。这是我的C代码: -
#include <stdio.h>
int main() {
char dot[500];
int i = 0, j = 0;
int count = 0, count1 = 0, count2 = 0;
int lhb[100];
int rhb[100];
int dots[100];
int pair_1[100];
int pair_2[100];
int pair_3[100];
FILE * fp;
fp = fopen("structure.txt", "r");
while (fscanf(fp, "%c", & dot[i]) != EOF) {
i++;
}
fclose(fp);
for (i = 0; dot[i] != '\0'; i++) {
if (dot[i] == '(') {
lhb[count] = dot[i];
pair_1[count] = i;
count++;
}
else if (dot[i] == '.') {
rhb[count1] = dot[i];
pair_2[count1] = i;
count1++;
}
else {
dots[count2] = dot[i];
pair_3[count2] = i;
count2++;
}
}
printf("Base-pair details :\n");
for (j = 0; j < count; j++)
printf("%d--%d\n", pair_1[j] + 1, pair_3[count - j - 1] + 1);
printf("Loop details :\n");
// for(j=0;j<=count;j++)
// printf("--%d-",pair_2[j]+1);
return 0;
}
答案 0 :(得分:1)
这是一个潜在的解决方案。 Free包含一个索引每个点和列的列表,其中包含具有每对索引的元组列表。这是基于您的数据是完美的假设(即左对和右对的数量相同,左对之前没有右对)。然而,这可以被修改以检查边缘情况。根据你的问题,我开始将索引设为1而不是0。
data = '(((((((..((((.....(..)))).((((.........)))).....(((((..)....))))))))))))....'
left = []
group = []
prev = ''
free = []
pairs = []
for index, elem in enumerate(data, 1):
if elem == '.' and prev == '.':
group.append(index)
elif elem == '.':
group = [index]
else:
if len(group) >= 1:
free.append(group)
group = []
if elem == '(':
left.append(index)
elif elem == ')':
pairs.append([left.pop(), index])
prev = elem
if len(group) > 0:
free.append(group)
pairs.sort()
输出:
[[1, 72], [2, 71], [3, 70], [4, 69], [5, 68], [6, 67], [7, 66], [10, 65], [11, 25], [12, 24], [13, 23], [19, 22], [27, 43], [28, 42], [29, 41], [30, 40], [49, 64], [50, 63], [51, 62], [52, 61], [53, 56]]
[[8, 9], [14, 15, 16, 17, 18], [20, 21], [26], [31, 32, 33, 34, 35, 36, 37, 38, 39], [44, 45, 46, 47, 48], [54, 55], [57, 58, 59, 60]]
代码通过在每个元素上迭代一次来工作。如果它遇到左边的paren,它会将索引附加到列表中。当它遇到一个正确的paren时,它弹出最后一个看到的左paren的索引创建一对。至于自由点,跟踪前一个元素会告诉您如何处理每个点。如果看到一个,继续添加到当前列表,否则启动一个新列表。
答案 1 :(得分:0)
真正解决这个问题的最好方法是保持堆栈。对于遇到的每个(
,您可以将索引值推送到堆栈中,并且对于每个)
,您需要使用插入最后(
索引的数字弹出堆栈。这意味着(
的索引与)
的索引形成一对。
这可以通过这样做来实现
seq = '(((((((..((((.....(..)))).((((.........)))).....(((((..)....))))))))))))....'
xStack = []
for i, x in enumerate(seq):
if x == '(':
xStack.append(i)
if x == ')':
o = xStack.pop()
现在已经有了基本步骤,除了维护括号的索引之外,您还需要做更多的事情。在弹出操作之后你需要存储匹配的对,为了做到这一点,让我们引入另一个变量,当我们遇到.
seq = '(((((((..((((.....(..)))).((((.........)))).....(((((..)....))))))))))))....'
xStack = []
resultingPairs = []
for i, x in enumerate(seq):
if x == '(':
xStack.append(i)
if x == ')':
o = xStack.pop()
tempPair = [o, i]
resultingPairs.append(tempPair)
if x == '.':
pass
现在我们得到的结果看起来像这样
[[18, 21], [12, 22], [11, 23], [10, 24], [29, 39], [28, 40], [27, 41], [26, 42], [52, 55], [51, 60], [50, 61], [49, 62], [48, 63], [9, 64], [6, 65], [5, 66], [4, 67], [3, 68], [2, 69], [1, 70], [0, 71]]
我们需要找出所有空闲空间的位置,这可以通过以下方式轻松完成
spacesList = [i for i in range(len(seq)) if seq.startswith('.', i)]
导致
[7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59, 72, 73, 74, 75]
现在,您可以轻松编写传递spacesList
和resultingPairs
的函数,并获取每个可能对之间的可用空间数。有很多可能的优化,但这应该能够帮助您开始正确的方向。
def getSpacesCount(spacesList, resultingPairs):
for pair in resultingPairs:
a = pair[0]
b = pair[1]
spacesCount = 0
for val in spacesList:
if a < val < b:
spacesCount+=1
print a,b,spacesCount
seq = '(((((((..((((.....(..)))).((((.........)))).....(((((..)....))))))))))))....'
xStack = []
resultingPairs = []
for i, x in enumerate(seq):
if x == '(':
xStack.append(i)
if x == ')':
o = xStack.pop()
tempPair = [o, i]
resultingPairs.append(tempPair)
if x == '.':
pass
spacesList = [i for i in range(len(seq)) if seq.startswith('.', i)]
getSpacesCount(spacesList, resultingPairs)
你有左括号的位置值,右括号和它们之间的自由空格数。
>>> getSpacesCount(spacesList, resultingPairs)
18 21 2
12 22 7
11 23 7
10 24 7
29 39 9
28 40 9
27 41 9
26 42 9
52 55 2
51 60 6
50 61 6
49 62 6
48 63 6
9 64 28
6 65 30
5 66 30
4 67 30
3 68 30
2 69 30
1 70 30
0 71 30
修改强> 似乎无法弄清楚如何编辑stackoverflow的注释,将函数更新为
def getSpacesCount(spacesList, resultingPairs):
for pair in resultingPairs:
a = pair[0]
b = pair[1]
spacesCount = 0
spaces = []
for val in spacesList:
if a < val < b:
spaces.append(val)
spacesCount+=1
print a,b,spacesCount,spaces
这将为您提供计数和职位。你可以保留你真正喜欢的那个。
>>> getSpacesCount(spacesList, resultingPairs)
18 21 2 [19, 20]
12 22 7 [13, 14, 15, 16, 17, 19, 20]
11 23 7 [13, 14, 15, 16, 17, 19, 20]
10 24 7 [13, 14, 15, 16, 17, 19, 20]
29 39 9 [30, 31, 32, 33, 34, 35, 36, 37, 38]
28 40 9 [30, 31, 32, 33, 34, 35, 36, 37, 38]
27 41 9 [30, 31, 32, 33, 34, 35, 36, 37, 38]
26 42 9 [30, 31, 32, 33, 34, 35, 36, 37, 38]
52 55 2 [53, 54]
51 60 6 [53, 54, 56, 57, 58, 59]
50 61 6 [53, 54, 56, 57, 58, 59]
49 62 6 [53, 54, 56, 57, 58, 59]
48 63 6 [53, 54, 56, 57, 58, 59]
9 64 28 [13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
6 65 30 [7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
5 66 30 [7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
4 67 30 [7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
3 68 30 [7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
2 69 30 [7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
1 70 30 [7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
0 71 30 [7, 8, 13, 14, 15, 16, 17, 19, 20, 25, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 53, 54, 56, 57, 58, 59]
答案 2 :(得分:0)
我不确定你想要得到什么,但是这个perl会产生与Navidad20相同的效果。它依赖于正则表达式。它使用Regexp::Common模块来获取平衡括号的位置,并使用简单的npm install <module> --legacy-bundling
循环来获取“免费”的位置。元素。它从1开始计算,而不是从0开始。
我不知道无效数据会如何表现。
while
输出是:
#!/usr/bin/perl
use strict;
use warnings;
use Regexp::Common qw /balanced/;
my $seq = '(((((((..((((.....(..)))).((((.........)))).....(((((..)....))))))))))))....';
while ($seq =~ /(?=($RE{balanced}{-parens=>'()'}))/g) {
print 1 + $-[1], ' ', $+[1], " $1\n";
}
my @free;
push @free, [ 1 + $-[0] .. $+[0] ] while $seq =~ /\.+/g;
use Data::Dumper; print Dumper \@free;