2008年6月10日星期二

关于一道做错了的生物题

原题来自这里:
http://www.douban.com/group/topic/3408141/
其实题目来说,主要考的恐怕不是概率,所以我这么折腾,很多东西都是不靠题的。后来想明白了,我决定丢开原题,很邪恶的把它改成符合我解答的形式,嘿嘿嘿……
出自《遗传学》高等教育出版社
  假设SPOCK先生的父亲是在自火星的星际飞船“企业号”的船长,他有火星血统。表现出的特征有尖耳朵(由等位基因P决定)、无肾上腺(由等位基 因A决定)、心脏靠右(由等位基因R决定),这3个基因对于地球上相对的基因是显性,这3个基因位于同一对常染色体上,它们的连锁图如下(略过):
  如果SPOCK先生与一位地球上的女人结婚,不考虑干涉,则他们的孩子中有多少是
  a.三个性状都像火星人?
  b.火星人的耳朵和心脏,但是地球人的肾上腺?
  c.火星人的耳朵,但是地球人的心脏和肾上腺?


那么我的解答如下:

  我们假设有3种基因,它们存在显隐区分,设之为
  
  >>> P='Pp'
  >>> A='Aa'
  >>> R='Rr'
  
  在后面,我们以大写的字符数据指代显型基因,小写字符指代隐型。
  现在我们生成PAR基因的所有可能的组合(这里我犯了第一个错误,实际上这个个数是2的6次幂):
  >>> All_G = [p0+p1+a0+a1+r0+r1 for p0 in P for p1 in P for a0 in A for a1 in A for r0 in R for r1 in R]
  
  生成的All_G如下:
  
  ['PPAARR', 'PPAARr', 'PPAArR', 'PPAArr', 'PPAaRR', 'PPAaRr', 'PPAarR', 'PPAarr', 'PPaARR', 'PPaARr', 'PPaArR', 'PPaArr', 'PPaaRR', 'PPaaRr', 'PPaarR', 'PPaarr', 'PpAARR', 'PpAARr', 'PpAArR', 'PpAArr', 'PpAaRR', 'PpAaRr', 'PpAarR', 'PpAarr', 'PpaARR', 'PpaARr', 'PpaArR', 'PpaArr', 'PpaaRR', 'PpaaRr', 'PpaarR', 'Ppaarr', 'pPAARR', 'pPAARr', 'pPAArR', 'pPAArr', 'pPAaRR', 'pPAaRr', 'pPAarR', 'pPAarr', 'pPaARR', 'pPaARr', 'pPaArR', 'pPaArr', 'pPaaRR', 'pPaaRr', 'pPaarR', 'pPaarr', 'ppAARR', 'ppAARr', 'ppAArR', 'ppAArr', 'ppAaRR', 'ppAaRr', 'ppAarR', 'ppAarr', 'ppaARR', 'ppaARr', 'ppaArR', 'ppaArr', 'ppaaRR', 'ppaaRr', 'ppaarR', 'ppaarr']
  
  >>> len(All_G)
  64
  
  但是实际上这只是一个全组合,并不符合我们的要求,我们需要找出所有的全显式基因组合。
  
  这里先定义一个判断基因位是否为显性的函数:
  
  >>> def isV(g): return (g[0].isupper() or g[1].isupper())
  
  这样就很容易定义一个判断基因是否全显性的函数:
  
  >>> def is_all(g): return isV(g[:2]) and isV(g[2:4]) and isV(g[4:])
  
  据此我们得出SPOCK船长可能拥有的PAR基因的所有组合:
  
  >>> SPOCK = [g for g in All_G if is_all(g)]
  >>> SPOCK
  ['PPAARR', 'PPAARr', 'PPAArR', 'PPAaRR', 'PPAaRr', 'PPAarR', 'PPaARR', 'PPaARr', 'PPaArR', 'PpAARR', 'PpAARr', 'PpAArR', 'PpAaRR', 'PpAaRr', 'PpAarR', 'PpaARR', 'PpaARr', 'PpaArR', 'pPAARR', 'pPAARr', 'pPAArR', 'pPAaRR', 'pPAaRr', 'pPAarR', 'pPaARR', 'pPaARr', 'pPaArR']
  
  实际上SPOCK船长的基因有27种可能:
  
  >>> len(SPOCK)
  27
  
  这是因为每个基因对,有3种组合方式可以呈现显性。于是这里是3*3*3。
  
  那么他的后代继承某一种组合的奇数位或偶数位。考虑到SPOCK船长的地球女性配偶只拥有隐性基因,这里只需考虑SPOCK的基因单倍体就可以了,我们求得SPOCK船长给后代所有的PAR传承可能:
  
  >>> SPOCK_GEN = [spock[i]+spock[2+i]+spock[4+i] for i in (0, 1) for spock in SPOCK]
  
  >>> SPOCK_GEN
  ['PAR', 'PAR', 'PAr', 'PAR', 'PAR', 'PAr', 'PaR', 'PaR', 'Par', 'PAR', 'PAR', 'PAr', 'PAR', 'PAR', 'PAr', 'PaR', 'PaR', 'Par', 'pAR', 'pAR', 'pAr', 'pAR', 'pAR', 'pAr', 'paR', 'paR', 'par', 'PAR', 'PAr', 'PAR', 'PaR', 'Par', 'PaR', 'PAR', 'PAr', 'PAR', 'pAR', 'pAr', 'pAR', 'paR', 'par', 'paR', 'pAR', 'pAr', 'pAR', 'PAR', 'PAr', 'PAR', 'PaR', 'Par', 'PaR', 'PAR', 'PAr', 'PAR']
  
  
  显然,这个数目应该是27*2=54:
  
  >>> len(SPOCK_GEN)
  54
  
  
  剩下就是简单粗暴的数数了,三个基因位都呈显式继承的可能有:
  
  >>> all_like_spock = [gen for gen in SPOCK_GEN if gen.isupper()]
  >>> all_like_spock
  ['PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR', 'PAR']
  >>> len(all_like_spock)
  16
  
  共16种,那么16/54消元得到8/27,同理,PR显性,A隐性的组合数:
  
  >>> PaR_gen = [gen for gen in SPOCK_GEN if gen[0].isupper() and gen[1].islower() and gen[2].isupper()]
  >>> PaR_gen
  ['PaR', 'PaR', 'PaR', 'PaR', 'PaR', 'PaR', 'PaR', 'PaR']
  >>> len(PaR_gen)
  8
  
  8/54消元得到4/27。
  
  而P呈显性,AR呈隐性的数目为:
  
  >>> Par_gen = [gen for gen in SPOCK_GEN if gen[0].isupper() and gen[1:].islower()]
  >>> Par_gen
  ['Par', 'Par', 'Par', 'Par']
  >>> len(Par_gen)
  4
  
  消元得到 2/27。
  
  BTW,数数的时候我写得太罗嗦了,我自己刚发现,应该直接 if gen == 'PaR'这样写的……


补:其实,如果不考虑专业的生物知识,这个题有一个有趣的数学变种--如果三个基因在三条不同的常染色体上,那么,以原题的题目,就会出现一些复杂的变化。以后有机会我们在填坑……不对,再挖坑……也不对……总之,下次再说吧……