6

我试图想出一个好的算法来创建一个右手DNA 字符串的表示,使用破折号字符,用于任意数量的字符。

这是我目前拥有的,使用 776#的:

  #########                 ##########
    #########                ##########
      #########              ##########
        #########          ##########
          ##########     ##########
            ########## ##########
              ###### ##########
                ## ##########
                 ########## #
               ########## #####
             ########## #########
           ##########    ##########
         ##########        ##########
       ##########           ##########
     ##########             ##########
   ##########               ##########
  ##########               ##########
  ##########             ##########
  ##########           ##########
   ##########        ##########
     ###########   ##########
       ######### ##########
         ##### ##########
           # ##########
           ########## ###
         ########## #######
       ##########  ##########
     ##########      ##########
   ##########          ##########
  ##########             ##########
  ##########               ##########
  ##########                 ##########
   ##########                 ##########
     ##########               ##########
       ##########             ##########
         ##########          ##########
           ##########      ##########
             ##########  ##########
               ####### ##########
                 #### #########
                    ######### #
                  ########## ###
                ########### #######

但是当我手动尝试通过复制/粘贴重复螺旋时,螺旋并没有完美对齐。

具有与上述示例相同的宽度但也具有碱基对交叉键(如在此图像中或在下面的围巾图案中)的解决方案也是可以接受的。

围巾图案

4

5 回答 5

6

这个问题的关键是要认识到您可以将螺旋上的每条链表示为正弦波的组合 - 一个用于周期性部分,一个用于页面的“深度”。以这种方式参数化问题后,您就可以控制螺旋线的各个方面。下面的示例使用*#来显示不同的股线来说明这一点。如果您选择的波长值与整数值不相称,您将获得比最佳结果更少的结果 - 但现在您可以使用输入来找到您认为最美观的表示。

from numpy import *

amp = 10
length = 100
wavelength = 20

omega = (2*pi)/wavelength
phi   = wavelength*(0.5)
X = arange(1,length)
Y1 = round_(amp*(sin(omega*X) + 1))
Y2 = round_(amp*(sin(omega*X+phi) + 1))

offset = phi/2
Z1 = sin(omega*X + offset)
Z2 = sin(omega*X + phi + offset)

T1 = " ######### "
T2 = " ********* "
clen = len(T1)

H = zeros((length,amp*2+clen),dtype='str')
H[:,:] = " "

for n,(y1,y2,z1,z2) in enumerate(zip(Y1,Y2,Z1,Z2)):
    H[n,y1:y1+clen] = list(T1)
    H[n,y2:y2+clen] = list(T2)

    # Overwrite if first helix is on top
    if z1>z2: H[n,y1:y1+clen] = list(T1)

for line in H:
    print "".join(line)

这些值给出:

   *********  #########        
  *********      #########     
 *********         #########   
 *********           ######### 
   *********         ######### 
     *********       ######### 
       *********   #########   
          ****** #########     
              #########        
           ######### ****      
        #########  *********   
     #########      *********  
   #########         ********* 
 #########           ********* 
 #########         *********   
 #########       *********     
   #########   *********       
     ###### *********          
        *********              
      ********* ####           
   *********  #########        
  *********      #########     
 *********         #########   
 *********           ######### 
   *********         ######### 
     *********       ######### 
       *********   #########   
          ****** #########     
              #########        
于 2012-04-23T15:54:17.893 回答
2

这应该给你一个体面的开始:

from math import sin, cos, pi

class RightHelix(object):
    def __init__(self, maxima, minima, period, offset):
        self.mid = 0.5 * (maxima + minima)
        self.mag = 0.5 * (maxima - minima)
        self.k = 2.0 * pi / period
        self.offs = self.k * offset
    def x(self, t):
        return self.mid + self.mag * sin(self.k*t - self.offs)
    def y(self, t):
        return -self.mag * cos(self.k*t - self.offs)

def main():
    rh = RightHelix(33, 7, 20, -2)

    for t in range(40):
        x,y = rh.x(t), rh.y(t)
        print(' '*int(x-0.5) + ('O','X')[y>0])

if __name__=="__main__":
    main()

如给定的,产生

                           O
                              O
                               O
                                O
                               X
                              X
                           X
                       X
                   X
               X
           X
        X
       X
      X
       O
        O
           O
               O
                   O
                       O
                           O
                              O
                               O
                                O
                               X
                              X
                           X
                       X
                   X
               X
           X
        X
       X
      X
       O
        O
           O
               O
                   O
                       O

(Xs 和 Os 只是为了表明它确实是一个右手螺旋)。

于 2012-04-23T15:30:25.447 回答
2

这个怎么样:

import math

phaseA = math.pi/1.5
phaseB = 0
step = math.pi/20
width = 30  # screen size
breadth = 8  # breadth of DNA single string

x = 0.0
while True:
  x += step
  if x > 30.0: break
  yA = math.sin(x + phaseA)
  zA = math.cos(x + phaseA)
  yB = math.sin(x + phaseB)
  zB = math.cos(x + phaseB)
  if zA > zB:  # which is in front?
    yTop, yBottom = yA, yB
  else:
    yTop, yBottom = yB, yA
  # screenify values:
  yTop    = 1 + int((1.0 + yTop)    / 2.0 * (width-breadth))
  yBottom = 1 + int((1.0 + yBottom) / 2.0 * (width-breadth))
  line = ' ' * yBottom + '#' * breadth + ' ' * (width-yBottom)
  line = list(line)  # make mutable
  line[yTop-1] = ' '
  line[yTop+breadth+1] = ' '
  for i in range(breadth):
    line[yTop+i] = '#'
  print ''.join(line)

但是,它不使用特定数量的哈希作为输出。也许这是你们的要求之一,不知道...

只要step值是 的整数部分,它就应该产生重复模式math.pi

于 2012-04-23T16:00:03.340 回答
2

这是我的方法。它可能与其他任何人没有本质上的不同,但我写了它,所以它是这样的:

上半部分是配置。下半部分是动作。

from math import cos, sin, pi

length = 50
width = 30
thickness = 10
rotation = 0.15
strands = [0, 2 * pi / 3]
strand_char = "#"

radius = width / 2
for line in range(length):
    output = [" "] * (width + thickness + 2)
    total_rotation = -line * rotation
    sorted_strands = sorted(strands, key=lambda s: cos(total_rotation + s))
    for strand_offset in sorted_strands:
        pos = int(radius * sin(total_rotation + strand_offset) + radius)
        output[pos : pos + thickness + 2] = " " + strand_char * thickness + " "
    print("".join(output))

输出:

                ##########  ##########    
             ##########      ##########   
           ##########         ##########  
         ##########           ##########  
       ##########             ##########  
     ##########               ##########  
    ##########               ##########   
  ##########                ##########    
  ##########               ##########     
 ##########               ##########      
 ##########             ##########        
 ##########           ##########          
 ##########         ##########            
  ##########      ##########              
   ##########  ##########                 
    ######## ##########                   
     ##### ##########                     
       # ##########                       
       ########## #                       
     ########## #####                     
    ########## ########                   
  ##########    ##########                
 ##########       ##########              
 ##########         ##########            
 ##########           ##########          
 ##########             ##########        
 ##########               ##########      
  ##########               ##########     
   ##########                ##########   
    ##########                ##########  
     ##########               ##########  
       ##########             ##########  
         ##########           ##########  
           ##########         ##########  
             ##########      ##########   
                ##########  ##########    
                  ######## ##########     
                    ##### ##########      
                      # ##########        
                      ########## #        
                    ########## #####      
                 ########## #########     
               ##########    ##########   
             ##########       ##########  
           ##########         ##########  
         ##########           ##########  
       ##########             ##########  
     ##########               ##########  
    ##########               ##########   
  ##########                ##########    
于 2012-04-23T16:11:09.690 回答
1
                 ########## ####
               ########## ########
             ##########  ###########
           ##########      ##########
         ##########         ##########
       ##########            #########
     ##########              #########
   ##########               ##########
  ##########               ##########
  ##########             ##########
  ##########           ##########
   ##########        ##########
     ###########   ##########
       ######### ##########
         ##### ##########
           # ##########
           ########## ###
         ########## #######
       ##########  ##########
     ##########      ##########
   ##########          ##########
  ##########             ##########
  ##########               ##########
  ##########                 ##########
   ##########                 ##########
     ##########               ##########
       ##########             ##########
         ##########          ##########
           ##########      ##########
             ##########  ##########
               ####### ##########
                 #### #########
                    ######### #

. . .

可悲的是,我希望这是我答案的总和。但我应该解释一下:当你对镶嵌进行更改时,你需要使用基本的重复单元(如果你修改它的镶嵌方式,你必须修改它的其他部分,但你没有这样做)。我把你的图案剪成我认为看起来像重复单元的东西,然后复制粘贴一次;当我对底部进行更改时,我对顶部进行了相同的更改。

<deep thinking>有时候不用想太多就能找到最简单的解决方案。</deep thinking>

不过,您绝对可以对 DNA 图像执行分色算法,将其转换为位图。(您可以对拥有版权的图像执行此操作。)如果您不喜欢使用相同的字符,您还可以使用 ascii 艺术生成器,您可以在网络和开源软件中找到数十个通过一些谷歌搜索。但是,这不在 StackOverflow 常见问题解答的范围内,所以我不会对此进行详细介绍,除了链接这篇关于矢量样式 ascii-art 转换的计算机科学论文:http://www.cse.cuhk .edu.hk/~ttwong/papers/asciiart/asciiart.pdf

于 2012-04-23T14:52:13.457 回答