-
Completing a TreeBioinformatics/Rosalind 2019. 6. 17. 23:37
http://rosalind.info/problems/tree/
ROSALIND | Completing a Tree
It appears that your browser has JavaScript disabled. Rosalind requires your browser to be JavaScript enabled. Completing a Tree solved by 2689 2012년 7월 11일 12:00:00 오전 by Rosalind Team Topics: Graph Algorithms, Phylogeny The Tree of Life Figure 1. A phylo
rosalind.info
adjacency list를 입력으로 주고 그 리스트들을 하나의 tree로 만들려면 몇개의 최소 edge가 필요한지 묻는 문제이다. cluster별로 분류한 후 cluster의 갯수 - 1을 구하면 된다.
from functools import reduce with open('rosalind_tree.txt') as f: nodes, *edges = f.read().strip().split('\n') segments = [] adj_nodes = reduce(lambda a, b: set(a).union(set(b)), map(lambda x: x.split(' '), edges)) for node in range(1, int(nodes) + 1): if str(node) not in adj_nodes: segments.append(set([str(node)])) for edge in edges: new_cluster = True e1, e2 = edge.split(' ') for segment in segments: if e1 in segment or e2 in segment: segment.add(e1) segment.add(e2) new_cluster = False if new_cluster is True: segments.append(set([e1, e2])) def merge_dup(segments): new_segments = segments[0:] for seg1 in segments: for seg2 in segments: if seg1 != seg2 and len(seg1.intersection(seg2)) > 0: new_seg = seg1.union(seg2) new_segments.remove(seg1) new_segments.remove(seg2) new_segments.append(new_seg) return new_segments return segments prev_seg_len = 0 while prev_seg_len != len(segments): prev_seg_len = len(segments) segments = merge_dup(segments) print(len(segments) - 1)
for node in range(1, int(nodes) + 1): if str(node) not in adj_nodes: segments.append(set([str(node)]))
문제에선 입력의 첫번째줄에 노드의 갯수를 주는데 adjacency list에 없는 노드들도 있으므로 해당 노드들은 미리 clusters(segment)에 추가해준다.
for edge in edges: new_cluster = True e1, e2 = edge.split(' ') for segment in segments: if e1 in segment or e2 in segment: segment.add(e1) segment.add(e2) new_cluster = False if new_cluster is True: segments.append(set([e1, e2]))
그리고 adjecency list를 순회하며 segment에 이미 해당 edge를 구성하는 node가 있으면 해당 segment에 추가하고 없으면 새로운 segment를 생성하여 segments에 추가한다.
def merge_dup(segments): new_segments = segments[0:] for seg1 in segments: for seg2 in segments: if seg1 != seg2 and len(seg1.intersection(seg2)) > 0: new_seg = seg1.union(seg2) new_segments.remove(seg1) new_segments.remove(seg2) new_segments.append(new_seg) return new_segments return segments
이 부분이 중요한데 adjecency list를 순회하면서 segments에 추가하면 adjecency list가 정렬되어있다면 별 문제가 안되지만 정렬되어있지 않다면 같은 node를 포함한, 즉 같은 segment가 다른 segment로 추가될 수 있다. 예를들어
1 2 3 4 2 3
이 입력으로 들어온다면
[{1,2}] -> [{1,2}, {3,4}] -> [{1,2,3}, {3,4}]
이런식으로 segments가 생성이 될것이다. 그러므로 merge_dup 함수를 만들어 같은 segment지만 분리된것들을 합쳐주었다.
'Bioinformatics > Rosalind' 카테고리의 다른 글
Finding a Spliced Motif (0) 2019.06.19 k-Mer Composition (0) 2019.06.18 Genome Assembly as Shortest Superstring (0) 2019.06.13 Independent Alleles (0) 2019.06.08 Locating Restriction Sites (0) 2019.03.04 댓글