背景:
MtDNA是人类DNA的一部分,是从母亲传给孩子的,很少发生突变。由于这对所有人类都是如此,因此有可能创建一棵巨大的树,以可视化方式将所有人类如何通过其母系关系彼此联系,一直到假设的EVE。当孩子出生时,MtDNA中的每个突变都会从其父树中的分支创建一个新的子分支。
在此处了解有关线粒体DNA(mtDNA)的更多信息:https://en.wikipedia.org/wiki/线粒体DNA
目的:
您的程序将获得mtDNA树枝突变计数列表,并且您的程序应提供它的树状视图
输入和输出示例:
输入是一个三列的分号分隔表,每个分支都有一行。例:
L0a'b'f'k;L0;14
L0a'b'f;L0a'b'f'k;23
L0;mtEVE;10
L0a'b;L0a'b'f;30
L0a;L0a'b;38
L0a1'4;L0a;39
L0a1;L0a1'4;40
L0a1a;L0a1;42
L0a1a NL;L0a1a;43
L0a1a1;L0a1a NL;44
L0a1a2;L0a1a NL;45
L0a1a3;L0a1a NL;44
L0a1 NL;L0a1;41
L0a1b;L0a1 NL;44
L0a1b NL;L0a1b;45
L0a1b1;L0a1b NL;46
L0a1b1a;L0a1b1;47
L0a1b1a1;L0a1b1a;48
L0a1b2;L0a1b NL;48
L0a1b2a;L0a1b2;50
L0a1c;L0a1 NL;45
L0a1d;L0a1 NL;44
L0a4;L0a1'4;55
L0a2;L0a;47
L0a2a;L0a2;49
L0a2a1;L0a2a;50
L0a2a1a;L0a2a1;51
L0a2a1a1;L0a2a1a;53
L0a2a1a2;L0a2a1a;53
L0a2a2;L0a2a;53
L0a2a2a;L0a2a2;54
L0a2b;L0a2;57
L0a2b1;L0a2b;58
L0a2c;L0a2;60
L0a2d;L0a2;49
L0a3;L0a;53
L0b;L0a'b;48
L0f;L0a'b'f;37
L0f1;L0f;61
L0f2;L0f;41
L0f2a;L0f2;46
L0f2a1;L0f2a;59
L0f2b;L0f2;63
L0k;L0a'b'f'k;39
L0k1;L0k;48
L0k2;L0k;54
L0d;L0;21
L0d1'2;L0d;25
L0d1;L0d1'2;30
L0d1 NL;L0d1;31
L0d1a;L0d1 NL;38
L0d1a1;L0d1a;41
L0d1c;L0d1 NL;39
L0d1c1;L0d1c;45
L0d1c1a;L0d1c1;46
L0d1c1b;L0d1c1;46
L0d1b;L0d1 NL;36
L0d1b1;L0d1b;40
L0d2;L0d1'2;31
L0d2a'b;L0d2;32
L0d2a;L0d2a'b;42
L0d2a1;L0d2a;43
L0d2b;L0d2a'b;46
L0d2c;L0d2;45
L0d3;L0d;39
您的程序应输出从左到右的树状视图,其中包括一些基于输入的数字。根据示例输入,这是有效的输出:
0│ ┐ mtEVE [ 0][ 63]
10│ └♦♦♦♦♦♦♦♦♦┬────────────────┬─────────────────────────────────── L0 [ 10][ 63]
21│ │ └♦♦♦♦♦♦♦♦♦♦┬──────┬───────────────── L0d [ 11][ 46]
39│ │ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦ L0d3 [ 18][ 39]
25│ │ └♦♦♦┐ L0d1'2 [ 4][ 46]
30│ │ ├♦♦♦♦┬─────────────── L0d1 [ 5][ 46]
31│ │ │ └┬────┬┐ L0d1 NL [ 1][ 46]
36│ │ │ │ │└♦♦♦♦┬─── L0d1b [ 5][ 40]
40│ │ │ │ │ └♦♦♦ L0d1b1 [ 4][ 40]
38│ │ │ │ └♦♦♦♦♦♦┬── L0d1a [ 7][ 41]
41│ │ │ │ └♦♦ L0d1a1 [ 3][ 41]
39│ │ │ └♦♦♦♦♦♦♦┬────── L0d1c [ 8][ 46]
45│ │ │ └♦♦♦♦♦┬ L0d1c1 [ 6][ 46]
46│ │ │ ├ L0d1c1a [ 1][ 46]
46│ │ │ └ L0d1c1b [ 1][ 46]
31│ │ └♦♦♦♦♦┬┬───────────── L0d2 [ 6][ 46]
45│ │ │└♦♦♦♦♦♦♦♦♦♦♦♦♦ L0d2c [ 14][ 45]
32│ │ └┬──┐ L0d2a'b [ 1][ 46]
42│ │ │ └♦♦♦♦♦♦♦♦♦┬ L0d2a [ 10][ 43]
43│ │ │ └ L0d2a1 [ 1][ 43]
46│ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦ L0d2b [ 14][ 46]
14│ └♦♦♦┬────────┐ L0a'b'f'k [ 4][ 63]
39│ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦┬─────┬──────── L0k [ 25][ 54]
48│ │ │ └♦♦♦♦♦♦♦♦ L0k1 [ 9][ 48]
54│ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦ L0k2 [ 15][ 54]
23│ └♦♦♦♦♦♦♦♦┬──┐ L0a'b'f [ 9][ 63]
30│ │ └♦♦♦♦♦♦┬───────────┐ L0a'b [ 7][ 60]
48│ │ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦ L0b [ 18][ 48]
38│ │ └♦♦♦♦♦♦♦┬────┬─┬────────────── L0a [ 8][ 60]
53│ │ │ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦ L0a3 [ 15][ 53]
39│ │ │ └┬────┐ L0a1'4 [ 1][ 55]
40│ │ │ │ └┬────┬──── L0a1 [ 1][ 50]
42│ │ │ │ │ └♦┬── L0a1a [ 2][ 45]
43│ │ │ │ │ └┬┐ L0a1a NL [ 1][ 45]
44│ │ │ │ │ │├ L0a1a1 [ 1][ 44]
44│ │ │ │ │ │└ L0a1a3 [ 1][ 44]
45│ │ │ │ │ └♦ L0a1a2 [ 2][ 45]
41│ │ │ │ └┬────┬┐ L0a1 NL [ 1][ 50]
44│ │ │ │ │ │└♦♦ L0a1d [ 3][ 44]
45│ │ │ │ │ └♦♦♦ L0a1c [ 4][ 45]
44│ │ │ │ └♦♦┬───── L0a1b [ 3][ 50]
45│ │ │ │ └┬─┐ L0a1b NL [ 1][ 50]
46│ │ │ │ │ └┬─ L0a1b1 [ 1][ 48]
47│ │ │ │ │ └┬ L0a1b1a [ 1][ 48]
48│ │ │ │ │ └ L0a1b1a1 [ 1][ 48]
48│ │ │ │ └♦♦┬─ L0a1b2 [ 3][ 50]
50│ │ │ │ └♦ L0a1b2a [ 2][ 50]
55│ │ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦ L0a4 [ 16][ 55]
47│ │ └♦♦♦♦♦♦♦♦┬─┬───┬────┬─ L0a2 [ 9][ 60]
49│ │ │ │ │ └♦ L0a2d [ 2][ 49]
49│ │ │ │ └♦┬┬─── L0a2a [ 2][ 54]
50│ │ │ │ │└┬── L0a2a1 [ 1][ 53]
51│ │ │ │ │ └┬─ L0a2a1a [ 1][ 53]
53│ │ │ │ │ ├♦ L0a2a1a1 [ 2][ 53]
53│ │ │ │ │ └♦ L0a2a1a2 [ 2][ 53]
53│ │ │ │ └♦♦♦┬ L0a2a2 [ 4][ 54]
54│ │ │ │ └ L0a2a2a [ 1][ 54]
57│ │ │ └♦♦♦♦♦♦♦♦♦┬ L0a2b [ 10][ 58]
58│ │ │ └ L0a2b1 [ 1][ 58]
60│ │ └♦♦♦♦♦♦♦♦♦♦♦♦ L0a2c [ 13][ 60]
37│ └♦♦♦♦♦♦♦♦♦♦♦♦♦┬─┬─────────────────────── L0f [ 14][ 63]
61│ │ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦ L0f1 [ 24][ 61]
41│ └♦♦♦┬───┬───────────────── L0f2 [ 4][ 63]
46│ │ └♦♦♦♦┬──────────── L0f2a [ 5][ 59]
59│ │ └♦♦♦♦♦♦♦♦♦♦♦♦ L0f2a1 [ 13][ 59]
63│ └♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦ L0f2b [ 22][ 63]
输入:详细信息
输入表未按任何特定顺序排序。如果我们随机重新排列输入行,则输出应保持不变。
输入中的每一行代表一个mtDNA树枝或一个假设的树枝。输入表的长度可以是任意数量的行。
输入:详细信息-列A(分支名称):
第一列是实际的分支名称。该名称将输入线分为两组线型,应该以彼此不同的方式处理(稍后说明):
- 类型1:名称由任意
'
或后缀组成NL
- 类型2:名称不包含任何
'
或后缀NL
。
名称最多可包含20个字符。
输入:详细信息-列B(父分支名称):
第二列包含指向父分支名称的指针。多个行(分支)可以共享同一父级。输入表中总是有1个唯一的父分支名称,它们指向在输入行中未表示的父节点,该父分支名称是树的根。在示例输入中,它是指向根的第三行:mtEVE
。如果输入具有多个根或无限循环,则它是无效的输入。
输入:详细信息-C列(突变数):
第三列是特定分支从根开始计数的突变总数。从假设的母本根(人类/黑猩猩的祖先EVE)开始,人类mtDNA的单行突变没有超过100次,但是您的程序应该能够处理3位数的突变,最高可达999。
从输入中,您可以通过从父变量中减去突变数来计算唯一突变的分支数。
输出:详细信息
如果根据输入描述输入无效,则程序应输出3条不同错误消息中的1条。
- 错误消息1,如果输入具有多个根:
ERROR: Multiple roots
- 错误消息2,如果输入父指针循环:
ERROR: Endless loop
- 错误消息3,其他与输入有关的无效信息:
ERROR: Invalid input
如果输入没有错误,则程序应根据以下约束输出树:每行包括5个部分,A,B,C,D和E:
- A:5个字符,3个字符右对齐的突变数,一个竖线字符:
|
和1个空格 - B:[最大突变数]个字符,宽树+ 1个空格
- C:20个字符,左对齐分支名称
- D:封装在
[
和之间的分支的5个字符,3个字符的唯一突变的右对齐#]
。(下面将解释唯一的突变)。 - E:该分支以及封装在
[
和之间的所有子分支的总突变数的5个字符,右对齐的最大字符数为3个字符]
。
唯一突变的分支#是当前分支与其父分支具有的突变#之差。第一行是根,应该用0
#突变和#唯一突变表示。
输出:明细-行顺序/分类
如果两个或多个子分支共享同一个父分支,则分支按子分支最大总突变数的降序排列。在我们的示例中L0a1'4
,L0a3
并L0a2
共享父级:L0a
。
在树状视图中,从上到下的顺序是,子分支中括号内的总突变数的最大值:L0a3
(53),L0a1'4
(55),L0a2
(60)。
如果两个或多个子分支在子分支上共享相同的最大突变数,则它们将垂直对齐并从同一位置从其父分支分支,这些子分支之间的行顺序按字母顺序排列。
输出:详细信息-树(B部分)
树应与以下ascii字符可以得出:└
,─
,┬
,┐
,├
,│
,♦
树的逻辑是应表示所有突变。来自母体分支的分支:┬
或┐
代表1个突变。同一分支上的其他独特突变用:表示,♦
并且必须将它们左对齐并放在第一个子分支之前。
子分支从其父级沿x轴分支,其位置由所有后续子分支中的最大突变数确定。
如前所述,输入具有2种不同类型的输入线。键入1且分支名称中带有任何'字符或NL后缀,不应在其行的最右边填充水平线,而应┐
在最后一个子分支处以a结尾。在示例中,它应用于以下分支:
L0a'b'f'k;L0;14
L0a'b'f;L0a'b'f'k;23
L0a'b;L0a'b'f;30
L0a1'4;L0a;39
L0a1a NL;L0a1a;43
L0a1 NL;L0a1;41
L0a1b NL;L0a1b;45
L0d1'2;L0d;25
L0d1 NL;L0d1;31
L0d2a'b;L0d2;32
希望示例输入和输出能够回答有关如何绘制树的任何其他问题,将其视为弄清楚逻辑的挑战。
灵感
欢迎您试用我的(未发布的)JavaScript版本以获取灵感:http ://artificial.se/DNA/mtDNAmutationTree3.html (它没有错误检查功能,并且添加了一些统计信息,这些不是本次特殊挑战的一部分) 。
完整的mtDNA树版本[基于http://www.phylotree.org/ mtDNA树Build 16(2014年2月19日)]可在以下位置找到:
http://artificial.se/DNA/mtDNAfull.html
用于完整树的数据文件:
http://artificial.se/DNA/mtDNA_full.txt
这是一个代码高尔夫挑战。
L0a1'4
不是(55)而是(39),L0a2
不是(60)而是(47)...您能澄清一下吗?
L0d1
L0d2
根据排序规则,不应将其放置在前面:“ ...降序...”