Skip to content

Commit a41402b

Browse files
authored
Add relative-distance (#2947)
1 parent a606586 commit a41402b

File tree

14 files changed

+827
-0
lines changed

14 files changed

+827
-0
lines changed

config.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,19 @@
10541054
],
10551055
"difficulty": 5
10561056
},
1057+
{
1058+
"slug": "relative-distance",
1059+
"name": "Relative Distance",
1060+
"uuid": "a3cf95fd-c7c1-4199-a253-7bae8d1aba9a",
1061+
"practices": [
1062+
"maps"
1063+
],
1064+
"prerequisites": [
1065+
"lists",
1066+
"maps"
1067+
],
1068+
"difficulty": 5
1069+
},
10571070
{
10581071
"slug": "robot-name",
10591072
"name": "Robot Name",
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+
This is similar to the pop culture idea that every Hollywood actor is [within six degrees of Kevin Bacon][six-bacons].
5+
6+
- You will be given an input, with all parent names and their children.
7+
- Each name is unique, a child _can_ have one or two parents.
8+
- The degree of separation is defined as the shortest number of connections from one person to another.
9+
- If two individuals are not connected, return a value that represents "no known relationship."
10+
Please see the test cases for the actual implementation.
11+
12+
## Example
13+
14+
Given the following family tree:
15+
16+
```text
17+
┌──────────┐ ┌──────────┐ ┌───────────┐
18+
│ Helena │ │ Erdős ├─────┤ Shusaku │
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 2 (Tariq → Isla → Uma).
31+
There's no known relationship between Isla and Kevin, 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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"authors": [
3+
"BNAndras"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/main/java/RelativeDistance.java"
8+
],
9+
"test": [
10+
"src/test/java/RelativeDistanceTest.java"
11+
],
12+
"example": [
13+
".meta/src/reference/java/RelativeDistance.java"
14+
],
15+
"invalidator": [
16+
"build.gradle"
17+
]
18+
},
19+
"blurb": "Given a family tree, calculate the degree of separation.",
20+
"source": "vaeng",
21+
"source_url": "https://github.com/exercism/problem-specifications/pull/2537"
22+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import java.util.HashMap;
2+
import java.util.HashSet;
3+
import java.util.LinkedList;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.Queue;
7+
8+
class RelativeDistance {
9+
10+
private final Map<String, HashSet<String>> graph;
11+
12+
RelativeDistance(Map<String, List<String>> familyTree) {
13+
final HashMap<String, HashSet<String>> connections = new HashMap<>();
14+
15+
for (Map.Entry<String, List<String>> entry : familyTree.entrySet()) {
16+
String parent = entry.getKey();
17+
List<String> children = entry.getValue();
18+
19+
connections.putIfAbsent(parent, new HashSet<>());
20+
21+
for (String child : children) {
22+
connections.putIfAbsent(child, new HashSet<>());
23+
24+
connections.get(parent).add(child);
25+
connections.get(child).add(parent);
26+
27+
for (String sibling : children) {
28+
if (!sibling.equals(child)) {
29+
connections.get(child).add(sibling);
30+
}
31+
}
32+
}
33+
}
34+
35+
graph = connections;
36+
}
37+
38+
int degreeOfSeparation(String personA, String personB) {
39+
if (!graph.containsKey(personA) || !graph.containsKey(personB)) {
40+
return -1;
41+
}
42+
43+
Queue<String> queue = new LinkedList<>();
44+
Map<String, Integer> distances = new HashMap<>() {
45+
{
46+
put(personA, 0);
47+
}
48+
};
49+
queue.add(personA);
50+
51+
while (!queue.isEmpty()) {
52+
String current = queue.poll();
53+
int currentDistance = distances.get(current);
54+
55+
for (String relative : graph.get(current)) {
56+
if (!distances.containsKey(relative)) {
57+
if (relative.equals(personB)) {
58+
return currentDistance + 1;
59+
}
60+
distances.put(relative, currentDistance + 1);
61+
queue.add(relative);
62+
}
63+
}
64+
}
65+
66+
return -1;
67+
}
68+
}
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: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
plugins {
2+
id "java"
3+
}
4+
5+
repositories {
6+
mavenCentral()
7+
}
8+
9+
dependencies {
10+
testImplementation platform("org.junit:junit-bom:5.10.0")
11+
testImplementation "org.junit.jupiter:junit-jupiter"
12+
testImplementation "org.assertj:assertj-core:3.25.1"
13+
14+
testRuntimeOnly "org.junit.platform:junit-platform-launcher"
15+
}
16+
17+
test {
18+
useJUnitPlatform()
19+
20+
testLogging {
21+
exceptionFormat = "full"
22+
showStandardStreams = true
23+
events = ["passed", "failed", "skipped"]
24+
}
25+
}
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
4+
validateDistributionUrl=true
5+
zipStoreBase=GRADLE_USER_HOME
6+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)