Skip to content

Commit 2c657af

Browse files
authored
add relative-distance (#372)
1 parent 3391162 commit 2c657af

File tree

8 files changed

+352
-0
lines changed

8 files changed

+352
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,14 @@
814814
"prerequisites": [],
815815
"difficulty": 5
816816
},
817+
{
818+
"slug": "relative-distance",
819+
"name": "Relative Distance",
820+
"uuid": "4060784f-e4ce-44dc-985a-328d190d4f94",
821+
"practices": [],
822+
"prerequisites": [],
823+
"difficulty": 5
824+
},
817825
{
818826
"slug": "minesweeper",
819827
"name": "Minesweeper",
Lines changed: 39 additions & 0 deletions
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
Lines changed: 12 additions & 0 deletions
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/
Lines changed: 19 additions & 0 deletions
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.coffee"
8+
],
9+
"test": [
10+
"relative-distance.spec.coffee"
11+
],
12+
"example": [
13+
".meta/example.coffee"
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+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
class RelativeDistance
2+
@degreesOfSeparation: (familyTree, personA, personB) ->
3+
neighbors = {}
4+
for parent, children of familyTree
5+
neighbors[parent] ?= []
6+
for child in children
7+
neighbors[child] ?= []
8+
neighbors[parent].push child unless child in neighbors[parent]
9+
neighbors[child].push parent unless parent in neighbors[child]
10+
11+
if children.length > 1
12+
for child1 in children
13+
for child2 in children when child1 isnt child2
14+
neighbors[child1].push child2 unless child2 in neighbors[child1]
15+
16+
return -1 unless neighbors[personA] and neighbors[personB]
17+
18+
queue = [[personA, 0]]
19+
visited = {}
20+
visited[personA] = 1
21+
22+
while queue.length
23+
[current, degree] = queue.shift()
24+
25+
return degree if current is personB
26+
27+
for neighbor in neighbors[current] when not visited[neighbor]
28+
queue.push [neighbor, degree + 1]
29+
visited[neighbor] = 1
30+
31+
-1
32+
33+
module.exports = RelativeDistance
Lines changed: 31 additions & 0 deletions
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"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class RelativeDistance
2+
@degreesOfSeparation: (familyTree, personA, personB) ->
3+
4+
module.exports = RelativeDistance
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
RD = require './relative-distance'
2+
3+
describe 'RelativeDistance', ->
4+
it 'Direct parent-child relation', ->
5+
familyTree = {
6+
'Vera': ['Tomoko']
7+
'Tomoko': ['Aditi']
8+
}
9+
results = RD.degreesOfSeparation familyTree, 'Vera', 'Tomoko'
10+
expect(results).toEqual 1
11+
12+
xit 'Sibling relationship', ->
13+
familyTree = {
14+
'Dalia': ['Olga', 'Yassin']
15+
}
16+
results = RD.degreesOfSeparation familyTree, 'Olga', 'Yassin'
17+
expect(results).toEqual 1
18+
19+
xit 'Two degrees of separation, grandchild', ->
20+
familyTree = {
21+
'Khadija': ['Mateo']
22+
'Mateo': ['Rami']
23+
}
24+
results = RD.degreesOfSeparation familyTree, 'Khadija', 'Rami'
25+
expect(results).toEqual 2
26+
27+
xit 'Unrelated individuals', ->
28+
familyTree = {
29+
'Priya': ['Rami']
30+
'Kaito': ['Elif']
31+
}
32+
results = RD.degreesOfSeparation familyTree, 'Priya', 'Kaito'
33+
expect(results).toEqual -1
34+
35+
xit 'Complex graph, cousins', ->
36+
familyTree = {
37+
'Aiko': ['Bao', 'Carlos']
38+
'Bao': ['Dalia', 'Elias']
39+
'Carlos': ['Fatima', 'Gustavo']
40+
'Dalia': ['Hassan', 'Isla']
41+
'Elias': ['Javier']
42+
'Fatima': ['Khadija', 'Liam']
43+
'Gustavo': ['Mina']
44+
'Hassan': ['Noah', 'Olga']
45+
'Isla': ['Pedro']
46+
'Javier': ['Quynh', 'Ravi']
47+
'Khadija': ['Sofia']
48+
'Liam': ['Tariq', 'Uma']
49+
'Mina': ['Viktor', 'Wang']
50+
'Noah': ['Xiomara']
51+
'Olga': ['Yuki']
52+
'Pedro': ['Zane', 'Aditi']
53+
'Quynh': ['Boris']
54+
'Ravi': ['Celine']
55+
'Sofia': ['Diego', 'Elif']
56+
'Tariq': ['Farah']
57+
'Uma': ['Giorgio']
58+
'Viktor': ['Hana', 'Ian']
59+
'Wang': ['Jing']
60+
'Xiomara': ['Kaito']
61+
'Yuki': ['Leila']
62+
'Zane': ['Mateo']
63+
'Aditi': ['Nia']
64+
'Boris': ['Oscar']
65+
'Celine': ['Priya']
66+
'Diego': ['Qi']
67+
'Elif': ['Rami']
68+
'Farah': ['Sven']
69+
'Giorgio': ['Tomoko']
70+
'Hana': ['Umar']
71+
'Ian': ['Vera']
72+
'Jing': ['Wyatt']
73+
'Kaito': ['Xia']
74+
'Leila': ['Yassin']
75+
'Mateo': ['Zara']
76+
'Nia': ['Antonio']
77+
'Oscar': ['Bianca']
78+
'Priya': ['Cai']
79+
'Qi': ['Dimitri']
80+
'Rami': ['Ewa']
81+
'Sven': ['Fabio']
82+
'Tomoko': ['Gabriela']
83+
'Umar': ['Helena']
84+
'Vera': ['Igor']
85+
'Wyatt': ['Jun']
86+
'Xia': ['Kim']
87+
'Yassin': ['Lucia']
88+
'Zara': ['Mohammed']
89+
}
90+
results = RD.degreesOfSeparation familyTree, 'Dimitri', 'Fabio'
91+
expect(results).toEqual 9
92+
93+
xit 'Complex graph, no shortcut, far removed nephew', ->
94+
familyTree = {
95+
'Mina': ['Viktor', 'Wang']
96+
'Olga': ['Yuki']
97+
'Javier': ['Quynh', 'Ravi']
98+
'Tariq': ['Farah']
99+
'Viktor': ['Hana', 'Ian']
100+
'Diego': ['Qi']
101+
'Carlos': ['Fatima', 'Gustavo']
102+
'Hana': ['Umar']
103+
'Jing': ['Wyatt']
104+
'Sven': ['Fabio']
105+
'Zane': ['Mateo']
106+
'Isla': ['Pedro']
107+
'Quynh': ['Boris']
108+
'Kaito': ['Xia']
109+
'Liam': ['Tariq', 'Uma']
110+
'Priya': ['Cai']
111+
'Qi': ['Dimitri']
112+
'Wang': ['Jing']
113+
'Yuki': ['Leila']
114+
'Xia': ['Kim']
115+
'Pedro': ['Zane', 'Aditi']
116+
'Uma': ['Giorgio']
117+
'Giorgio': ['Tomoko']
118+
'Gustavo': ['Mina']
119+
'Sofia': ['Diego', 'Elif']
120+
'Leila': ['Yassin']
121+
'Umar': ['Helena']
122+
'Aiko': ['Bao', 'Carlos']
123+
'Fatima': ['Khadija', 'Liam']
124+
'Oscar': ['Bianca']
125+
'Wyatt': ['Jun']
126+
'Ian': ['Vera']
127+
'Mateo': ['Zara']
128+
'Noah': ['Xiomara']
129+
'Celine': ['Priya']
130+
'Xiomara': ['Kaito']
131+
'Bao': ['Dalia', 'Elias']
132+
'Elif': ['Rami']
133+
'Farah': ['Sven']
134+
'Aditi': ['Nia']
135+
'Vera': ['Igor']
136+
'Boris': ['Oscar']
137+
'Khadija': ['Sofia']
138+
'Zara': ['Mohammed']
139+
'Dalia': ['Hassan', 'Isla']
140+
'Ravi': ['Celine']
141+
'Yassin': ['Lucia']
142+
'Elias': ['Javier']
143+
'Nia': ['Antonio']
144+
'Rami': ['Ewa']
145+
'Hassan': ['Noah', 'Olga']
146+
'Tomoko': ['Gabriela']
147+
}
148+
results = RD.degreesOfSeparation familyTree, 'Lucia', 'Jun'
149+
expect(results).toEqual 14
150+
151+
xit 'Complex graph, some shortcuts, cross-down and cross-up, cousins several times removed, with unrelated family tree', ->
152+
familyTree = {
153+
'Mina': ['Viktor', 'Wang']
154+
'Olga': ['Yuki']
155+
'Javier': ['Quynh', 'Ravi']
156+
'Tariq': ['Farah']
157+
'Viktor': ['Hana', 'Ian']
158+
'Diego': ['Qi']
159+
'Carlos': ['Fatima', 'Gustavo']
160+
'Hana': ['Umar']
161+
'Jing': ['Wyatt']
162+
'Sven': ['Fabio']
163+
'Zane': ['Mateo']
164+
'Isla': ['Pedro']
165+
'Quynh': ['Boris']
166+
'Kaito': ['Xia']
167+
'Liam': ['Tariq', 'Uma']
168+
'Priya': ['Cai']
169+
'Qi': ['Dimitri']
170+
'Wang': ['Jing']
171+
'Yuki': ['Leila']
172+
'Xia': ['Kim']
173+
'Pedro': ['Zane', 'Aditi']
174+
'Uma': ['Giorgio']
175+
'Giorgio': ['Tomoko']
176+
'Gustavo': ['Mina']
177+
'Sofia': ['Diego', 'Elif']
178+
'Leila': ['Yassin']
179+
'Umar': ['Helena']
180+
'Aiko': ['Bao', 'Carlos']
181+
'Fatima': ['Khadija', 'Liam']
182+
'Oscar': ['Bianca']
183+
'Wyatt': ['Jun']
184+
'Ian': ['Vera']
185+
'Mateo': ['Zara']
186+
'Noah': ['Xiomara']
187+
'Celine': ['Priya']
188+
'Xiomara': ['Kaito']
189+
'Bao': ['Dalia']
190+
'Elif': ['Rami']
191+
'Farah': ['Sven']
192+
'Aditi': ['Nia']
193+
'Vera': ['Igor']
194+
'Boris': ['Oscar']
195+
'Khadija': ['Sofia']
196+
'Zara': ['Mohammed']
197+
'Dalia': ['Hassan', 'Isla']
198+
'Ravi': ['Celine']
199+
'Yassin': ['Lucia']
200+
'Nia': ['Antonio']
201+
'Rami': ['Ewa']
202+
'Hassan': ['Noah', 'Olga']
203+
'Tomoko': ['Gabriela']
204+
}
205+
results = RD.degreesOfSeparation familyTree, 'Wyatt', 'Xia'
206+
expect(results).toEqual 12

0 commit comments

Comments
 (0)