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

Add satellite exercise #1296

Merged
merged 1 commit into from
Oct 22, 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
14 changes: 14 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2233,6 +2233,20 @@
"result"
],
"difficulty": 5
},
{
"slug": "satellite",
"name": "Satellite",
"uuid": "bcfeb5b7-08d3-4039-95b2-ebda6b7288aa",
"practices": [
"recursion"
],
"prerequisites": [
"recursion",
"discriminated-unions",
"numbers"
],
"difficulty": 7
}
],
"foregone": [
Expand Down
7 changes: 7 additions & 0 deletions exercises/Exercises.sln
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "KillerSudokuHelper", "pract
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "StateOfTicTacToe", "practice\state-of-tic-tac-toe\StateOfTicTacToe.fsproj", "{A12FEF19-5EE8-430E-BD66-2D93ADFC1944}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Satellite", "practice\satellite\Satellite.fsproj", "{FF432193-3D08-4BD4-ADCD-1512BF67A425}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -910,6 +912,10 @@ Global
{A12FEF19-5EE8-430E-BD66-2D93ADFC1944}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A12FEF19-5EE8-430E-BD66-2D93ADFC1944}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A12FEF19-5EE8-430E-BD66-2D93ADFC1944}.Release|Any CPU.Build.0 = Release|Any CPU
{FF432193-3D08-4BD4-ADCD-1512BF67A425}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF432193-3D08-4BD4-ADCD-1512BF67A425}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF432193-3D08-4BD4-ADCD-1512BF67A425}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF432193-3D08-4BD4-ADCD-1512BF67A425}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{B404AA3C-A226-409A-A035-6C1DC66940DD} = {B7E719DB-FB8D-43B4-B529-55FCF6E3DC3F}
Expand Down Expand Up @@ -1063,5 +1069,6 @@ Global
{1850FAE9-5ACB-41D0-91BB-AD17A1021248} = {391BEEC4-91A8-43F3-AE94-D5CB9A8FA611}
{FCE9E627-CFF9-4EF3-84BE-D42B354825AA} = {391BEEC4-91A8-43F3-AE94-D5CB9A8FA611}
{A12FEF19-5EE8-430E-BD66-2D93ADFC1944} = {391BEEC4-91A8-43F3-AE94-D5CB9A8FA611}
{FF432193-3D08-4BD4-ADCD-1512BF67A425} = {391BEEC4-91A8-43F3-AE94-D5CB9A8FA611}
EndGlobalSection
EndGlobal
12 changes: 12 additions & 0 deletions exercises/practice/satellite/.config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fantomas-tool": {
"version": "4.7.9",
"commands": [
"fantomas"
]
}
}
}
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/Example.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Satellite

type Tree =
| Empty
| Node of value: string * left: Tree * right: Tree

let rec createTree inorder preorder =
match preorder with
| [] -> Empty
| hd :: tail ->
let hdIdx = inorder |> List.findIndex (fun x -> x = hd)
let leftInorder, rightInorder = inorder[0 .. hdIdx - 1], inorder[hdIdx + 1 ..]
let leftPreorder, rightPreorder = tail[0 .. leftInorder.Length - 1], tail[leftInorder.Length ..]
Node(hd, createTree leftInorder leftPreorder, createTree rightInorder rightPreorder)

let treeFromTraversals preorder inorder =
if List.length preorder <> List.length inorder then
Error "traversals must have the same length"
elif List.sort preorder <> List.sort inorder then
Error "traversals must have the same elements"
elif List.distinct preorder <> preorder then
Error "traversals must contain unique items"
else
Ok(createTree preorder inorder)
17 changes: 17 additions & 0 deletions exercises/practice/satellite/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"authors": [
"erikschierboom"
],
"files": {
"solution": [
"Satellite.fs"
],
"test": [
"SatelliteTests.fs"
],
"example": [
".meta/Example.fs"
]
},
"blurb": "Rebuild binary trees from pre-order and in-order traversals."
}
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"
8 changes: 8 additions & 0 deletions exercises/practice/satellite/Satellite.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Satellite

type Tree =
| Empty
| Node of value: string * left: Tree * right: Tree

let treeFromTraversals preorder inorder =
failwith "Please implement the 'treeFromTraversals' function"
22 changes: 22 additions & 0 deletions exercises/practice/satellite/Satellite.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<GenerateProgramFile>false</GenerateProgramFile>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<Compile Include="Satellite.fs" />
<Compile Include="SatelliteTests.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Exercism.Tests" Version="0.1.0-beta1" />
<PackageReference Include="FsUnit.xUnit" Version="4.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>
51 changes: 51 additions & 0 deletions exercises/practice/satellite/SatelliteTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module SatelliteTests

open FsUnit.Xunit
open Xunit

open Satellite

[<Fact>]
let ``Empty tree`` () =
let expected: Result<Tree,string> = Ok (
Empty
)
treeFromTraversals [] [] |> should equal expected

[<Fact>]
let ``Tree with one item`` () =
let expected: Result<Tree,string> = Ok (
Node("a", Empty, Empty)
)
treeFromTraversals ["a"] ["a"] |> should equal expected

[<Fact>]
let ``Tree with many items`` () =
let expected: Result<Tree,string> = Ok (
Node(
"a",
Node("i", Empty, Empty),
Node(
"x",
Node("f", Empty, Empty),
Node("r", Empty, Empty)
)
)
)
treeFromTraversals ["i"; "a"; "f"; "x"; "r"] ["a"; "i"; "x"; "f"; "r"] |> should equal expected

[<Fact>]
let ``Reject traversals of different length`` () =
let expected: Result<Tree,string> = Error "traversals must have the same length"
treeFromTraversals ["b"; "a"; "r"] ["a"; "b"] |> should equal expected

[<Fact>]
let ``Reject inconsistent traversals of same length`` () =
let expected: Result<Tree,string> = Error "traversals must have the same elements"
treeFromTraversals ["a"; "b"; "c"] ["x"; "y"; "z"] |> should equal expected

[<Fact>]
let ``Reject traversals with repeated items`` () =
let expected: Result<Tree,string> = Error "traversals must contain unique items"
treeFromTraversals ["b"; "a"; "a"] ["a"; "b"; "a"] |> should equal expected

34 changes: 34 additions & 0 deletions generators/Generators.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2056,3 +2056,37 @@ type KillerSudokuHelper() =

type StateOfTicTacToe() =
inherit ExerciseGenerator()

type Satellite() =
inherit ExerciseGenerator()

let renderTree (root: JToken) =
let rec render indent (node: JToken) =
let indentation = String(' ', indent * 4)

if node.HasValues then
let value = node["v"]
let left = node["l"] |> render (indent + 1)
let right = node["r"] |> render (indent + 1)

if node["l"].HasValues || node["r"].HasValues then
$"{indentation}Node(\n" +
$"{indentation} \"{value}\",\n" +
$"{left},\n" +
$"{right}\n" +
$"{indentation})"
else
$"{indentation}Node(\"{value}\", Empty, Empty)"
else
$"{indentation}Empty"

render 2 root

override _.PropertiesWithIdentifier _ = [ "expected" ]

override _.IdentifierTypeAnnotation(_, _, _) = Some "Result<Tree,string>"

override _.RenderExpected(_, _, value) =
match value.SelectToken "error" with
| null -> $"Ok (\n%s{renderTree value}\n )"
| error -> $"Error \"%s{string error}\""
7 changes: 0 additions & 7 deletions generators/Properties/launchSettings.json

This file was deleted.

Loading