Skip to content

Commit 7eff5a5

Browse files
Add satellite exercise (exercism#275)
1 parent ba6ad9a commit 7eff5a5

File tree

7 files changed

+228
-0
lines changed

7 files changed

+228
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,14 @@
919919
"practices": [],
920920
"prerequisites": [],
921921
"difficulty": 8
922+
},
923+
{
924+
"slug": "satellite",
925+
"name": "Satellite",
926+
"uuid": "351dfb26-5fd4-447c-a89b-c8f201f6c6bc",
927+
"practices": [],
928+
"prerequisites": [],
929+
"difficulty": 9
922930
}
923931
]
924932
},
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Instructions
2+
3+
Imagine you need to transmit a binary tree to a satellite approaching Alpha Centauri and you have limited bandwidth.
4+
Since the tree has no repeating items it can be uniquely represented by its [pre-order and in-order traversals][wiki].
5+
6+
Write the software for the satellite to rebuild the tree from the traversals.
7+
8+
A pre-order traversal reads the value of the current node before (hence "pre") reading the left subtree in pre-order.
9+
Afterwards the right subtree is read in pre-order.
10+
11+
An in-order traversal reads the left subtree in-order then the current node and finally the right subtree in-order.
12+
So in order from left to right.
13+
14+
For example the pre-order traversal of this tree is [a, i, x, f, r].
15+
The in-order traversal of this tree is [i, a, f, x, r]
16+
17+
```text
18+
a
19+
/ \
20+
i x
21+
/ \
22+
f r
23+
```
24+
25+
Note: the first item in the pre-order traversal is always the root.
26+
27+
[wiki]: https://en.wikipedia.org/wiki/Tree_traversal
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"satellite.v"
8+
],
9+
"test": [
10+
"run_test.v"
11+
],
12+
"example": [
13+
".meta/example.v"
14+
]
15+
},
16+
"blurb": "Rebuild binary trees from pre-order and in-order traversals."
17+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
module main
2+
3+
type Tree = Empty | Node
4+
5+
struct Empty {}
6+
7+
struct Node {
8+
left Tree = Empty{}
9+
right Tree = Empty{}
10+
value rune
11+
}
12+
13+
fn tree_from_traversals(preorder string, inorder string) !Tree {
14+
mut p := preorder.runes()
15+
mut i := inorder.runes()
16+
if p.len != i.len {
17+
return error('traversals must have the same length')
18+
}
19+
20+
if p.len == 0 {
21+
return Empty{}
22+
}
23+
24+
if repeats(p) || repeats(i) {
25+
return error('traversals must contain unique items')
26+
}
27+
28+
return traverse(none, mut p, mut i)
29+
}
30+
31+
fn repeats(r []rune) bool {
32+
for i in 1 .. (r.len) {
33+
for j in 0 .. i {
34+
if r[j] == r[i] {
35+
return true
36+
}
37+
}
38+
}
39+
return false
40+
}
41+
42+
fn traverse(successor ?rune, mut preorder []rune, mut inorder []rune) !Tree {
43+
if s := successor {
44+
if inorder.len > 0 && inorder[0] == s {
45+
return Empty{}
46+
}
47+
}
48+
49+
if preorder.len == 0 {
50+
return Empty{}
51+
}
52+
53+
value := preorder[0]
54+
preorder = preorder[1..(preorder.len)]
55+
56+
left := traverse(value, mut preorder, mut inorder)!
57+
58+
if inorder.len == 0 || inorder[0] != value {
59+
return error('traversals must have the same elements')
60+
}
61+
62+
inorder = inorder[1..(inorder.len)]
63+
64+
right := traverse(successor, mut preorder, mut inorder)!
65+
66+
return Node{left, right, value}
67+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# This is an auto-generated file. Regular comments will be removed when this
2+
# file is regenerated. Regenerating will not touch any manually added keys,
3+
# so comments can be added in a "comment" key.
4+
5+
[8df3fa26-811a-4165-9286-ff9ac0850d19]
6+
description = "Empty tree"
7+
8+
[f945ccfc-05e3-47d7-825b-0270559d43ad]
9+
description = "Tree with one item"
10+
11+
[a0121d5f-37b0-48dd-9c64-cba4c4464135]
12+
description = "Tree with many items"
13+
14+
[6074041f-4891-4d81-a128-401050c2a3b0]
15+
description = "Reject traversals of different length"
16+
17+
[27916ce4-45f3-4d8b-8528-496fedc157ca]
18+
description = "Reject inconsistent traversals of same length"
19+
20+
[d86a3d72-76a9-43b5-9d3a-e64cb1216035]
21+
description = "Reject traversals with repeated items"
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
module main
2+
3+
fn test_empty_tree() {
4+
preorder := ''
5+
inorder := ''
6+
expected := fn () Tree {
7+
return Empty{}
8+
}
9+
assert tree_from_traversals(preorder, inorder)! == expected()
10+
}
11+
12+
fn test_tree_with_one_item() {
13+
preorder := 'a'
14+
inorder := 'a'
15+
expected := fn () Tree {
16+
return Node{
17+
value: `a`
18+
}
19+
}
20+
assert tree_from_traversals(preorder, inorder)! == expected()
21+
}
22+
23+
fn test_tree_with_many_items() {
24+
preorder := 'aixfr'
25+
inorder := 'iafxr'
26+
expected := fn () Tree {
27+
return Node{
28+
left: Node{
29+
value: `i`
30+
}
31+
right: Node{
32+
left: Node{
33+
value: `f`
34+
}
35+
right: Node{
36+
value: `r`
37+
}
38+
value: `x`
39+
}
40+
value: `a`
41+
}
42+
}
43+
assert tree_from_traversals(preorder, inorder)! == expected()
44+
}
45+
46+
fn test_reject_traversals_of_different_length() {
47+
preorder := 'ab'
48+
inorder := 'bar'
49+
if _ := tree_from_traversals(preorder, inorder) {
50+
assert false, 'Reject traversals of different length should return an error'
51+
} else {
52+
assert err.msg() == 'traversals must have the same length'
53+
}
54+
}
55+
56+
fn test_reject_inconsistent_traversals_of_same_length() {
57+
preorder := 'xyz'
58+
inorder := 'abc'
59+
if _ := tree_from_traversals(preorder, inorder) {
60+
assert false, 'Reject inconsistent traversals of same length should return an error'
61+
} else {
62+
assert err.msg() == 'traversals must have the same elements'
63+
}
64+
}
65+
66+
fn test_reject_traversals_with_repeated_items() {
67+
preorder := 'aba'
68+
inorder := 'baa'
69+
if _ := tree_from_traversals(preorder, inorder) {
70+
assert false, 'Reject traversals with repeated items should return an error'
71+
} else {
72+
assert err.msg() == 'traversals must contain unique items'
73+
}
74+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module main
2+
3+
type Tree = Empty | Node
4+
5+
struct Empty {}
6+
7+
struct Node {
8+
left Tree = Empty{}
9+
right Tree = Empty{}
10+
value rune
11+
}
12+
13+
fn tree_from_traversals(preorder string, inorder string) !Tree {
14+
}

0 commit comments

Comments
 (0)