From 3ddbb329ceda631449b1e5c4a79cefccd8a12be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Gillet?= Date: Sat, 12 Jun 2021 13:56:27 +0900 Subject: [PATCH 1/4] [#726] New practice exercise --- config.json | 15 ++++++ .../practice/satellite/.docs/instructions.md | 29 +++++++++++ exercises/practice/satellite/.formatter.exs | 4 ++ .../practice/satellite/.meta/config.json | 18 +++++++ exercises/practice/satellite/.meta/example.ex | 41 +++++++++++++++ exercises/practice/satellite/.meta/tests.toml | 22 ++++++++ exercises/practice/satellite/lib/satellite.ex | 14 +++++ exercises/practice/satellite/mix.exs | 28 ++++++++++ .../satellite/test/satellite_test.exs | 52 +++++++++++++++++++ .../practice/satellite/test/test_helper.exs | 2 + 10 files changed, 225 insertions(+) create mode 100644 exercises/practice/satellite/.docs/instructions.md create mode 100644 exercises/practice/satellite/.formatter.exs create mode 100644 exercises/practice/satellite/.meta/config.json create mode 100644 exercises/practice/satellite/.meta/example.ex create mode 100644 exercises/practice/satellite/.meta/tests.toml create mode 100644 exercises/practice/satellite/lib/satellite.ex create mode 100644 exercises/practice/satellite/mix.exs create mode 100644 exercises/practice/satellite/test/satellite_test.exs create mode 100644 exercises/practice/satellite/test/test_helper.exs diff --git a/config.json b/config.json index e910031b30..a5b7808e0a 100644 --- a/config.json +++ b/config.json @@ -2380,6 +2380,21 @@ ], "difficulty": 9 }, + { + "slug": "satellite", + "name": "Satellite", + "uuid": "a07e01e6-7cea-4db9-a514-7c95788e90a9", + "prerequisites": [ + "pattern-matching", + "tuple", + "cond", + "recursion" + ], + "practices": [ + "recusrion" + ], + "difficulty": 6 + }, { "slug": "zebra-puzzle", "name": "Zebra Puzzle", diff --git a/exercises/practice/satellite/.docs/instructions.md b/exercises/practice/satellite/.docs/instructions.md new file mode 100644 index 0000000000..3a8077960f --- /dev/null +++ b/exercises/practice/satellite/.docs/instructions.md @@ -0,0 +1,29 @@ +# Description + +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] + +``` + 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 diff --git a/exercises/practice/satellite/.formatter.exs b/exercises/practice/satellite/.formatter.exs new file mode 100644 index 0000000000..d2cda26edd --- /dev/null +++ b/exercises/practice/satellite/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/exercises/practice/satellite/.meta/config.json b/exercises/practice/satellite/.meta/config.json new file mode 100644 index 0000000000..ca834e65a6 --- /dev/null +++ b/exercises/practice/satellite/.meta/config.json @@ -0,0 +1,18 @@ +{ + "blurb": "Rebuild binary trees from pre-order and in-order traversals.", + "authors": [ + "jiegillet" + ], + "contributors": [], + "files": { + "solution": [ + "lib/satellite.ex" + ], + "test": [ + "test/satellite_test.exs" + ], + "example": [ + ".meta/example.ex" + ] + } +} diff --git a/exercises/practice/satellite/.meta/example.ex b/exercises/practice/satellite/.meta/example.ex new file mode 100644 index 0000000000..663a27566b --- /dev/null +++ b/exercises/practice/satellite/.meta/example.ex @@ -0,0 +1,41 @@ +defmodule Satellite do + @typedoc """ + A tree, which can be empty, or made from a left branch, a node and a right branch + """ + @type tree :: {} | {tree, any, tree} + + @doc """ + Build a tree from the elements given in a pre-order and in-order style + """ + @spec build_tree(preorder :: [any], inorder :: [any]) :: tree | {:error, String.t()} + + def build_tree(preorder, inorder) do + p_length = length(preorder) + i_length = length(inorder) + p_set = MapSet.new(preorder) + i_set = MapSet.new(inorder) + + cond do + p_length != i_length -> {:error, "traversals must have the same length"} + p_set != i_set -> {:error, "traversals must have the same elements"} + p_length != MapSet.size(p_set) -> {:error, "traversals must contain unique items"} + true -> build_tree(preorder, inorder, :safe) + end + end + + def build_tree([], [], :safe), do: {} + + def build_tree([root | preorder], inorder, :safe) do + {in_left, in_right, pre_left, pre_right} = split(root, inorder, preorder) + + {build_tree(pre_left, in_left, :safe), root, build_tree(pre_right, in_right, :safe)} + end + + defp split(root, [root | inorder], preorder), do: {[], inorder, [], preorder} + + defp split(root, [i | inorder], [p | preorder]) do + {in_left, in_right, pre_left, pre_right} = split(root, inorder, preorder) + + {[i | in_left], in_right, [p | pre_left], pre_right} + end +end diff --git a/exercises/practice/satellite/.meta/tests.toml b/exercises/practice/satellite/.meta/tests.toml new file mode 100644 index 0000000000..2d5ff6015d --- /dev/null +++ b/exercises/practice/satellite/.meta/tests.toml @@ -0,0 +1,22 @@ +# This is an auto-generated file. Regular comments will be removed when this +# file is regenerated. Regenerating will not touch any manually added keys, +# so comments can be added in 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" + diff --git a/exercises/practice/satellite/lib/satellite.ex b/exercises/practice/satellite/lib/satellite.ex new file mode 100644 index 0000000000..12ff2bcf99 --- /dev/null +++ b/exercises/practice/satellite/lib/satellite.ex @@ -0,0 +1,14 @@ +defmodule Satellite do + @typedoc """ + A tree, which can be empty, or made from a left branch, a node and a right branch + """ + @type tree :: {} | {tree, any, tree} + + @doc """ + Build a tree from the elements given in a pre-order and in-order style + """ + @spec build_tree(preorder :: [any], inorder :: [any]) :: tree | {:error, String.t()} + + def build_tree(preorder, inorder) do + end +end diff --git a/exercises/practice/satellite/mix.exs b/exercises/practice/satellite/mix.exs new file mode 100644 index 0000000000..370bdd443c --- /dev/null +++ b/exercises/practice/satellite/mix.exs @@ -0,0 +1,28 @@ +defmodule Satellite.MixProject do + use Mix.Project + + def project do + [ + app: :satellite, + version: "0.1.0", + # elixir: "~> 1.8", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/exercises/practice/satellite/test/satellite_test.exs b/exercises/practice/satellite/test/satellite_test.exs new file mode 100644 index 0000000000..33cee4cfa0 --- /dev/null +++ b/exercises/practice/satellite/test/satellite_test.exs @@ -0,0 +1,52 @@ +defmodule SatelliteTest do + use ExUnit.Case + + # @tag :pending + test "Empty tree" do + preorder = [] + inorder = [] + tree = {} + assert Satellite.build_tree(preorder, inorder) == tree + end + + @tag :pending + test "Tree with one item" do + preorder = [:a] + inorder = [:a] + tree = {{}, :a, {}} + assert Satellite.build_tree(preorder, inorder) == tree + end + + @tag :pending + test "Tree with many items" do + preorder = ~w(a i x f r)a + inorder = ~w(i a f x r)a + tree = {{{}, :i, {}}, :a, {{{}, :f, {}}, :x, {{}, :r, {}}}} + + assert Satellite.build_tree(preorder, inorder) == tree + end + + @tag :pending + test "Reject traversals of different length" do + preorder = [:a, :b] + inorder = [:b, :a, :r] + error = {:error, "traversals must have the same length"} + assert Satellite.build_tree(preorder, inorder) == error + end + + @tag :pending + test "Reject inconsistent traversals of same length" do + preorder = [:x, :y, :z] + inorder = [:a, :b, :c] + error = {:error, "traversals must have the same elements"} + assert Satellite.build_tree(preorder, inorder) == error + end + + @tag :pending + test "Reject traversals with repeated items" do + preorder = [:a, :b, :a] + inorder = [:b, :a, :a] + error = {:error, "traversals must contain unique items"} + assert Satellite.build_tree(preorder, inorder) == error + end +end diff --git a/exercises/practice/satellite/test/test_helper.exs b/exercises/practice/satellite/test/test_helper.exs new file mode 100644 index 0000000000..35fc5bff82 --- /dev/null +++ b/exercises/practice/satellite/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.start() +ExUnit.configure(exclude: :pending, trace: true) From c432839213fffbd52d5a6f7b6d3571e04d7271c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Gillet?= Date: Sat, 12 Jun 2021 22:41:02 +0900 Subject: [PATCH 2/4] Change type to {:ok, tree} --- exercises/practice/satellite/.meta/example.ex | 4 ++-- exercises/practice/satellite/lib/satellite.ex | 2 +- exercises/practice/satellite/test/satellite_test.exs | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/exercises/practice/satellite/.meta/example.ex b/exercises/practice/satellite/.meta/example.ex index 663a27566b..778a30e40c 100644 --- a/exercises/practice/satellite/.meta/example.ex +++ b/exercises/practice/satellite/.meta/example.ex @@ -7,7 +7,7 @@ defmodule Satellite do @doc """ Build a tree from the elements given in a pre-order and in-order style """ - @spec build_tree(preorder :: [any], inorder :: [any]) :: tree | {:error, String.t()} + @spec build_tree(preorder :: [any], inorder :: [any]) :: {:ok, tree} | {:error, String.t()} def build_tree(preorder, inorder) do p_length = length(preorder) @@ -19,7 +19,7 @@ defmodule Satellite do p_length != i_length -> {:error, "traversals must have the same length"} p_set != i_set -> {:error, "traversals must have the same elements"} p_length != MapSet.size(p_set) -> {:error, "traversals must contain unique items"} - true -> build_tree(preorder, inorder, :safe) + true -> {:ok, build_tree(preorder, inorder, :safe)} end end diff --git a/exercises/practice/satellite/lib/satellite.ex b/exercises/practice/satellite/lib/satellite.ex index 12ff2bcf99..7768a85e9a 100644 --- a/exercises/practice/satellite/lib/satellite.ex +++ b/exercises/practice/satellite/lib/satellite.ex @@ -7,7 +7,7 @@ defmodule Satellite do @doc """ Build a tree from the elements given in a pre-order and in-order style """ - @spec build_tree(preorder :: [any], inorder :: [any]) :: tree | {:error, String.t()} + @spec build_tree(preorder :: [any], inorder :: [any]) :: {:ok, tree} | {:error, String.t()} def build_tree(preorder, inorder) do end diff --git a/exercises/practice/satellite/test/satellite_test.exs b/exercises/practice/satellite/test/satellite_test.exs index 33cee4cfa0..f4b393a84a 100644 --- a/exercises/practice/satellite/test/satellite_test.exs +++ b/exercises/practice/satellite/test/satellite_test.exs @@ -6,7 +6,7 @@ defmodule SatelliteTest do preorder = [] inorder = [] tree = {} - assert Satellite.build_tree(preorder, inorder) == tree + assert Satellite.build_tree(preorder, inorder) == {:ok, tree} end @tag :pending @@ -14,7 +14,7 @@ defmodule SatelliteTest do preorder = [:a] inorder = [:a] tree = {{}, :a, {}} - assert Satellite.build_tree(preorder, inorder) == tree + assert Satellite.build_tree(preorder, inorder) == {:ok, tree} end @tag :pending @@ -22,8 +22,7 @@ defmodule SatelliteTest do preorder = ~w(a i x f r)a inorder = ~w(i a f x r)a tree = {{{}, :i, {}}, :a, {{{}, :f, {}}, :x, {{}, :r, {}}}} - - assert Satellite.build_tree(preorder, inorder) == tree + assert Satellite.build_tree(preorder, inorder) == {:ok, tree} end @tag :pending From ee04547ca6fdb155098d986bdde3c145f8037cc9 Mon Sep 17 00:00:00 2001 From: Jie Date: Sat, 12 Jun 2021 22:42:52 +0900 Subject: [PATCH 3/4] Typos and prerequisites Co-authored-by: Angelika Tyborska --- config.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/config.json b/config.json index a5b7808e0a..7e211a7840 100644 --- a/config.json +++ b/config.json @@ -2386,12 +2386,15 @@ "uuid": "a07e01e6-7cea-4db9-a514-7c95788e90a9", "prerequisites": [ "pattern-matching", - "tuple", + "tuples", "cond", - "recursion" + "recursion", + "atoms", + "lists", + "enum" ], "practices": [ - "recusrion" + "recursion" ], "difficulty": 6 }, From 178499b270422a39320d3d1520659b68924f3192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Gillet?= Date: Sat, 12 Jun 2021 22:43:47 +0900 Subject: [PATCH 4/4] Update contributions --- exercises/practice/satellite/.meta/config.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exercises/practice/satellite/.meta/config.json b/exercises/practice/satellite/.meta/config.json index ca834e65a6..3cd9373242 100644 --- a/exercises/practice/satellite/.meta/config.json +++ b/exercises/practice/satellite/.meta/config.json @@ -3,7 +3,9 @@ "authors": [ "jiegillet" ], - "contributors": [], + "contributors": [ + "angelikatyborska" + ], "files": { "solution": [ "lib/satellite.ex"