Skip to content

Commit c888dc6

Browse files
committed
Add relative-distance
1 parent e8835c9 commit c888dc6

File tree

8 files changed

+355
-0
lines changed

8 files changed

+355
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,14 @@
733733
"prerequisites": [],
734734
"difficulty": 5
735735
},
736+
{
737+
"slug": "relative-distance",
738+
"name": "Relative Distance",
739+
"uuid": "7b9866ac-c408-4487-98cc-eca051df33ec",
740+
"practices": [],
741+
"prerequisites": [],
742+
"difficulty": 5
743+
},
736744
{
737745
"slug": "simple-linked-list",
738746
"name": "Simple Linked List",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Instructions
2+
3+
Your task is to determine the degree of separation between two individuals in a family tree.
4+
5+
- You will be given an input, with all parent names and their children.
6+
- Each name is unique, a child _can_ have one or two parents.
7+
- The degree of separation is defined as the shortest number of connections from one person to another.
8+
- If two individuals are not connected, return a value that represents "no known relationship."
9+
Please see the test cases for the actual implementation.
10+
11+
## Example
12+
13+
Given the following family tree:
14+
15+
```text
16+
┌──────────┐ ┌──────────┐ ┌───────────┐
17+
│ Helena │ │ Erdős │ │ Shusaku │
18+
└───┬───┬──┘ └─────┬────┘ └──────┬────┘
19+
┌───┘ └───────┐ └──────┬──────┘
20+
▼ ▼ ▼
21+
┌──────────┐ ┌────────┐ ┌──────────┐
22+
│ Isla │ │ Tariq │ │ Kevin │
23+
└────┬─────┘ └────┬───┘ └──────────┘
24+
▼ ▼
25+
┌─────────┐ ┌────────┐
26+
│ Uma │ │ Morphy │
27+
└─────────┘ └────────┘
28+
```
29+
30+
The degree of separation between Tariq and Uma is 3 (Tariq → Helena → Isla → Uma).
31+
There's no known relationship between Isla and [Kevin][six-bacons], as there is no connection in the given data.
32+
The degree of separation between Uma and Isla is 1.
33+
34+
~~~~exercism/note
35+
Isla and Tariq are siblings and have a separation of 1.
36+
Similarly, this implementation would report a separation of 2 from you to your father's brother.
37+
~~~~
38+
39+
[six-bacons]: https://en.m.wikipedia.org/wiki/Six_Degrees_of_Kevin_Bacon
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Introduction
2+
3+
You've been hired to develop **Noble Knots**, the hottest new dating app for nobility!
4+
With centuries of royal intermarriage, things have gotten… _complicated_.
5+
To avoid any _oops-we're-twins_ situations, your job is to build a system that checks how closely two people are related.
6+
7+
Noble Knots is inspired by Iceland's "[Islendinga-App][islendiga-app]," which is backed up by a database that traces all known family connections between Icelanders from the time of the settlement of Iceland.
8+
Your algorithm will determine the **degree of separation** between two individuals in the royal family tree.
9+
10+
Will your app help crown a perfect match?
11+
12+
[islendiga-app]: http://www.islendingaapp.is/information-in-english/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"BNAndras"
4+
],
5+
"files": {
6+
"solution": [
7+
"relative_distance.vim"
8+
],
9+
"test": [
10+
"relative_distance.vader"
11+
],
12+
"example": [
13+
".meta/example.vim"
14+
]
15+
},
16+
"blurb": "Given a family tree, calculate the degree of separation.",
17+
"source": "vaeng",
18+
"source_url": "https://github.com/exercism/problem-specifications/pull/2537"
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
function! DegreeOfSeparation(familyTree, personA, personB) abort
2+
if a:personA ==# a:personB
3+
return 0
4+
endif
5+
6+
let l:neighbors = {}
7+
for [l:parent, l:children] in items(a:familyTree)
8+
let l:neighbors[l:parent] = get(l:neighbors, l:parent, [])
9+
for l:child in l:children
10+
let l:neighbors[l:child] = get(l:neighbors, l:child, [])
11+
call add(l:neighbors[l:parent], l:child)
12+
call add(l:neighbors[l:child], l:parent)
13+
endfor
14+
15+
" Add links only between siblings
16+
if len(l:children) > 1
17+
for l:child1 in l:children
18+
for l:child2 in l:children
19+
if l:child1 != l:child2 && index(l:neighbors[l:child1], l:child2) == -1
20+
call add(l:neighbors[l:child1], l:child2)
21+
endif
22+
endfor
23+
endfor
24+
endif
25+
endfor
26+
27+
if !has_key(l:neighbors, a:personA) || !has_key(l:neighbors, a:personB)
28+
return -1
29+
endif
30+
31+
let l:queue = [[a:personA, 0]]
32+
33+
let l:visited = {}
34+
let l:visited[a:personA] = 1
35+
36+
while !empty(l:queue)
37+
let [l:current, l:degree] = remove(l:queue, 0)
38+
39+
if l:current ==# a:personB
40+
return l:degree
41+
endif
42+
43+
let l:unvisited = filter(l:neighbors[l:current], '!has_key(visited, v:val)')
44+
for l:neighbor in l:unvisited
45+
call add(l:queue, [l:neighbor, l:degree + 1])
46+
let l:visited[l:neighbor] = 1
47+
endfor
48+
endwhile
49+
50+
return -1
51+
endfunction
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[4a1ded74-5d32-47fb-8ae5-321f51d06b5b]
13+
description = "Direct parent-child relation"
14+
15+
[30d17269-83e9-4f82-a0d7-8ef9656d8dce]
16+
description = "Sibling relationship"
17+
18+
[8dffa27d-a8ab-496d-80b3-2f21c77648b5]
19+
description = "Two degrees of separation, grandchild"
20+
21+
[34e56ec1-d528-4a42-908e-020a4606ee60]
22+
description = "Unrelated individuals"
23+
24+
[93ffe989-bad2-48c4-878f-3acb1ce2611b]
25+
description = "Complex graph, cousins"
26+
27+
[2cc2e76b-013a-433c-9486-1dbe29bf06e5]
28+
description = "Complex graph, no shortcut, far removed nephew"
29+
30+
[46c9fbcb-e464-455f-a718-049ea3c7400a]
31+
description = "Complex graph, some shortcuts, cross-down and cross-up, cousins several times removed, with unrelated family tree"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
Execute (Direct parent-child relation):
2+
let g:familyTree = {
3+
\ 'Vera': ['Tomoko'],
4+
\ 'Tomoko': ['Aditi']}
5+
AssertEqual 1, DegreeOfSeparation(g:familyTree, 'Vera', 'Tomoko')
6+
7+
Execute (Sibling relationship):
8+
let g:familyTree = {'Dalia': ['Olga', 'Yassin']}
9+
AssertEqual 1, DegreeOfSeparation(g:familyTree, 'Olga', 'Yassin')
10+
11+
Execute (Two degrees of separation, grandchild):
12+
let g:familyTree = {
13+
\ 'Khadija': ['Mateo'],
14+
\ 'Mateo': ['Rami']}
15+
AssertEqual 2, DegreeOfSeparation(g:familyTree, 'Khadija', 'Rami')
16+
17+
Execute (Unrelated individuals):
18+
let g:familyTree = {
19+
\ 'Priya': ['Rami'],
20+
\ 'Kaito': ['Elif']}
21+
AssertEqual -1, DegreeOfSeparation(g:familyTree, 'Priya', 'Kaito')
22+
23+
Execute (Complex graph, cousins):
24+
let g:familyTree = {
25+
\ 'Aiko': ['Bao', 'Carlos'],
26+
\ 'Bao': ['Dalia', 'Elias'],
27+
\ 'Carlos': ['Fatima', 'Gustavo'],
28+
\ 'Dalia': ['Hassan', 'Isla'],
29+
\ 'Elias': ['Javier'],
30+
\ 'Fatima': ['Khadija', 'Liam'],
31+
\ 'Gustavo': ['Mina'],
32+
\ 'Hassan': ['Noah', 'Olga'],
33+
\ 'Isla': ['Pedro'],
34+
\ 'Javier': ['Quynh', 'Ravi'],
35+
\ 'Khadija': ['Sofia'],
36+
\ 'Liam': ['Tariq', 'Uma'],
37+
\ 'Mina': ['Viktor', 'Wang'],
38+
\ 'Noah': ['Xiomara'],
39+
\ 'Olga': ['Yuki'],
40+
\ 'Pedro': ['Zane', 'Aditi'],
41+
\ 'Quynh': ['Boris'],
42+
\ 'Ravi': ['Celine'],
43+
\ 'Sofia': ['Diego', 'Elif'],
44+
\ 'Tariq': ['Farah'],
45+
\ 'Uma': ['Giorgio'],
46+
\ 'Viktor': ['Hana', 'Ian'],
47+
\ 'Wang': ['Jing'],
48+
\ 'Xiomara': ['Kaito'],
49+
\ 'Yuki': ['Leila'],
50+
\ 'Zane': ['Mateo'],
51+
\ 'Aditi': ['Nia'],
52+
\ 'Boris': ['Oscar'],
53+
\ 'Celine': ['Priya'],
54+
\ 'Diego': ['Qi'],
55+
\ 'Elif': ['Rami'],
56+
\ 'Farah': ['Sven'],
57+
\ 'Giorgio': ['Tomoko'],
58+
\ 'Hana': ['Umar'],
59+
\ 'Ian': ['Vera'],
60+
\ 'Jing': ['Wyatt'],
61+
\ 'Kaito': ['Xia'],
62+
\ 'Leila': ['Yassin'],
63+
\ 'Mateo': ['Zara'],
64+
\ 'Nia': ['Antonio'],
65+
\ 'Oscar': ['Bianca'],
66+
\ 'Priya': ['Cai'],
67+
\ 'Qi': ['Dimitri'],
68+
\ 'Rami': ['Ewa'],
69+
\ 'Sven': ['Fabio'],
70+
\ 'Tomoko': ['Gabriela'],
71+
\ 'Umar': ['Helena'],
72+
\ 'Vera': ['Igor'],
73+
\ 'Wyatt': ['Jun'],
74+
\ 'Xia': ['Kim'],
75+
\ 'Yassin': ['Lucia'],
76+
\ 'Zara': ['Mohammed']}
77+
AssertEqual 9, DegreeOfSeparation(g:familyTree, 'Dimitri', 'Fabio')
78+
79+
Execute (Complex graph, no shortcut, far removed nephew):
80+
let g:familyTree = {
81+
\ 'Mina': ['Viktor', 'Wang'],
82+
\ 'Olga': ['Yuki'],
83+
\ 'Javier': ['Quynh', 'Ravi'],
84+
\ 'Tariq': ['Farah'],
85+
\ 'Viktor': ['Hana', 'Ian'],
86+
\ 'Diego': ['Qi'],
87+
\ 'Carlos': ['Fatima', 'Gustavo'],
88+
\ 'Hana': ['Umar'],
89+
\ 'Jing': ['Wyatt'],
90+
\ 'Sven': ['Fabio'],
91+
\ 'Zane': ['Mateo'],
92+
\ 'Isla': ['Pedro'],
93+
\ 'Quynh': ['Boris'],
94+
\ 'Kaito': ['Xia'],
95+
\ 'Liam': ['Tariq', 'Uma'],
96+
\ 'Priya': ['Cai'],
97+
\ 'Qi': ['Dimitri'],
98+
\ 'Wang': ['Jing'],
99+
\ 'Yuki': ['Leila'],
100+
\ 'Xia': ['Kim'],
101+
\ 'Pedro': ['Zane', 'Aditi'],
102+
\ 'Uma': ['Giorgio'],
103+
\ 'Giorgio': ['Tomoko'],
104+
\ 'Gustavo': ['Mina'],
105+
\ 'Sofia': ['Diego', 'Elif'],
106+
\ 'Leila': ['Yassin'],
107+
\ 'Umar': ['Helena'],
108+
\ 'Aiko': ['Bao', 'Carlos'],
109+
\ 'Fatima': ['Khadija', 'Liam'],
110+
\ 'Oscar': ['Bianca'],
111+
\ 'Wyatt': ['Jun'],
112+
\ 'Ian': ['Vera'],
113+
\ 'Mateo': ['Zara'],
114+
\ 'Noah': ['Xiomara'],
115+
\ 'Celine': ['Priya'],
116+
\ 'Xiomara': ['Kaito'],
117+
\ 'Bao': ['Dalia', 'Elias'],
118+
\ 'Elif': ['Rami'],
119+
\ 'Farah': ['Sven'],
120+
\ 'Aditi': ['Nia'],
121+
\ 'Vera': ['Igor'],
122+
\ 'Boris': ['Oscar'],
123+
\ 'Khadija': ['Sofia'],
124+
\ 'Zara': ['Mohammed'],
125+
\ 'Dalia': ['Hassan', 'Isla'],
126+
\ 'Ravi': ['Celine'],
127+
\ 'Yassin': ['Lucia'],
128+
\ 'Elias': ['Javier'],
129+
\ 'Nia': ['Antonio'],
130+
\ 'Rami': ['Ewa'],
131+
\ 'Hassan': ['Noah', 'Olga'],
132+
\ 'Tomoko': ['Gabriela']}
133+
AssertEqual 14, DegreeOfSeparation(g:familyTree, 'Lucia', 'Jun')
134+
135+
Execute (Complex graph, some shortcuts, cross-down and cross-up, cousins several times removed, with unrelated family tree):
136+
let g:familyTree = {
137+
\ 'Mina': ['Viktor', 'Wang'],
138+
\ 'Olga': ['Yuki'],
139+
\ 'Javier': ['Quynh', 'Ravi'],
140+
\ 'Tariq': ['Farah'],
141+
\ 'Viktor': ['Hana', 'Ian'],
142+
\ 'Diego': ['Qi'],
143+
\ 'Carlos': ['Fatima', 'Gustavo'],
144+
\ 'Hana': ['Umar'],
145+
\ 'Jing': ['Wyatt'],
146+
\ 'Sven': ['Fabio'],
147+
\ 'Zane': ['Mateo'],
148+
\ 'Isla': ['Pedro'],
149+
\ 'Quynh': ['Boris'],
150+
\ 'Kaito': ['Xia'],
151+
\ 'Liam': ['Tariq', 'Uma'],
152+
\ 'Priya': ['Cai'],
153+
\ 'Qi': ['Dimitri'],
154+
\ 'Wang': ['Jing'],
155+
\ 'Yuki': ['Leila'],
156+
\ 'Xia': ['Kim'],
157+
\ 'Pedro': ['Zane', 'Aditi'],
158+
\ 'Uma': ['Giorgio'],
159+
\ 'Giorgio': ['Tomoko'],
160+
\ 'Gustavo': ['Mina'],
161+
\ 'Sofia': ['Diego', 'Elif'],
162+
\ 'Leila': ['Yassin'],
163+
\ 'Umar': ['Helena'],
164+
\ 'Aiko': ['Bao', 'Carlos'],
165+
\ 'Fatima': ['Khadija', 'Liam'],
166+
\ 'Oscar': ['Bianca'],
167+
\ 'Wyatt': ['Jun'],
168+
\ 'Ian': ['Vera'],
169+
\ 'Mateo': ['Zara'],
170+
\ 'Noah': ['Xiomara'],
171+
\ 'Celine': ['Priya'],
172+
\ 'Xiomara': ['Kaito'],
173+
\ 'Bao': ['Dalia'],
174+
\ 'Elif': ['Rami'],
175+
\ 'Farah': ['Sven'],
176+
\ 'Aditi': ['Nia'],
177+
\ 'Vera': ['Igor'],
178+
\ 'Boris': ['Oscar'],
179+
\ 'Khadija': ['Sofia'],
180+
\ 'Zara': ['Mohammed'],
181+
\ 'Dalia': ['Hassan', 'Isla'],
182+
\ 'Ravi': ['Celine'],
183+
\ 'Yassin': ['Lucia'],
184+
\ 'Nia': ['Antonio'],
185+
\ 'Rami': ['Ewa'],
186+
\ 'Hassan': ['Noah', 'Olga'],
187+
\ 'Tomoko': ['Gabriela']}
188+
AssertEqual 12, DegreeOfSeparation(g:familyTree, 'Wyatt', 'Xia')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"
2+
" Given a dictionary of parents and children,
3+
" find the shortest number of connections between two people
4+
"
5+
function! DegreeOfSeparation(familyTree, personA, personB) abort
6+
" your code goes here
7+
endfunction

0 commit comments

Comments
 (0)