From b8181175c9dd97bb389c4387586b1cb25accf0b0 Mon Sep 17 00:00:00 2001 From: Alexander Heldt Date: Mon, 3 Nov 2025 21:47:09 +0100 Subject: [PATCH] tracks-on-tracks-on-tracks --- .../.exercism/config.json | 25 ++++ .../.exercism/metadata.json | 1 + tracks-on-tracks-on-tracks/.gitignore | 4 + tracks-on-tracks-on-tracks/HELP.md | 32 ++++ tracks-on-tracks-on-tracks/HINTS.md | 28 ++++ tracks-on-tracks-on-tracks/README.md | 141 ++++++++++++++++++ tracks-on-tracks-on-tracks/gleam.toml | 14 ++ tracks-on-tracks-on-tracks/manifest.toml | 31 ++++ .../src/tracks_on_tracks_on_tracks.gleam | 36 +++++ .../tracks_on_tracks_on_tracks_test.gleam | 130 ++++++++++++++++ 10 files changed, 442 insertions(+) create mode 100644 tracks-on-tracks-on-tracks/.exercism/config.json create mode 100644 tracks-on-tracks-on-tracks/.exercism/metadata.json create mode 100644 tracks-on-tracks-on-tracks/.gitignore create mode 100644 tracks-on-tracks-on-tracks/HELP.md create mode 100644 tracks-on-tracks-on-tracks/HINTS.md create mode 100644 tracks-on-tracks-on-tracks/README.md create mode 100644 tracks-on-tracks-on-tracks/gleam.toml create mode 100644 tracks-on-tracks-on-tracks/manifest.toml create mode 100644 tracks-on-tracks-on-tracks/src/tracks_on_tracks_on_tracks.gleam create mode 100644 tracks-on-tracks-on-tracks/test/tracks_on_tracks_on_tracks_test.gleam diff --git a/tracks-on-tracks-on-tracks/.exercism/config.json b/tracks-on-tracks-on-tracks/.exercism/config.json new file mode 100644 index 0000000..fa32e30 --- /dev/null +++ b/tracks-on-tracks-on-tracks/.exercism/config.json @@ -0,0 +1,25 @@ +{ + "authors": [ + "lpil" + ], + "files": { + "solution": [ + "src/tracks_on_tracks_on_tracks.gleam" + ], + "test": [ + "test/tracks_on_tracks_on_tracks_test.gleam" + ], + "exemplar": [ + ".meta/example.gleam" + ], + "invalidator": [ + "gleam.toml", + "manifest.toml" + ] + }, + "forked_from": [ + "fsharp/tracks-on-tracks-on-tracks", + "elm/tracks-on-tracks-on-tracks" + ], + "blurb": "Learn abouts lists by keeping track of the programming languages you want to learn." +} diff --git a/tracks-on-tracks-on-tracks/.exercism/metadata.json b/tracks-on-tracks-on-tracks/.exercism/metadata.json new file mode 100644 index 0000000..f1adb3c --- /dev/null +++ b/tracks-on-tracks-on-tracks/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"gleam","exercise":"tracks-on-tracks-on-tracks","id":"45633801cbc44ee598fd630722a10e7e","url":"https://exercism.org/tracks/gleam/exercises/tracks-on-tracks-on-tracks","handle":"fw353qwgs","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/tracks-on-tracks-on-tracks/.gitignore b/tracks-on-tracks-on-tracks/.gitignore new file mode 100644 index 0000000..170cca9 --- /dev/null +++ b/tracks-on-tracks-on-tracks/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +build +erl_crash.dump diff --git a/tracks-on-tracks-on-tracks/HELP.md b/tracks-on-tracks-on-tracks/HELP.md new file mode 100644 index 0000000..ba1b17b --- /dev/null +++ b/tracks-on-tracks-on-tracks/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/tracks_on_tracks_on_tracks.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/tracks-on-tracks-on-tracks/HINTS.md b/tracks-on-tracks-on-tracks/HINTS.md new file mode 100644 index 0000000..35e3703 --- /dev/null +++ b/tracks-on-tracks-on-tracks/HINTS.md @@ -0,0 +1,28 @@ +# Hints + +## 1. Create a new list + +- An empty list can be created using the `[]` syntax. + +## 2. Define an existing list + +- Lists with multiple elements can be created using the `["a", "b", "c"]` syntax. + +## 3. Add a new language to a list + +- The spread syntax (`[x, ..list]`) can be used to add an element to the beginning of a list. + +## 4. Count the languages in the list + +- There is a function in the `gleam/list` module to [count the elements in a list][length]. + +## 5. Reverse the list + +- There is a function in the `gleam/list` module to [reverse a list][reverse]. + +## 6. Check if list is exciting + +- You can use pattern matching using the list and list spread patterns to match on specific list structures. + +[reverse]: https://hexdocs.pm/gleam_stdlib/gleam/list.html#reverse +[length]: https://hexdocs.pm/gleam_stdlib/gleam/list.html#length \ No newline at end of file diff --git a/tracks-on-tracks-on-tracks/README.md b/tracks-on-tracks-on-tracks/README.md new file mode 100644 index 0000000..2f92811 --- /dev/null +++ b/tracks-on-tracks-on-tracks/README.md @@ -0,0 +1,141 @@ +# Tracks on Tracks on Tracks + +Welcome to Tracks on Tracks on Tracks on Exercism's Gleam Track. +If you need help running the tests or submitting your code, check out `HELP.md`. +If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :) + +## Introduction + +## Lists + +A list in Gleam is an immutable collection of zero or more values. The values in a list must all have the same type. As lists are immutable, once a list has been constructed, its value can never change. Any functions/operators that appear to modify a list (such as adding an element), will actually return a new list. + +Lists can be defined as follows: + +```gleam +let empty = [] +let singleValue = [5] +let threeValues = ["a", "b", "c"] +``` + +The most common way to add an element to a list is through the spread syntax: + +```gleam +let two_to_four = [2, 3, 4] +let one_to_four = [1, ..two_to_four] +// -> [1, 2, 3, 4] +``` + +The [`gleam/list`](https://hexdocs.pm/gleam_stdlib/gleam/list.html) module in the Gleam standard library contains many useful functions for working with lists. This module is very commonly used in Gleam code so it is good to be familiar with it. + +Lists patterns can be used in case expressions to match on lists and assign contained values to variables: + +```gleam +pub fn describe(list: List(String)) -> String { + case list { + [] -> "Empty list" + [x] -> "List with one item: " <> x + [x, y] -> "List with two items: " <> x <> " and " <> y + _ -> "List with three or more items" + } +} +``` + +As well as matching on exact length lists, the spread syntax can be used to match on lists of at-least a certain length: + +```gleam +pub fn describe(list: List(String)) -> String { + case list { + [_, _, ..] -> "List with at least two items" + [_] -> "List with one item" + [] -> "Empty list" + } +} +``` + +The spread syntax can also be used to assign the rest of the list to a variable: + +```gleam +pub fn remove_first_item(list: List(String)) -> List(String) { + case list { + // Return the list without the first item + [_, ..rest] -> rest + + // There's no first item to remove, return an empty list + _ -> [] + } +} +``` + +Case expressions should have a pattern for every possible value of the type being matched on, so a final discard pattern (`_`) is often used to handle any remaining values. + +## Instructions + +In this exercise you'll be writing code to keep track of a list of programming languages you want to learn on Exercism. + +You have six tasks, which will all involve dealing with lists. + +## 1. Create a new list + +To keep track of the languages you want to learn, you'll need to create a new list. Define the `new_list` function that returns a new, empty list. + +```gleam +new_list() +// -> [] +``` + +## 2. Define an existing list + +Currently, you have a piece of paper listing the languages you want to learn: Gleam, Go, and TypeScript. Define the `existing_list` function to return this list. + +```gleam +existing_list() +// -> ["Gleam", "Go", "TypeScript"] +``` + +## 3. Add a new language to a list + +As you explore Exercism and find more interesting languages, you want to add them to your list. Implement the `add_language` function to add a new language to the beginning of your list. + +```gleam +add_language(["OCaml", "Elixir"], "Scheme") +// -> ["Scheme", "OCaml", "Elixir"] +``` + +## 4. Count the languages in the list + +Counting the languages one-by-one is inconvenient. Implement the `count_languages` function to count the number of languages on your list. + +```gleam +count_languages(["jq", "Elm", "Rust", "Kotlin"]) +// -> 4 +``` + +## 5. Reverse the list + +At some point, you realize that your list is actually ordered backwards! Implement the `reverse_list` function to reverse your list. + +```gleam +reverse_list(["Python", "Julia", "Idris", "COBOL"]) +// -> ["COBOL", "Idris", "Julia", "Python"] +``` + +## 6. Check if list is exciting + +While you love all languages, Gleam has a special place in your heart. As such, you're really excited about a list of languages if: + +- The first on the list is Gleam. +- The second item on the list is Gleam and the list contain either two or three languages. + +Implement the `exciting_list` function to check if a list of languages is exciting: + +```gleam +exciting_list(["Lua", "Gleam"]) +// -> True +``` + +## Source + +### Created by + +- @lpil \ No newline at end of file diff --git a/tracks-on-tracks-on-tracks/gleam.toml b/tracks-on-tracks-on-tracks/gleam.toml new file mode 100644 index 0000000..6c4a560 --- /dev/null +++ b/tracks-on-tracks-on-tracks/gleam.toml @@ -0,0 +1,14 @@ +name = "tracks_on_tracks_on_tracks" +version = "0.1.0" + +[dependencies] +gleam_otp = "~> 0.7 or ~> 1.0" +gleam_stdlib = ">= 0.54.0 or ~> 1.0" +simplifile = "~> 1.0" +gleam_erlang = ">= 0.25.0 and < 1.0.0" +gleam_yielder = ">= 1.1.0 and < 2.0.0" +gleam_regexp = ">= 1.1.0 and < 2.0.0" +gleam_deque = ">= 1.0.0 and < 2.0.0" + +[dev-dependencies] +exercism_test_runner = "~> 1.9" diff --git a/tracks-on-tracks-on-tracks/manifest.toml b/tracks-on-tracks-on-tracks/manifest.toml new file mode 100644 index 0000000..7b32e9a --- /dev/null +++ b/tracks-on-tracks-on-tracks/manifest.toml @@ -0,0 +1,31 @@ +# 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.9.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 = "0B17BB25F2FF1E60266467C24FE0CA04005410306AA05E9A4B41B1852D72865C" }, + { name = "filepath", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "67A6D15FB39EEB69DD31F8C145BB5A421790581BD6AA14B33D64D5A55DBD6587" }, + { 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 = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "E155BA1A787FD11827048355021C0390D2FE9A518485526F631A9D472858CC6D" }, + { name = "gleam_community_ansi", version = "1.4.3", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "8A62AE9CC6EA65BEA630D95016D6C07E4F9973565FA3D0DE68DC4200D8E0DD27" }, + { name = "gleam_community_colour", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "FDD6AC62C6EC8506C005949A4FCEF032038191D5EAAEC3C9A203CD53AE956ACA" }, + { name = "gleam_deque", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_deque", source = "hex", outer_checksum = "64D77068931338CF0D0CB5D37522C3E3CCA7CB7D6C5BACB41648B519CC0133C7" }, + { name = "gleam_erlang", version = "0.34.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "0C38F2A128BAA0CEF17C3000BD2097EB80634E239CE31A86400C4416A5D0FDCC" }, + { name = "gleam_json", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "C55C5C2B318533A8072D221C5E06E5A75711C129E420DD1CE463342106012E5D" }, + { name = "gleam_otp", version = "0.16.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "50DA1539FC8E8FA09924EB36A67A2BBB0AD6B27BCDED5A7EF627057CF69D035E" }, + { name = "gleam_regexp", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "7F5E0C0BBEB3C58E57C9CB05FA9002F970C85AD4A63BA1E55CBCB35C15809179" }, + { name = "gleam_stdlib", version = "0.55.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "32D8F4AE03771516950047813A9E359249BD9FBA5C33463FDB7B953D6F8E896B" }, + { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, + { name = "glexer", version = "2.2.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glexer", source = "hex", outer_checksum = "5C235CBDF4DA5203AD5EAB1D6D8B456ED8162C5424FE2309CFFB7EF438B7C269" }, + { name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" }, +] + +[requirements] +exercism_test_runner = { version = "~> 1.9" } +gleam_deque = { version = ">= 1.0.0 and < 2.0.0" } +gleam_erlang = { version = ">= 0.25.0 and < 1.0.0" } +gleam_otp = { version = "~> 0.7 or ~> 1.0" } +gleam_regexp = { version = ">= 1.1.0 and < 2.0.0" } +gleam_stdlib = { version = ">= 0.54.0 or ~> 1.0" } +gleam_yielder = { version = ">= 1.1.0 and < 2.0.0" } +simplifile = { version = "~> 1.0" } diff --git a/tracks-on-tracks-on-tracks/src/tracks_on_tracks_on_tracks.gleam b/tracks-on-tracks-on-tracks/src/tracks_on_tracks_on_tracks.gleam new file mode 100644 index 0000000..ff46fac --- /dev/null +++ b/tracks-on-tracks-on-tracks/src/tracks_on_tracks_on_tracks.gleam @@ -0,0 +1,36 @@ +import gleam/list + +pub fn new_list() -> List(String) { + [] +} + +pub fn existing_list() -> List(String) { + ["Gleam", "Go", "TypeScript"] +} + +pub fn add_language(languages: List(String), language: String) -> List(String) { + [language, ..languages] +} + +pub fn count_languages(languages: List(String)) -> Int { + list.length(languages) +} + +pub fn reverse_list(languages: List(String)) -> List(String) { + list.reverse(languages) +} + +pub fn exciting_list(languages: List(String)) -> Bool { + // - The first on the list is Gleam. + // - The second item on the list is Gleam and the list contain either two or three languages. + case languages { + [first] -> first == "Gleam" + [first, second, ..] -> + first == "Gleam" + || { + second == "Gleam" + && { list.length(languages) == 2 || list.length(languages) == 3 } + } + _ -> False + } +} diff --git a/tracks-on-tracks-on-tracks/test/tracks_on_tracks_on_tracks_test.gleam b/tracks-on-tracks-on-tracks/test/tracks_on_tracks_on_tracks_test.gleam new file mode 100644 index 0000000..48c8deb --- /dev/null +++ b/tracks-on-tracks-on-tracks/test/tracks_on_tracks_on_tracks_test.gleam @@ -0,0 +1,130 @@ +import exercism/should +import exercism/test_runner +import tracks_on_tracks_on_tracks + +pub fn main() { + test_runner.main() +} + +pub fn new_list_test() { + tracks_on_tracks_on_tracks.new_list() + |> should.equal([]) +} + +pub fn existing_list_test() { + tracks_on_tracks_on_tracks.existing_list() + |> should.equal(["Gleam", "Go", "TypeScript"]) +} + +pub fn add_language_to_new_list_test() { + tracks_on_tracks_on_tracks.add_language([], "Elixir") + |> should.equal(["Elixir"]) +} + +pub fn add_language_to_existing_list_test() { + tracks_on_tracks_on_tracks.add_language(["Gleam", "Go", "TypeScript"], "Lua") + |> should.equal(["Lua", "Gleam", "Go", "TypeScript"]) +} + +pub fn add_language_to_custom_list_test() { + tracks_on_tracks_on_tracks.add_language(["Scheme"], "Racket") + |> should.equal(["Racket", "Scheme"]) +} + +pub fn count_languages_on_new_list_test() { + tracks_on_tracks_on_tracks.count_languages( + tracks_on_tracks_on_tracks.new_list(), + ) + |> should.equal(0) +} + +pub fn count_languages_on_existing_list_test() { + tracks_on_tracks_on_tracks.count_languages( + tracks_on_tracks_on_tracks.existing_list(), + ) + |> should.equal(3) +} + +pub fn count_languages_on_custom_list_test() { + tracks_on_tracks_on_tracks.count_languages(["Python", "JavaScript"]) + |> should.equal(2) +} + +pub fn reverse_order_of_new_list_test() { + tracks_on_tracks_on_tracks.reverse_list(tracks_on_tracks_on_tracks.new_list()) + |> should.equal([]) +} + +pub fn reverse_order_of_existing_list_test() { + tracks_on_tracks_on_tracks.reverse_list( + tracks_on_tracks_on_tracks.existing_list(), + ) + |> should.equal(["TypeScript", "Go", "Gleam"]) +} + +pub fn reverse_order_of_custom_list_test() { + tracks_on_tracks_on_tracks.reverse_list(["Kotlin", "Java", "Scala", "Clojure"]) + |> should.equal(["Clojure", "Scala", "Java", "Kotlin"]) +} + +pub fn empty_list_is_not_exciting_test() { + let assert False = tracks_on_tracks_on_tracks.exciting_list([]) +} + +pub fn singleton_list_with_gleam_is_exciting_test() { + let assert True = tracks_on_tracks_on_tracks.exciting_list(["Gleam"]) +} + +pub fn singleton_list_without_gleam_is_not_exciting_test() { + let assert False = tracks_on_tracks_on_tracks.exciting_list(["Go"]) +} + +pub fn two_item_list_with_gleam_as_first_item_is_exciting_test() { + let assert True = + tracks_on_tracks_on_tracks.exciting_list(["Gleam", "Clojure"]) +} + +pub fn two_item_list_with_gleam_as_second_item_is_exciting_test() { + let assert True = tracks_on_tracks_on_tracks.exciting_list(["Raku", "Gleam"]) +} + +pub fn two_item_list_without_gleam_is_not_exciting_test() { + let assert False = tracks_on_tracks_on_tracks.exciting_list(["Python", "Go"]) +} + +pub fn three_item_list_with_gleam_as_first_item_is_exciting_test() { + let assert True = + tracks_on_tracks_on_tracks.exciting_list(["Gleam", "Lisp", "Clojure"]) +} + +pub fn three_item_list_with_gleam_as_second_item_is_exciting_test() { + let assert True = + tracks_on_tracks_on_tracks.exciting_list(["Java", "Gleam", "C#"]) +} + +pub fn three_item_list_with_gleam_as_third_item_is_not_exciting_test() { + let assert False = + tracks_on_tracks_on_tracks.exciting_list(["Julia", "Assembly", "Gleam"]) +} + +pub fn four_item_list_with_gleam_as_first_item_is_exciting_test() { + let assert True = + tracks_on_tracks_on_tracks.exciting_list(["Gleam", "C", "C++", "C#"]) +} + +pub fn four_item_list_with_gleam_as_second_item_is_not_exciting_test() { + let assert False = + tracks_on_tracks_on_tracks.exciting_list(["Elm", "Gleam", "C#", "Scheme"]) +} + +pub fn four_item_list_with_gleam_as_third_item_is_not_exciting_test() { + let assert False = + tracks_on_tracks_on_tracks.exciting_list(["Delphi", "D", "Gleam", "Prolog"]) +} + +pub fn four_item_list_with_gleam_as_fourth_item_is_not_exciting_test() { + let assert False = + tracks_on_tracks_on_tracks.exciting_list([ + "Julia", "Assembly", "Crystal", "Gleam", + ]) +}