Skip to content

Commit c8f70ae

Browse files
feat(ancestors): add python solution
1 parent 3e7dd5d commit c8f70ae

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

ancestors/ancestors.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
def create_ancestor_graph(relationships):
2+
ancestor_graph = {}
3+
for parent, child in relationships:
4+
if parent not in ancestor_graph:
5+
ancestor_graph[parent] = []
6+
7+
if child not in ancestor_graph:
8+
ancestor_graph[child] = []
9+
10+
ancestor_graph[child].append(parent)
11+
12+
return ancestor_graph
13+
14+
15+
def earliest_ancestor(child, ancestor_graph):
16+
if child not in ancestor_graph or not ancestor_graph[child]:
17+
return -1
18+
19+
queue = [child]
20+
visited = set()
21+
22+
while queue:
23+
tempq = []
24+
for person in queue:
25+
for ancestor in ancestor_graph[person]:
26+
if ancestor not in visited:
27+
visited.add(ancestor)
28+
tempq.append(ancestor)
29+
30+
if not tempq:
31+
return queue[0]
32+
33+
queue = tempq
34+
35+
return -1
36+
37+
38+
def get_all_ancestors(child, ancestor_graph):
39+
if child not in ancestor_graph or not ancestor_graph[child]:
40+
return set()
41+
42+
queue = [child]
43+
visited = set()
44+
45+
while queue:
46+
tempq = []
47+
for person in queue:
48+
for ancestor in ancestor_graph[person]:
49+
if ancestor not in visited:
50+
visited.add(ancestor)
51+
tempq.append(ancestor)
52+
53+
queue = tempq
54+
55+
return visited
56+
57+
58+
def has_common_ancestor(child1, child2, ancestor_graph):
59+
child1_ancestors = get_all_ancestors(child1, ancestor_graph)
60+
child2_ancestors = get_all_ancestors(child2, ancestor_graph)
61+
62+
return len(child1_ancestors & child2_ancestors) > 0
63+
64+
65+
def one_or_zero_parents(ancestor_graph):
66+
children = []
67+
for child in ancestor_graph.keys():
68+
if len(ancestor_graph[child]) <= 1:
69+
children.append(child)
70+
return children
71+
72+
73+
parent_child_pairs1 = [
74+
(2, 3), (3, 15), (3, 6), (5, 6), (5, 7),
75+
(4, 5), (4, 8), (4, 9), (9, 11), (14, 4),
76+
]
77+
ancestor_graph1 = create_ancestor_graph(parent_child_pairs1)
78+
print(earliest_ancestor(8, ancestor_graph1)) # 14
79+
print(earliest_ancestor(7, ancestor_graph1)) # 14
80+
print(earliest_ancestor(6, ancestor_graph1)) # 14
81+
print(earliest_ancestor(15, ancestor_graph1)) # 2
82+
print(earliest_ancestor(14, ancestor_graph1)) # -1
83+
print()
84+
print(has_common_ancestor(3, 8, ancestor_graph1)) # false
85+
print(has_common_ancestor(5, 8, ancestor_graph1)) # true
86+
print(has_common_ancestor(6, 8, ancestor_graph1)) # true
87+
print(has_common_ancestor(6, 9, ancestor_graph1)) # true
88+
print(has_common_ancestor(1, 3, ancestor_graph1)) # false
89+
print(has_common_ancestor(7, 11, ancestor_graph1)) # true
90+
print(has_common_ancestor(6, 5, ancestor_graph1)) # true
91+
print(has_common_ancestor(5, 6, ancestor_graph1)) # true
92+
print()
93+
print(one_or_zero_parents(ancestor_graph1))
94+
print()
95+
96+
parent_child_pairs2 = [
97+
(2, 3), (3, 15), (3, 6), (5, 6), (5, 7),
98+
(4, 5), (4, 8), (4, 9), (9, 11), (14, 2),
99+
]
100+
ancestor_graph2 = create_ancestor_graph(parent_child_pairs2)
101+
print(earliest_ancestor(8, ancestor_graph2)) # 4
102+
print(earliest_ancestor(7, ancestor_graph2)) # 4
103+
print(earliest_ancestor(6, ancestor_graph2)) # 14
104+
print(earliest_ancestor(15, ancestor_graph2)) # 14
105+
print(earliest_ancestor(14, ancestor_graph2)) # -1
106+
print()
107+
print(has_common_ancestor(4, 12, ancestor_graph2)) # false
108+
print(has_common_ancestor(11, 6, ancestor_graph2)) # true
109+
print(has_common_ancestor(11, 3, ancestor_graph2)) # false
110+
print()
111+
print(one_or_zero_parents(ancestor_graph2))

0 commit comments

Comments
 (0)