Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Satellite exercise #1210

Merged
merged 4 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,17 @@
"algorithms"
]
},
{
"slug": "satellite",
"name": "Satellite",
"uuid": "22136812-8160-49f0-8a0d-f76a2086a34c",
"practices": [],
"prerequisites": [],
"difficulty": 6,
"topics": [
"maybe"
]
Comment on lines +510 to +512
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ErikSchierboom I am not familiar with this feature, so I cannot judge this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Topics are deprecated and are not used by the website. They are allowed to be in the config.json as they used to be used and they could be useful to help determine the practices and prerequisites fields.

},
{
"slug": "go-counting",
"name": "Go Counting",
Expand Down
27 changes: 27 additions & 0 deletions exercises/practice/satellite/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Instructions

Imagine you need to transmit a binary tree to a satellite approaching Alpha Centauri and you have limited bandwidth.
Since the tree has no repeating items it can be uniquely represented by its [pre-order and in-order traversals][wiki].

Write the software for the satellite to rebuild the tree from the traversals.

A pre-order traversal reads the value of the current node before (hence "pre") reading the left subtree in pre-order.
Afterwards the right subtree is read in pre-order.

An in-order traversal reads the left subtree in-order then the current node and finally the right subtree in-order.
So in order from left to right.

For example the pre-order traversal of this tree is [a, i, x, f, r].
The in-order traversal of this tree is [i, a, f, x, r]

```text
a
/ \
i x
/ \
f r
```

Note: the first item in the pre-order traversal is always the root.

[wiki]: https://en.wikipedia.org/wiki/Tree_traversal
24 changes: 24 additions & 0 deletions exercises/practice/satellite/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"authors": [
"tofische"
],
"files": {
"solution": [
"src/Satellite.hs",
"package.yaml"
],
"test": [
"test/Tests.hs"
],
"example": [
".meta/examples/success-standard/src/Satellite.hs"
],
"editor": [
"src/BinaryTree.hs"
],
"invalidator": [
"stack.yaml"
]
},
"blurb": "Rebuild binary trees from pre-order and in-order traversals."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: satellite

dependencies:
- base
- containers

library:
exposed-modules:
- Satellite
- BinaryTree
source-dirs: src
# dependencies:

tests:
test:
main: Tests.hs
source-dirs: test
dependencies:
- satellite
- hspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module BinaryTree (BinaryTree(..)) where

data BinaryTree a = Leaf | Branch (BinaryTree a) a (BinaryTree a)
deriving (Show, Eq)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Satellite (treeFromTraversals) where

import Data.Set (fromList, size)
import BinaryTree (BinaryTree(..))

treeFromTraversals :: Ord a => [a] -> [a] -> Maybe (BinaryTree a)
treeFromTraversals preorder inorder =
if (not.null) preorder && length preorder == size (fromList preorder)
then treeFromTraversals' preorder inorder
else Nothing

treeFromTraversals' :: Ord a => [a] -> [a] -> Maybe (BinaryTree a)
treeFromTraversals' preorder inorder = Branch <$> leftChild <*> pure root <*> rightChild
where
root = head preorder
(inLeft, rest) = span (/= root) inorder
inRight = tail rest
(preLeft, preRight) = splitAt (length inLeft) $ tail preorder
leftChild
| null preLeft && null inLeft = Just Leaf
| null preLeft || null inLeft = Nothing
| otherwise = treeFromTraversals' preLeft inLeft
rightChild
| null preRight && null inRight = Just Leaf
| null preRight || null inRight = Nothing
| otherwise = treeFromTraversals' preRight inRight
28 changes: 28 additions & 0 deletions exercises/practice/satellite/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[8df3fa26-811a-4165-9286-ff9ac0850d19]
description = "Empty tree"

[f945ccfc-05e3-47d7-825b-0270559d43ad]
description = "Tree with one item"

[a0121d5f-37b0-48dd-9c64-cba4c4464135]
description = "Tree with many items"

[6074041f-4891-4d81-a128-401050c2a3b0]
description = "Reject traversals of different length"

[27916ce4-45f3-4d8b-8528-496fedc157ca]
description = "Reject inconsistent traversals of same length"

[d86a3d72-76a9-43b5-9d3a-e64cb1216035]
description = "Reject traversals with repeated items"
23 changes: 23 additions & 0 deletions exercises/practice/satellite/package.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: satellite
version: 1.0.0.0

dependencies:
- base

library:
exposed-modules:
- Satellite
- BinaryTree
source-dirs: src
ghc-options: -Wall
# dependencies:
# - foo # List here the packages you
# - bar # want to use in your solution.

tests:
test:
main: Tests.hs
source-dirs: test
dependencies:
- satellite
- hspec
4 changes: 4 additions & 0 deletions exercises/practice/satellite/src/BinaryTree.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module BinaryTree (BinaryTree(..)) where

data BinaryTree a = Leaf | Branch (BinaryTree a) a (BinaryTree a)
deriving (Show, Eq)
6 changes: 6 additions & 0 deletions exercises/practice/satellite/src/Satellite.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Satellite (treeFromTraversals) where

import BinaryTree (BinaryTree(..))

treeFromTraversals :: Ord a => [a] -> [a] -> Maybe (BinaryTree a)
treeFromTraversals preorder inorder = error "You need to implement this function."
1 change: 1 addition & 0 deletions exercises/practice/satellite/stack.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
resolver: lts-20.18
57 changes: 57 additions & 0 deletions exercises/practice/satellite/test/Tests.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{-# LANGUAGE RecordWildCards #-}

import Data.Foldable (for_)
import Test.Hspec (Spec, describe, it, shouldBe)
import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith)

import Satellite (treeFromTraversals)
import BinaryTree (BinaryTree(..))

main :: IO ()
main = hspecWith defaultConfig {configFailFast = True} specs

specs :: Spec
specs = do
describe "treeFromTraversals" $ for_ cases $ test treeFromTraversals
where
test f Case{..} = it description $ f preorder inorder `shouldBe` expected

data Case = Case { description :: String
, preorder :: String
, inorder :: String
, expected :: Maybe (BinaryTree Char)
}

cases :: [Case]
cases =
[ Case { description = "Empty tree"
, preorder = ""
, inorder = ""
, expected = Nothing
}
, Case { description = "Tree with one item"
, preorder = "a"
, inorder = "a"
, expected = Just (Branch Leaf 'a' Leaf)
}
, Case { description = "Tree with many items"
, preorder = "aixfr"
, inorder = "iafxr"
, expected = Just (Branch (Branch Leaf 'i' Leaf) 'a' (Branch (Branch Leaf 'f' Leaf) 'x' (Branch Leaf 'r' Leaf)))
}
, Case { description = "Reject traversals of different length"
, preorder = "ab"
, inorder = "bar"
, expected = Nothing
}
, Case { description = "Reject inconsistent traversals of same length"
, preorder = "xyz"
, inorder = "abc"
, expected = Nothing
}
, Case { description = "Reject traversals with repeated items"
, preorder = "aba"
, inorder = "baa"
, expected = Nothing
}
]
Loading