我有一个固定的32位,用于存储尽可能多的DNA。存储1个字符的DNA('A'
,'C'
,'G'
或'T'
)所需的空间量为2位(00
,{{1} },01
,10
,因为只有4种组合。)
要存储最多2个字符,(例如,11
,A
,C
,G
,T
, AA
,...,AC
)有20种可能的组合,我们可以使用函数GG
来处理,其中((4**(x+1))-2)/(4-1)
是我们想要的最大DNA长度储藏。因此,16个字符的DNA将具有5,726,623,060个组合,但是在32位中,我最多只能存储4,294,967,296个数字(2 ** 32)。
如此长的故事简短,在32位中,可以存储的可变长度DNA的最大量是15个字母(1,431,655,764种组合)。
因此,下一步是制作一个函数,最多可以将15个字母的DNA作为字符串,并将其转换为数字。哪个号码(x
可以是'A'
,可能是0
,可能是1
,它确实无关紧要,这并不重要只要我们可以撤消该功能并稍后将该号码返回1332904
。
我开始通过制作包含1,431,655,764个元素的'A'
对的字典来解决这个问题,但很快就用光了。这就是我需要从string到int的翻译函数的原因。
答案 0 :(得分:4)
这是我的建议。
如果存储字母需要2到30位,则至少还有2位可以帮助您推断出长度。始终在表示字符的位之后添加1
,并用零填充其余部分。这样,如果您在位模式中查找最后1
,它将始终位于字符串结尾之后。
E.g。
A -> 00 (meaning 'A') followed by 1 (meaning 'end') followed by 29 zeroes
-> 00100000000000000000000000000000
C -> 01 (meaning 'C') followed by 1 (meaning 'end') followed by 29 zeroes
-> 01100000000000000000000000000000
G -> 10 (meaning 'G') followed by 1 (meaning 'end') followed by 29 zeroes
-> 10100000000000000000000000000000
T -> 11 (meaning 'T') followed by 1 (meaning 'end') followed by 29 zeroes
-> 11100000000000000000000000000000
AA -> 0000 (meaning 'AA') followed by 1, followed by 27 zeroes
-> 00001000000000000000000000000000
...
AAAAAAAAAAAAAAA
-> 000000000000000000000000000000 (meaning the 'A's) followed by 1, followed by 1 zero
-> 00000000000000000000000000000010
应该明确地表示你的字符串,并允许你最多15个字符,32位。
答案 1 :(得分:2)
给定静态排序,您可以将每个单独的排列称为表示序列中顺序的单个数字。然后,而不是建立字典,你可以在另一边转换它。
import itertools
def build_sequence(length):
return itertools.product("ACTG", repeat=length)
def encode(sequence: str):
seq = build_sequence(len(str))
t_seq = list(sequence) # to compare to seq
for idx, s in enumerate(seq):
if s == t_seq:
return idx
def decode(e_sequence):
max_length = math.ceil(math.log(e_sequence, 4))
# max_length is the character count of ATCGs that e_sequence contains,
# since each sequence has 4**length elements
seq = build_sequence(max_length)
for _ in range(e_sequence):
# skipping these is like indexing a list
next(seq)
return next(seq)
然后,您可以将该号码打包成较小的类型并通过线路发送,再次打开包装并解码。
import struct
packed = struct.pack("I", encode(some_sequence))
# send it? I'm not sure what you're doing with it
rcvd_pack = b'SUUU'
unpacked = struct.unpack("I", rcvd_pack)
# becomes a tuple of the value
enc_seq = unpacked[0]
result = decode(enc_seq)
这可以让你构建16个字符序列并将它们打包成32位数据。
答案 2 :(得分:1)
使用Khelwood的信息,我用以下代码解决了这个问题:
b = {'A':0b00,'C':0b01,'G':0b10,'T':0b11}
t = {'00':'A','01':'C','10':'G','11':'T'}
def binarize(string):
result = 0
for char in (string + 'G').ljust(16,'A'): result = (result << 2) + d[char]
return result
def textualize(value):
result = ''
for twobits in [ format(value, '032b')[i:i+2] for i in range(0,32,2) ]:
result += t[twobits]
return result.rstrip('A')[:-1]
>>> binarize('TTTTTTTTTTTTTTT')
4294967294
>>> textualize(4294967294)
u'TTTTTTTTTTTTTTT'
我确信有一种更有效的方法来完成所有这些,我认为我需要这样做,因为我将编码和解码数十亿次,但现在它至少可以工作:)