From 72a57b4b263cbb5c02dae37552dd1014f66275c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Fernandes?= Date: Fri, 20 Sep 2024 21:03:08 -0300 Subject: [PATCH] [gleam] complete satellite --- gleam/satellite/.gitignore | 4 ++ gleam/satellite/HELP.md | 32 ++++++++++++++ gleam/satellite/README.md | 38 ++++++++++++++++ gleam/satellite/gleam.toml | 12 +++++ gleam/satellite/manifest.toml | 28 ++++++++++++ gleam/satellite/src/satellite.gleam | 46 ++++++++++++++++++++ gleam/satellite/test/satellite_test.gleam | 53 +++++++++++++++++++++++ 7 files changed, 213 insertions(+) create mode 100644 gleam/satellite/.gitignore create mode 100644 gleam/satellite/HELP.md create mode 100644 gleam/satellite/README.md create mode 100644 gleam/satellite/gleam.toml create mode 100644 gleam/satellite/manifest.toml create mode 100644 gleam/satellite/src/satellite.gleam create mode 100644 gleam/satellite/test/satellite_test.gleam diff --git a/gleam/satellite/.gitignore b/gleam/satellite/.gitignore new file mode 100644 index 0000000..170cca9 --- /dev/null +++ b/gleam/satellite/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +build +erl_crash.dump diff --git a/gleam/satellite/HELP.md b/gleam/satellite/HELP.md new file mode 100644 index 0000000..03c67a9 --- /dev/null +++ b/gleam/satellite/HELP.md @@ -0,0 +1,32 @@ +# Help + +## Running the tests + +To run the tests, run the command `gleam test` from within the exercise directory. + +## Submitting your solution + +You can submit your solution using the `exercism submit src/satellite.gleam` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Gleam track's documentation](https://exercism.org/docs/tracks/gleam) +- The [Gleam track's programming category on the forum](https://forum.exercism.org/c/programming/gleam) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +To get help if you're having trouble, you can use one of the following resources: + +- [gleam.run](https://gleam.run/documentation/) is the gleam official documentation. +- [Discord](https://discord.gg/Fm8Pwmy) is the discord channel. +- [StackOverflow](https://stackoverflow.com/questions/tagged/gleam) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions. \ No newline at end of file diff --git a/gleam/satellite/README.md b/gleam/satellite/README.md new file mode 100644 index 0000000..3d26d93 --- /dev/null +++ b/gleam/satellite/README.md @@ -0,0 +1,38 @@ +# Satellite + +Welcome to Satellite on Exercism's Gleam Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## 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 + +## Source + +### Created by + +- @jiegillet \ No newline at end of file diff --git a/gleam/satellite/gleam.toml b/gleam/satellite/gleam.toml new file mode 100644 index 0000000..fbd13ab --- /dev/null +++ b/gleam/satellite/gleam.toml @@ -0,0 +1,12 @@ +name = "satellite" +version = "0.1.0" + +[dependencies] +gleam_bitwise = "~> 1.2" +gleam_otp = "~> 0.7 or ~> 1.0" +gleam_stdlib = "~> 0.32 or ~> 1.0" +simplifile = "~> 1.0" +gleam_erlang = ">= 0.25.0 and < 1.0.0" + +[dev-dependencies] +exercism_test_runner = "~> 1.4" diff --git a/gleam/satellite/manifest.toml b/gleam/satellite/manifest.toml new file mode 100644 index 0000000..3d13c8c --- /dev/null +++ b/gleam/satellite/manifest.toml @@ -0,0 +1,28 @@ +# This file was generated by Gleam +# You typically do not need to edit this file + +packages = [ + { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, + { name = "exercism_test_runner", version = "1.8.0", build_tools = ["gleam"], requirements = ["argv", "gap", "glance", "gleam_community_ansi", "gleam_erlang", "gleam_json", "gleam_stdlib", "simplifile"], otp_app = "exercism_test_runner", source = "hex", outer_checksum = "B944D89A9D049897DF28C63D595D89CB54D8C407D06EFFCE4CDA8C3EC1C9F51E" }, + { name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" }, + { name = "gap", version = "1.1.3", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_stdlib"], otp_app = "gap", source = "hex", outer_checksum = "6EF5E3B523FDFBC317E9EA28D5163EE04744A97C007106F90207569789612291" }, + { name = "glance", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "8F3314D27773B7C3B9FB58D8C02C634290422CE531988C0394FA0DF8676B964D" }, + { name = "gleam_bitwise", version = "1.3.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_bitwise", source = "hex", outer_checksum = "B36E1D3188D7F594C7FD4F43D0D2CE17561DE896202017548578B16FE1FE9EFC" }, + { name = "gleam_community_ansi", version = "1.4.1", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "4CD513FC62523053E62ED7BAC2F36136EC17D6A8942728250A9A00A15E340E4B" }, + { name = "gleam_community_colour", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "795964217EBEDB3DA656F5EB8F67D7AD22872EB95182042D3E7AFEF32D3FD2FE" }, + { name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" }, + { name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" }, + { name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" }, + { name = "gleam_stdlib", version = "0.39.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "2D7DE885A6EA7F1D5015D1698920C9BAF7241102836CE0C3837A4F160128A9C4" }, + { name = "glexer", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glexer", source = "hex", outer_checksum = "BD477AD657C2B637FEF75F2405FAEFFA533F277A74EF1A5E17B55B1178C228FB" }, + { name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" }, + { name = "thoas", version = "1.2.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "E38697EDFFD6E91BD12CEA41B155115282630075C2A727E7A6B2947F5408B86A" }, +] + +[requirements] +exercism_test_runner = { version = "~> 1.4" } +gleam_bitwise = { version = "~> 1.2" } +gleam_erlang = { version = ">= 0.25.0 and < 1.0.0" } +gleam_otp = { version = "~> 0.7 or ~> 1.0" } +gleam_stdlib = { version = "~> 0.32 or ~> 1.0" } +simplifile = { version = "~> 1.0" } diff --git a/gleam/satellite/src/satellite.gleam b/gleam/satellite/src/satellite.gleam new file mode 100644 index 0000000..d39e3fe --- /dev/null +++ b/gleam/satellite/src/satellite.gleam @@ -0,0 +1,46 @@ +import gleam/bool +import gleam/list +import gleam/set + +pub type Tree(a) { + Nil + Node(value: a, left: Tree(a), right: Tree(a)) +} + +pub type Error { + DifferentLengths + DifferentItems + NonUniqueItems +} + +pub fn tree_from_traversals( + inorder inorder: List(a), + preorder preorder: List(a), +) -> Result(Tree(a), Error) { + use <- bool.guard( + list.length(inorder) != list.length(preorder), + Error(DifferentLengths), + ) + + use <- bool.guard( + set.size(set.from_list(inorder)) != list.length(inorder), + Error(NonUniqueItems), + ) + + use <- bool.guard( + set.from_list(inorder) != set.from_list(preorder), + Error(DifferentItems), + ) + + Ok(traverse(inorder, preorder)) +} + +fn traverse(inorder: List(a), preorder: List(a)) -> Tree(a) { + use <- bool.guard(list.is_empty(inorder), Nil) + + let assert Ok(root) = list.find(preorder, list.contains(inorder, _)) + let assert #(left, [_, ..right]) = + list.split_while(inorder, fn(ch) { ch != root }) + + Node(root, traverse(left, preorder), traverse(right, preorder)) +} diff --git a/gleam/satellite/test/satellite_test.gleam b/gleam/satellite/test/satellite_test.gleam new file mode 100644 index 0000000..2c306ce --- /dev/null +++ b/gleam/satellite/test/satellite_test.gleam @@ -0,0 +1,53 @@ +import exercism/should +import exercism/test_runner +import satellite.{DifferentItems, DifferentLengths, Nil, Node, NonUniqueItems} + +pub fn main() { + test_runner.main() +} + +pub fn empty_tree_test() { + satellite.tree_from_traversals(inorder: [], preorder: []) + |> should.equal(Ok(Nil)) +} + +pub fn tree_with_one_item_test() { + satellite.tree_from_traversals(inorder: ["a"], preorder: ["a"]) + |> should.equal(Ok(Node(value: "a", left: Nil, right: Nil))) +} + +pub fn tree_with_many_items_test() { + satellite.tree_from_traversals(inorder: ["i", "a", "f", "x", "r"], preorder: [ + "a", "i", "x", "f", "r", + ]) + |> should.equal( + Ok(Node( + value: "a", + left: Node(value: "i", left: Nil, right: Nil), + right: Node( + value: "x", + left: Node(value: "f", left: Nil, right: Nil), + right: Node(value: "r", left: Nil, right: Nil), + ), + )), + ) +} + +pub fn reject_traversals_of_different_length_test() { + satellite.tree_from_traversals(inorder: ["b", "a", "r"], preorder: ["a", "b"]) + |> should.equal(Error(DifferentLengths)) +} + +pub fn reject_inconsistent_traversals_of_same_length_test() { + satellite.tree_from_traversals(inorder: ["a", "b", "c"], preorder: [ + "x", "y", "z", + ]) + |> should.equal(Error(DifferentItems)) +} + +pub fn reject_traversals_with_repeated_items_test() { + satellite.tree_from_traversals(inorder: ["b", "a", "a"], preorder: [ + "a", "b", "a", + ]) + |> should.equal(Error(NonUniqueItems)) +}