Skip to content

Commit 6b2e645

Browse files
authored
satellite: implement exercise (exercism#1831)
* Add initial files for setting up satellite exercise. * Setup tests for satellite. * Finish implementation of reference solution for satellite. * Fix style violations in satellite exercise.
1 parent 7eac364 commit 6b2e645

File tree

13 files changed

+451
-0
lines changed

13 files changed

+451
-0
lines changed

config.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,17 @@
14571457
"sets"
14581458
]
14591459
},
1460+
{
1461+
"slug": "satellite",
1462+
"uuid": "a5f8aef3-9661-49c7-9eb3-786ef9fe0e85",
1463+
"core": false,
1464+
"unlocked_by": "linked-list",
1465+
"difficulty": 10,
1466+
"topics": [
1467+
"trees",
1468+
"graphs"
1469+
]
1470+
},
14601471
{
14611472
"slug": "accumulate",
14621473
"uuid": "e58c29d2-80a7-40ef-bed0-4a184ae35f34",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Node {
2+
public final char value;
3+
public Node left;
4+
public Node right;
5+
6+
public Node(char value) {
7+
this(value, null, null);
8+
}
9+
10+
/** For testing purposes. */
11+
Node(char value, Node left, Node right) {
12+
this.value = value;
13+
this.left = left;
14+
this.right = right;
15+
}
16+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import java.util.ArrayList;
2+
import java.util.HashMap;
3+
import java.util.HashSet;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.Set;
7+
8+
public class Satellite {
9+
public Tree treeFromTraversals(
10+
List<Character> preorderInput, List<Character> inorderInput) {
11+
List<Character> preorder = new ArrayList<>(preorderInput);
12+
List<Character> inorder = new ArrayList<>(inorderInput);
13+
14+
checkArgument(
15+
preorder.size() == inorder.size(),
16+
"traversals must have the same length");
17+
18+
Set<Character> distinctLetters = new HashSet<>(preorder);
19+
Map<Character, Integer> inorderIndexByValue = indexByValue(inorder);
20+
21+
checkArgument(
22+
distinctLetters.size() == preorder.size()
23+
&& inorderIndexByValue.size() == inorder.size(),
24+
"traversals must contain unique items");
25+
checkArgument(
26+
distinctLetters.containsAll(inorderIndexByValue.keySet()),
27+
"traversals must have the same elements");
28+
29+
return new TreeBuilder(preorder, inorder, inorderIndexByValue).build();
30+
}
31+
32+
private static class TreeBuilder {
33+
private final List<Character> preorder;
34+
private final List<Character> inorder;
35+
private final Map<Character, Integer> inorderIndexByValue;
36+
private int preorderIndex = 0;
37+
38+
TreeBuilder(
39+
List<Character> preorder,
40+
List<Character> inorder,
41+
Map<Character, Integer> inorderIndexByValue) {
42+
this.preorder = preorder;
43+
this.inorder = inorder;
44+
this.inorderIndexByValue = inorderIndexByValue;
45+
}
46+
47+
Tree build() {
48+
return new Tree(makeNode(0, inorder.size() - 1));
49+
}
50+
51+
Node makeNode(int inorderStart, int inorderEnd) {
52+
if (inorderStart > inorderEnd
53+
|| preorderIndex >= preorder.size()) {
54+
return null;
55+
}
56+
Character value = preorder.get(preorderIndex++);
57+
Node node = new Node(value);
58+
int inorderIndex = inorderIndexByValue.get(value);
59+
node.left = makeNode(inorderStart, inorderIndex - 1);
60+
node.right = makeNode(inorderIndex + 1, inorderEnd);
61+
return node;
62+
}
63+
}
64+
65+
private static Map<Character, Integer> indexByValue(List<Character> inorder) {
66+
Map<Character, Integer> byIndex = new HashMap<>();
67+
for (int i = 0; i < inorder.size(); i++) {
68+
byIndex.put(inorder.get(i), i);
69+
}
70+
return byIndex;
71+
}
72+
73+
private static void checkArgument(boolean expression, String message) {
74+
if (!expression) {
75+
throw new IllegalArgumentException(message);
76+
}
77+
}
78+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import java.util.function.Consumer;
2+
import java.util.List;
3+
import java.util.ArrayList;
4+
5+
class Tree {
6+
private final Node root;
7+
8+
public Tree(Node root) {
9+
this.root = root;
10+
}
11+
12+
public List<Character> inorder() {
13+
List<Character> inorder = new ArrayList<>();
14+
inorder(root, inorder::add);
15+
return inorder;
16+
}
17+
18+
private void inorder(Node node, Consumer<Character> emitter) {
19+
if (node == null) {
20+
return;
21+
}
22+
inorder(node.left, emitter);
23+
emitter.accept(node.value);
24+
inorder(node.right, emitter);
25+
}
26+
27+
public List<Character> preorder() {
28+
List<Character> preorder = new ArrayList<>();
29+
preorder(root, preorder::add);
30+
return preorder;
31+
}
32+
33+
private void preorder(Node node, Consumer<Character> emitter) {
34+
if (node == null) {
35+
return;
36+
}
37+
emitter.accept(node.value);
38+
preorder(node.left, emitter);
39+
preorder(node.right, emitter);
40+
}
41+
42+
public List<Character> postorder() {
43+
List<Character> postorder = new ArrayList<>();
44+
postorder(root, postorder::add);
45+
return postorder;
46+
}
47+
48+
private void postorder(Node node, Consumer<Character> emitter) {
49+
if (node == null) {
50+
return;
51+
}
52+
postorder(node.left, emitter);
53+
postorder(node.right, emitter);
54+
emitter.accept(node.value);
55+
}
56+
}

exercises/satellite/.meta/version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2.0.0

exercises/satellite/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Satellite
2+
3+
Imagine you need to transmit a binary tree to a satellite approaching Alpha
4+
Centauri and you have limited bandwidth. Since the tree has no repeating
5+
items it can be uniquely represented by its [pre-order and in-order traversals][wiki].
6+
7+
Write the software for the satellite to rebuild the tree from the traversals.
8+
9+
A pre-order traversal reads the value of the current node before (hence "pre")
10+
reading the left subtree in pre-order. Afterwards the right subtree is read
11+
in pre-order.
12+
13+
An in-order traversal reads the left subtree in-order then the current node and
14+
finally the right subtree in-order. So in order from left to right.
15+
16+
For example the pre-order traversal of this tree is [a, i, x, f, r].
17+
The in-order traversal of this tree is [i, a, f, x, r]
18+
19+
```
20+
a
21+
/ \
22+
i x
23+
/ \
24+
f r
25+
```
26+
27+
Note: the first item in the pre-order traversal is always the root.
28+
29+
[wiki]: https://en.wikipedia.org/wiki/Tree_traversal
30+
31+
## Setup
32+
33+
Go through the setup instructions for Java to install the necessary
34+
dependencies:
35+
36+
[https://exercism.io/tracks/java/installation](https://exercism.io/tracks/java/installation)
37+
38+
# Running the tests
39+
40+
You can run all the tests for an exercise by entering the following in your
41+
terminal:
42+
43+
```sh
44+
$ gradle test
45+
```
46+
47+
In the test suites all tests but the first have been skipped.
48+
49+
Once you get a test passing, you can enable the next one by removing the
50+
`@Ignore("Remove to run test")` annotation.
51+
52+
53+
## Submitting Incomplete Solutions
54+
It's possible to submit an incomplete solution so you can see how others have
55+
completed the exercise.

exercises/satellite/build.gradle

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
apply plugin: "java"
2+
apply plugin: "eclipse"
3+
apply plugin: "idea"
4+
5+
repositories {
6+
mavenCentral()
7+
}
8+
9+
dependencies {
10+
testCompile "junit:junit:4.13"
11+
testImplementation "org.assertj:assertj-core:3.15.0"
12+
}
13+
14+
test {
15+
testLogging {
16+
exceptionFormat = 'full'
17+
showStandardStreams = true
18+
events = ["passed", "failed", "skipped"]
19+
}
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Node {
2+
public final char value;
3+
public Node left;
4+
public Node right;
5+
6+
public Node(char value) {
7+
this(value, null, null);
8+
}
9+
10+
/** For testing. */
11+
Node(char value, Node left, Node right) {
12+
this.value = value;
13+
this.left = left;
14+
this.right = right;
15+
}
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
3+
Since this exercise has a difficulty of > 4 it doesn't come
4+
with any starter implementation.
5+
This is so that you get to practice creating classes and methods
6+
which is an important part of programming in Java.
7+
8+
Please remove this comment when submitting your solution.
9+
10+
*/
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import java.util.function.Consumer;
2+
import java.util.List;
3+
import java.util.ArrayList;
4+
5+
class Tree {
6+
private final Node root;
7+
8+
public Tree(Node root) {
9+
this.root = root;
10+
}
11+
12+
public List<Character> inorder() {
13+
List<Character> inorder = new ArrayList<>();
14+
inorder(root, inorder::add);
15+
return inorder;
16+
}
17+
18+
private void inorder(Node node, Consumer<Character> emitter) {
19+
if (node == null) {
20+
return;
21+
}
22+
inorder(node.left, emitter);
23+
emitter.accept(node.value);
24+
inorder(node.right, emitter);
25+
}
26+
27+
public List<Character> preorder() {
28+
List<Character> preorder = new ArrayList<>();
29+
preorder(root, preorder::add);
30+
return preorder;
31+
}
32+
33+
private void preorder(Node node, Consumer<Character> emitter) {
34+
if (node == null) {
35+
return;
36+
}
37+
emitter.accept(node.value);
38+
preorder(node.left, emitter);
39+
preorder(node.right, emitter);
40+
}
41+
42+
public List<Character> postorder() {
43+
List<Character> postorder = new ArrayList<>();
44+
postorder(root, postorder::add);
45+
return postorder;
46+
}
47+
48+
private void postorder(Node node, Consumer<Character> emitter) {
49+
if (node == null) {
50+
return;
51+
}
52+
postorder(node.left, emitter);
53+
postorder(node.right, emitter);
54+
emitter.accept(node.value);
55+
}
56+
}

0 commit comments

Comments
 (0)