태그 보관물: ascii-art

ascii-art

mtDNA 돌연변이 트리

배경:

MtDNA는 인간 DNA의 일부로 어머니에서 어린이로 전달되며 거의 돌연변이가 없습니다. 이것은 모든 인간에게 사실이기 때문에 모계 조상을 통해 모든 인간이 가상의 EVE로 거슬러 올라가는 방법을 시각화하는 거대한 나무를 만들 수 있습니다. 아이가 태어날 때 MtDNA의 모든 돌연변이는 나무의 부모 가지에서 새로운 하위 가지를 만듭니다.

미토콘드리아 DNA (mtDNA)에 대한 자세한 내용은 여기 ( https://en.wikipedia.org/wiki/Mitochondrial_DNA )를 참조 하십시오.

객관적인:

귀하의 프로그램은 mtDNA 트리 분기 돌연변이 카운트 목록을 제공받으며 프로그램은 그 트리 뷰를 제공해야합니다

입력 및 출력 예 :

입력은 각 분기에 대한 행이있는 3 열 세미콜론으로 구분 된 테이블입니다. 예:

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 열 (변이의 수) :

세 번째 열은 특정 가지가 뿌리에서 세었던 돌연변이의 총 수입니다. 휴먼 mtDNA는 가상 모근 (Human / chimp ancestor EVE)에서 한 줄로 100 번 이상 돌연변이를 일으키지 않았지만 프로그램은 최대 999 개의 3 자리 돌연변이를 처리 할 수 ​​있어야합니다.

입력 값에서 상위 돌연변이 수에서 돌연변이 수를 빼서 고유 돌연변이의 분기 수를 계산할 수 있습니다.

출력 : 세부 사항

입력 설명에 따라 입력이 유효하지 않은 경우 프로그램은 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 가지 유형의 입력 라인이 있습니다. 분기 이름에 ‘문자 또는 NL 접미어가있는 1을 입력하면 행의 가장 오른쪽에있는 수평선을 채우지 말고 마지막 하위 분기의 끝으로 끝나야 합니다. 이 예에서는 다음 분기에 적용됩니다.

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

바라건대 입력 및 출력 예제가 트리를 그리는 방법에 대한 추가 질문에 대답하기를 바랍니다. 로직을 이해하는 데 어려움이 있다고 생각하십시오.

영감

당신은 영감을 내 (UN-golfed) 자바 스크립트 버전을 사용해 환영 : http://artificial.se/DNA/mtDNAmutationTree3.html은 (는 오류 검사 부족, 일부 통계는이 특정 문제의 일부가 아닌이 추가됩니다) .

완전한 mtDNA 트리 버전 ( http://www.phylotree.org/ mtDNA 트리 빌드 16 (2014 년 2 월 19 일) 기준)은 다음에서 찾을 수 있습니다.

http://artificial.se/DNA/mtDNAfull.html

전체 트리에 사용 된 데이터 파일 :

http://artificial.se/DNA/mtDNA_full.txt

이것은 코드 골프 도전입니다.



답변

파이썬 3, 925 바이트

예, 1KB 미만! 아마 아직도 골프를위한 방 …

import sys
class L:
 def __init__(x,**k):x.__dict__.update(k)
m={}
def e(x):print('ERROR: '+x);exit()
try:
 for x in sys.stdin:a,b,c=x.split(';');m[a]=L(s=a,p=b,m=int(c),l=0)
except:e('Invalid input')
a=set()
def k(x):
 if x.l<0:e('Endless loop')
 if x.l<1:y=m.get(x.p);x.l=-1;k(y)if y else a.add(x.p);x.l=1
for x in m:k(m[x])
r=L(s=a.pop(),p=0,m=0)
if a:e('Multiple roots')
m[r.s]=r
c={}
def u(x):
 c[x.s]=[m[y]for y in m if m[y].p==x.s];x.x=x.m
 for y in c[x.s]:u(y);x.x=max(x.x,y.x)
u(r)
o=[]
def f(p,x,o=o):
 d=x.m-p.m;j=p.m+r.x-x.x;s=x.s;x.i=len(o);l=sorted(c[s],key=lambda t:(t.x,t.s));q=' '*j+'└'+'♦'*(d-1);z='─'
 if"'"in s or s[-2:]=='NL'or x==r:q+=z*(x.x-l[0].x);z=' '
 o+=list("%3d│ "%x.m+q+z*(r.x-len(q))+' %-20s[%3d][%3d]'%(s,d,x.x)),;j+=5;o[p.i][j]='┐┬'[o[p.i][j]in'─┬']
 for i in range(p.i+1,x.i):o[i][j]='├│'[o[i][j]in' │']
 for y in l:f(x,y)
f(r,r)
print('\n'.join(''.join(x)for x in o))

답변