From 8296c79f689407803cc53efab4360a26a0075c61 Mon Sep 17 00:00:00 2001 From: davidoji Date: Mon, 4 Aug 2025 19:44:03 +0200 Subject: [PATCH] Some solutions for the julia path --- .../.exercism/config.json | 26 ++ .../.exercism/metadata.json | 1 + julia/annalyns-infiltration/HELP.md | 34 ++ julia/annalyns-infiltration/HINTS.md | 23 ++ julia/annalyns-infiltration/README.md | 162 +++++++++ .../annalyns-infiltration.jl | 15 + julia/annalyns-infiltration/runtests.jl | 71 ++++ julia/cars-assemble/.exercism/config.json | 20 ++ julia/cars-assemble/.exercism/metadata.json | 1 + julia/cars-assemble/HELP.md | 34 ++ julia/cars-assemble/HINTS.md | 22 ++ julia/cars-assemble/README.md | 150 +++++++++ julia/cars-assemble/cars-assemble.jl | 24 ++ julia/cars-assemble/runtests.jl | 108 ++++++ julia/chessboard/.exercism/config.json | 20 ++ julia/chessboard/.exercism/metadata.json | 1 + julia/chessboard/HELP.md | 34 ++ julia/chessboard/HINTS.md | 22 ++ julia/chessboard/README.md | 149 +++++++++ julia/chessboard/chessboard.jl | 15 + julia/chessboard/runtests.jl | 31 ++ .../collatz-conjecture/.exercism/config.json | 22 ++ .../.exercism/metadata.json | 1 + julia/collatz-conjecture/HELP.md | 34 ++ julia/collatz-conjecture/README.md | 51 +++ .../collatz-conjecture/collatz-conjecture.jl | 23 ++ julia/collatz-conjecture/runtests.jl | 15 + julia/currency-exchange/.exercism/config.json | 21 ++ .../currency-exchange/.exercism/metadata.json | 1 + julia/currency-exchange/HELP.md | 34 ++ julia/currency-exchange/HINTS.md | 41 +++ julia/currency-exchange/README.md | 313 ++++++++++++++++++ julia/currency-exchange/currency-exchange.jl | 24 ++ julia/currency-exchange/runtests.jl | 41 +++ julia/darts/.exercism/config.json | 21 ++ julia/darts/.exercism/metadata.json | 1 + julia/darts/HELP.md | 34 ++ julia/darts/README.md | 50 +++ julia/darts/darts.jl | 12 + julia/darts/runtests.jl | 57 ++++ .../.exercism/config.json | 23 ++ .../.exercism/metadata.json | 1 + julia/difference-of-squares/HELP.md | 34 ++ julia/difference-of-squares/README.md | 34 ++ .../difference-of-squares.jl | 14 + julia/difference-of-squares/runtests.jl | 27 ++ julia/eliuds-eggs/.exercism/config.json | 19 ++ julia/eliuds-eggs/.exercism/metadata.json | 1 + julia/eliuds-eggs/HELP.md | 34 ++ julia/eliuds-eggs/README.md | 89 +++++ julia/eliuds-eggs/eliuds-eggs.jl | 3 + julia/eliuds-eggs/runtests.jl | 21 ++ .../elyses-enchantments/.exercism/config.json | 24 ++ .../.exercism/metadata.json | 1 + julia/elyses-enchantments/HELP.md | 34 ++ julia/elyses-enchantments/HINTS.md | 42 +++ julia/elyses-enchantments/README.md | 243 ++++++++++++++ .../elyses-enchantments.jl | 50 +++ julia/elyses-enchantments/runtests.jl | 229 +++++++++++++ julia/hello-world/.exercism/config.json | 19 ++ julia/hello-world/.exercism/metadata.json | 1 + julia/hello-world/HELP.md | 34 ++ julia/hello-world/README.md | 31 ++ julia/hello-world/hello-world.jl | 3 + julia/hello-world/runtests.jl | 9 + julia/lasagna/.exercism/config.json | 26 ++ julia/lasagna/.exercism/metadata.json | 1 + julia/lasagna/HELP.md | 34 ++ julia/lasagna/HINTS.md | 26 ++ julia/lasagna/README.md | 164 +++++++++ julia/lasagna/lasagna.jl | 14 + julia/lasagna/runtests.jl | 29 ++ julia/leap/.exercism/config.json | 23 ++ julia/leap/.exercism/metadata.json | 1 + julia/leap/HELP.md | 34 ++ julia/leap/README.md | 40 +++ julia/leap/leap.jl | 18 + julia/leap/runtests.jl | 45 +++ julia/mixed-juices/.exercism/config.json | 20 ++ julia/mixed-juices/.exercism/metadata.json | 1 + julia/mixed-juices/HELP.md | 34 ++ julia/mixed-juices/HINTS.md | 21 ++ julia/mixed-juices/README.md | 148 +++++++++ julia/mixed-juices/mixed-juices.jl | 19 ++ julia/mixed-juices/runtests.jl | 171 ++++++++++ julia/perfect-numbers/.exercism/config.json | 25 ++ julia/perfect-numbers/.exercism/metadata.json | 1 + julia/perfect-numbers/HELP.md | 34 ++ julia/perfect-numbers/README.md | 61 ++++ julia/perfect-numbers/perfect-numbers.jl | 14 + julia/perfect-numbers/runtests.jl | 88 +++++ julia/raindrops/.exercism/config.json | 23 ++ julia/raindrops/.exercism/metadata.json | 1 + julia/raindrops/HELP.md | 34 ++ julia/raindrops/README.md | 48 +++ julia/raindrops/raindrops.jl | 16 + julia/raindrops/runtests.jl | 74 +++++ julia/secrets/.exercism/config.json | 20 ++ julia/secrets/.exercism/metadata.json | 1 + julia/secrets/HELP.md | 34 ++ julia/secrets/HINTS.md | 21 ++ julia/secrets/README.md | 185 +++++++++++ julia/secrets/runtests.jl | 30 ++ julia/secrets/secrets.jl | 15 + 104 files changed, 4373 insertions(+) create mode 100644 julia/annalyns-infiltration/.exercism/config.json create mode 100644 julia/annalyns-infiltration/.exercism/metadata.json create mode 100644 julia/annalyns-infiltration/HELP.md create mode 100644 julia/annalyns-infiltration/HINTS.md create mode 100644 julia/annalyns-infiltration/README.md create mode 100644 julia/annalyns-infiltration/annalyns-infiltration.jl create mode 100644 julia/annalyns-infiltration/runtests.jl create mode 100644 julia/cars-assemble/.exercism/config.json create mode 100644 julia/cars-assemble/.exercism/metadata.json create mode 100644 julia/cars-assemble/HELP.md create mode 100644 julia/cars-assemble/HINTS.md create mode 100644 julia/cars-assemble/README.md create mode 100644 julia/cars-assemble/cars-assemble.jl create mode 100644 julia/cars-assemble/runtests.jl create mode 100644 julia/chessboard/.exercism/config.json create mode 100644 julia/chessboard/.exercism/metadata.json create mode 100644 julia/chessboard/HELP.md create mode 100644 julia/chessboard/HINTS.md create mode 100644 julia/chessboard/README.md create mode 100644 julia/chessboard/chessboard.jl create mode 100644 julia/chessboard/runtests.jl create mode 100644 julia/collatz-conjecture/.exercism/config.json create mode 100644 julia/collatz-conjecture/.exercism/metadata.json create mode 100644 julia/collatz-conjecture/HELP.md create mode 100644 julia/collatz-conjecture/README.md create mode 100644 julia/collatz-conjecture/collatz-conjecture.jl create mode 100644 julia/collatz-conjecture/runtests.jl create mode 100644 julia/currency-exchange/.exercism/config.json create mode 100644 julia/currency-exchange/.exercism/metadata.json create mode 100644 julia/currency-exchange/HELP.md create mode 100644 julia/currency-exchange/HINTS.md create mode 100644 julia/currency-exchange/README.md create mode 100644 julia/currency-exchange/currency-exchange.jl create mode 100644 julia/currency-exchange/runtests.jl create mode 100644 julia/darts/.exercism/config.json create mode 100644 julia/darts/.exercism/metadata.json create mode 100644 julia/darts/HELP.md create mode 100644 julia/darts/README.md create mode 100644 julia/darts/darts.jl create mode 100644 julia/darts/runtests.jl create mode 100644 julia/difference-of-squares/.exercism/config.json create mode 100644 julia/difference-of-squares/.exercism/metadata.json create mode 100644 julia/difference-of-squares/HELP.md create mode 100644 julia/difference-of-squares/README.md create mode 100644 julia/difference-of-squares/difference-of-squares.jl create mode 100644 julia/difference-of-squares/runtests.jl create mode 100644 julia/eliuds-eggs/.exercism/config.json create mode 100644 julia/eliuds-eggs/.exercism/metadata.json create mode 100644 julia/eliuds-eggs/HELP.md create mode 100644 julia/eliuds-eggs/README.md create mode 100644 julia/eliuds-eggs/eliuds-eggs.jl create mode 100644 julia/eliuds-eggs/runtests.jl create mode 100644 julia/elyses-enchantments/.exercism/config.json create mode 100644 julia/elyses-enchantments/.exercism/metadata.json create mode 100644 julia/elyses-enchantments/HELP.md create mode 100644 julia/elyses-enchantments/HINTS.md create mode 100644 julia/elyses-enchantments/README.md create mode 100644 julia/elyses-enchantments/elyses-enchantments.jl create mode 100644 julia/elyses-enchantments/runtests.jl create mode 100644 julia/hello-world/.exercism/config.json create mode 100644 julia/hello-world/.exercism/metadata.json create mode 100644 julia/hello-world/HELP.md create mode 100644 julia/hello-world/README.md create mode 100644 julia/hello-world/hello-world.jl create mode 100644 julia/hello-world/runtests.jl create mode 100644 julia/lasagna/.exercism/config.json create mode 100644 julia/lasagna/.exercism/metadata.json create mode 100644 julia/lasagna/HELP.md create mode 100644 julia/lasagna/HINTS.md create mode 100644 julia/lasagna/README.md create mode 100644 julia/lasagna/lasagna.jl create mode 100644 julia/lasagna/runtests.jl create mode 100644 julia/leap/.exercism/config.json create mode 100644 julia/leap/.exercism/metadata.json create mode 100644 julia/leap/HELP.md create mode 100644 julia/leap/README.md create mode 100644 julia/leap/leap.jl create mode 100644 julia/leap/runtests.jl create mode 100644 julia/mixed-juices/.exercism/config.json create mode 100644 julia/mixed-juices/.exercism/metadata.json create mode 100644 julia/mixed-juices/HELP.md create mode 100644 julia/mixed-juices/HINTS.md create mode 100644 julia/mixed-juices/README.md create mode 100644 julia/mixed-juices/mixed-juices.jl create mode 100644 julia/mixed-juices/runtests.jl create mode 100644 julia/perfect-numbers/.exercism/config.json create mode 100644 julia/perfect-numbers/.exercism/metadata.json create mode 100644 julia/perfect-numbers/HELP.md create mode 100644 julia/perfect-numbers/README.md create mode 100644 julia/perfect-numbers/perfect-numbers.jl create mode 100644 julia/perfect-numbers/runtests.jl create mode 100644 julia/raindrops/.exercism/config.json create mode 100644 julia/raindrops/.exercism/metadata.json create mode 100644 julia/raindrops/HELP.md create mode 100644 julia/raindrops/README.md create mode 100644 julia/raindrops/raindrops.jl create mode 100644 julia/raindrops/runtests.jl create mode 100644 julia/secrets/.exercism/config.json create mode 100644 julia/secrets/.exercism/metadata.json create mode 100644 julia/secrets/HELP.md create mode 100644 julia/secrets/HINTS.md create mode 100644 julia/secrets/README.md create mode 100644 julia/secrets/runtests.jl create mode 100644 julia/secrets/secrets.jl diff --git a/julia/annalyns-infiltration/.exercism/config.json b/julia/annalyns-infiltration/.exercism/config.json new file mode 100644 index 0000000..4328e88 --- /dev/null +++ b/julia/annalyns-infiltration/.exercism/config.json @@ -0,0 +1,26 @@ +{ + "authors": [ + "SaschaMann", + "colinleach" + ], + "contributors": [ + "cmcaine", + "BNAndras" + ], + "files": { + "solution": [ + "annalyns-infiltration.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "language_versions": "≥1.0", + "forked_from": [ + "javascript/annalyns-infiltration" + ], + "blurb": "Learn about boolean expressions by implementing the quest logic for a new RPG." +} diff --git a/julia/annalyns-infiltration/.exercism/metadata.json b/julia/annalyns-infiltration/.exercism/metadata.json new file mode 100644 index 0000000..d500cab --- /dev/null +++ b/julia/annalyns-infiltration/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"annalyns-infiltration","id":"30cf911b357741e8a7c62eb77cf57308","url":"https://exercism.org/tracks/julia/exercises/annalyns-infiltration","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/annalyns-infiltration/HELP.md b/julia/annalyns-infiltration/HELP.md new file mode 100644 index 0000000..b426e03 --- /dev/null +++ b/julia/annalyns-infiltration/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit annalyns-infiltration.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/annalyns-infiltration/HINTS.md b/julia/annalyns-infiltration/HINTS.md new file mode 100644 index 0000000..9f227a5 --- /dev/null +++ b/julia/annalyns-infiltration/HINTS.md @@ -0,0 +1,23 @@ +# Hints + +## General + +- There are three [boolean operators][boolean-operators] to work with boolean values. +- Multiple operators can be combined in a single expression. + +## 1. Check if a fast attack can be made + +- The logical NOT operator (`!`) can be placed before an expression to negate its value. + +## 2. Check if the group can be spied upon + +- Boolean operators are typically used to evaluate whether two or more expressions are true or not true. + +## 3. Check if the prisoner can be signaled + +- Boolean operators execute in the order of their precedence (from highest to lowest): `!`, `&&`, `||`. +- In general, use of parentheses is encouraged to make your intention clearer. +- For more details check out the Operator Precedence section on the [official Julia documentation][operator-precedence]. + +[boolean-operators]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Boolean-Operators +[operator-precedence]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity \ No newline at end of file diff --git a/julia/annalyns-infiltration/README.md b/julia/annalyns-infiltration/README.md new file mode 100644 index 0000000..ffef4ec --- /dev/null +++ b/julia/annalyns-infiltration/README.md @@ -0,0 +1,162 @@ +# Annalyns Infiltration + +Welcome to Annalyns Infiltration on Exercism's Julia 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 + +## Booleans in Julia + +True or false values are represented by the `Bool` type. +It contains only two values: `true` and `false`. + +```julia-repl +julia> true +true + +julia> false +false +``` + +## Boolean Operators + +There are three Boolean operators in Julia. + +`&&` is Boolean "and". +It evaluates to `true` if the expressions on *both* sides of `&&` are `true`. + +```julia-repl +julia> true && true +true + +julia> true && false +false +``` + +`||` is Boolean "or". +It evaluates to `true` if an expression on *either* side of `||` is `true`. + +```julia-repl +julia> true || true +true + +julia> false || true +true +``` + +`!` is Boolean "not". +It exchanges `true` and `false` values. + +```julia-repl +julia> !true +false + +julia> !false +true +``` + +For longer and more complicated expressions, it is best to use parentheses to make your intention clear. + +```julia-repl +julia> (true || false) && (false && true) +false +``` + +## Instructions + +In this exercise, you'll be writing some logic for a video game a friend is developing. +The game's main character is Annalyn, a brave girl with a fierce and loyal pet dog. +Unfortunately, disaster strikes, as her best friend is kidnapped while searching for berries in the forest. +Annalyn will try to find and free her friend, optionally taking her dog with her on this quest. + +Annalyn eventually finds the camp in which her friend is imprisoned and it turns out there are two kidnappers: a mighty knight and a cunning archer. + +The player is presented with some options for what to do next. +For each of the four possible options you need to write a function that tells the game whether it should show that option or not. + +## 1. Check if the 'Fast Attack' option should be shown + +If the knight is sleeping, then Annalyn will be able to make a quick attack into the camp before he can wake up properly and get his armour on. + +Implement a function named `can_do_fast_attack` that takes a boolean value which indicates if the knight is awake. +This function returns `true` if the 'Fast Attack' action is available based on the state of the character. Otherwise, returns `false`: + +```julia-repl +julia> knight_awake = true + +julia> can_do_fast_attack(knight_awake) +false +``` + +## 2. Check if the 'Spy' option should be shown + +The group can be spied upon if at least one of them is awake. Otherwise, spying is a waste of time. + +Implement a function named `can_spy` that takes three boolean values, indicating if the knight, archer and prisoner, respectively, are awake. +The function returns `true` if the 'Spy' action is available based on the state of the characters. +Otherwise, returns `false`: + +```julia-repl +# Output suppressed from the next 3 lines +julia> knight_awake = false +julia> archer_awake = true +julia> prisoner_awake = false + +julia> can_spy(knight_awake, archer_awake, prisoner_awake) +true +``` + +## 3. Check if the 'Signal Prisoner' option should be shown + +The prisoner can be signalled using bird sounds if she is awake and the archer is sleeping. +If the archer is awake then she can't be safely signaled because the archer is also trained in bird signalling. + +Implement a function named `can_signal_prisoner` that takes two boolean values, indicating if the archer and prisoner, respectively, are awake. +The function returns `true` if the 'Signal Prisoner' action is available based on the state of the characters. +Otherwise, returns `false`: + +```julia-repl +julia> archer_awake = false +julia> prisoner_awake = true + +julia> can_signal_prisoner(archer_awake, prisoner_awake) +true +``` + +## 4. Check if the 'Free Prisoner' option should be shown + +Annalyn can try sneaking into the camp to free her friend. This is a risky thing to do and can only succeed in one of two ways: + +- If Annalyn has her pet dog with her, she can rescue the prisoner if the archer is asleep. + The knight is scared of the dog and the archer will not have time to get ready before Annalyn and her friend can escape. + +- If Annalyn does not have her dog then she and the prisoner must be very sneaky! + Annalyn can free the prisoner if she is awake and the knight and archer are both sleeping, but if the prisoner is sleeping, she can't be rescued: she would be startled by Annalyn's sudden appearance and wake up the knight and archer. + +Implement a function named `can_free_prisoner` that takes four boolean values. +The first three parameters indicate if the knight, archer and prisoner, respectively, are awake. +The last parameter indicates if Annalyn's pet dog is present. +The function returns `true` if the 'Free Prisoner' action is available based on the state of the characters. Otherwise, it returns `false`: + +```julia-repl +julia> knight_awake = false +julia> archer_awake = true +julia> prisoner_awake = false +julia> dog_present = false + +julia> can_free_prisoner(knight_awake, archer_awake, prisoner_awake, dog_present) +false +``` + +## Source + +### Created by + +- @SaschaMann +- @colinleach + +### Contributed to by + +- @cmcaine +- @BNAndras \ No newline at end of file diff --git a/julia/annalyns-infiltration/annalyns-infiltration.jl b/julia/annalyns-infiltration/annalyns-infiltration.jl new file mode 100644 index 0000000..b235494 --- /dev/null +++ b/julia/annalyns-infiltration/annalyns-infiltration.jl @@ -0,0 +1,15 @@ +function can_do_fast_attack(knight_awake) + return !knight_awake +end + +function can_spy(knight_awake, archer_awake, prisoner_awake) + return (knight_awake || archer_awake || prisoner_awake) +end + +function can_signal_prisoner(archer_awake, prisoner_awake) + return !archer_awake && prisoner_awake +end + +function can_free_prisoner(knight_awake, archer_awake, prisoner_awake, dog_present) + return (dog_present && !archer_awake) || (!dog_present && prisoner_awake && !knight_awake && !archer_awake) +end diff --git a/julia/annalyns-infiltration/runtests.jl b/julia/annalyns-infiltration/runtests.jl new file mode 100644 index 0000000..1d9ea95 --- /dev/null +++ b/julia/annalyns-infiltration/runtests.jl @@ -0,0 +1,71 @@ +using Test + +include("annalyns-infiltration.jl") + +# Julia 1.0 compat +# The function definition of eachrow is taken from Julia Base, +# released under the MIT license: https://julialang.org/license +if VERSION < v"1.1" + @eval eachrow(A) = (view(A, i, :) for i in axes(A, 1)) +end + +@testset verbose = true "tests" begin + @testset "fast attack" begin + @test !can_do_fast_attack(true) + @test can_do_fast_attack(false) + end + + @testset "spying" begin + character_state_combinations = Bool[ + 0 0 0 0; + 0 0 1 1; + 0 1 0 1; + 0 1 1 1; + 1 0 0 1; + 1 0 1 1; + 1 1 1 1; + ] + + for state in eachrow(character_state_combinations) + @test can_spy(state[1:3]...) == state[4] + end + end + + @testset "signaling prisoner" begin + character_state_combinations = Bool[ + 0 0 0; + 0 1 1; + 1 0 0; + 1 1 0; + ] + + for state in eachrow(character_state_combinations) + @test can_signal_prisoner(state[1:2]...) == state[3] + end + end + + @testset "freeing prisoner" begin + character_state_combinations = Bool[ + 0 0 0 0 0; + 0 0 0 1 1; + 0 0 1 0 1; + 0 0 1 1 1; + 0 1 0 0 0; + 0 1 0 1 0; + 0 1 1 0 0; + 0 1 1 1 0; + 1 0 0 0 0; + 1 0 0 1 1; + 1 0 1 0 0; + 1 0 1 1 1; + 1 1 0 0 0; + 1 1 0 1 0; + 1 1 1 0 0; + 1 1 1 1 0; + ] + + for state in eachrow(character_state_combinations) + @test can_free_prisoner(state[1:4]...) == state[5] + end + end +end diff --git a/julia/cars-assemble/.exercism/config.json b/julia/cars-assemble/.exercism/config.json new file mode 100644 index 0000000..b644616 --- /dev/null +++ b/julia/cars-assemble/.exercism/config.json @@ -0,0 +1,20 @@ +{ + "authors": [ + "colinleach" + ], + "files": { + "solution": [ + "cars-assemble.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "forked_from": [ + "csharp/cars-assemble" + ], + "blurb": "Learn about conditionals by analyzing the production of an assembly line." +} diff --git a/julia/cars-assemble/.exercism/metadata.json b/julia/cars-assemble/.exercism/metadata.json new file mode 100644 index 0000000..0cd62a9 --- /dev/null +++ b/julia/cars-assemble/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"cars-assemble","id":"45c3c88693d84b2d88daec48b8f45391","url":"https://exercism.org/tracks/julia/exercises/cars-assemble","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/cars-assemble/HELP.md b/julia/cars-assemble/HELP.md new file mode 100644 index 0000000..8e7c110 --- /dev/null +++ b/julia/cars-assemble/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit cars-assemble.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/cars-assemble/HINTS.md b/julia/cars-assemble/HINTS.md new file mode 100644 index 0000000..4a683f6 --- /dev/null +++ b/julia/cars-assemble/HINTS.md @@ -0,0 +1,22 @@ +# Hints + +## 1. Calculate the success rate + +- You need to translate the speed into a success rate, using the rules given in the instructions. +- The returned value is a floating-point number. +- Julia does not have the `select`/`case` syntax present in some other languages, but the Introduction discussed `if-else` syntax. + +## 2. Calculate the production rate per hour + +- The total theoretical production rate depends on the base production rate (a constant) and the speed. +- Return the actual production rate, which also depends on the success rate. + +## 3. Calculate the number of working items produced per minute + +- The hourly production rate was calculated in task 2. +- This task requires the rate per minute. +- Only complete, working cars are counted in this exercise, so you will need to remove part-complete cars from the count. +- The return value must be an integer (for example `7`, not `7.0`). +- The [Numbers][numbers] Concept already discussed ways to round values. + +[numbers]: https://exercism.org/tracks/julia/concepts/numbers \ No newline at end of file diff --git a/julia/cars-assemble/README.md b/julia/cars-assemble/README.md new file mode 100644 index 0000000..6af18fe --- /dev/null +++ b/julia/cars-assemble/README.md @@ -0,0 +1,150 @@ +# Cars Assemble + +Welcome to Cars Assemble on Exercism's Julia 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 + +## Comparison operators + +Comparison operators in Julia are similar to many other languages, though with some extra options for math-lovers. + +For equality, the operators are `==` (equal) and `!=` or `≠` (not equal). + +```julia +txt = "abc" +txt == "abc" # true +txt != "abc" # false +txt ≠ "abc" # false (synonym for !=) +``` + +In addition, we have the various greater/less than operators. + +```julia +1 < 3 # true +3 > 3 # false +3 <= 3 # true +3 ≤ 3 # true (synonym for <=) +4 >= 3 # true +4 ≥ 3 # true (synonym for >=) +``` + +As often with Julia, an appropriate editor makes use of the mathematical symbol easy. +Type `\ne`, `\le` or `\ge` then `TAB` to get `≠`, `≤` or `≥`. + +The previous example uses only numbers, but we will see in other parts of the syllabus that various additional types have a sense of ordering and can be tested for greater/less than. + +Comparison operators can be chained, which allows a clear and concise syntax: + +```julia +n = 3 +1 ≤ n ≤ 5 # true (n "between" two limits) +``` + +The previous example is a synonym for `1 ≤ n && n ≤ 5`. + +## Branching with `if` + +This is the full form of an `if` statement: + +```julia +if conditional1 + statements... +elseif conditional2 + statements... +else + statements... +end +``` + +There is no need for parentheses `()` or braces `{}`, and indentation is "only" to improve readability _(but readability is very important!)_. + +Both `elseif` and `else` are optional, and there can be multiple `elseif` blocks. +However, the `end` is required. + +It is possible to nest `if` statements, though you might want to help readability with the thoughtful use of parentheses, indents and comments. + +The shortest form of an `if` statement would be something like this: + +```julia +if n < 0 + n = 0 +end +``` + +As a reminder: only expressions that evaluate to `true` or `false` can be used as conditionals. +Julia deliberately avoids any concept of "truthiness", so zero values, empty strings and empty arrays are _not_ equivalent to `false`. + +## Ternary operator + +A simple and common situation is picking one of two values based on a conditional. + +Julia, like many languages, has a ternary operator to make this more concise. + +The syntax is `conditional ? value_if_true : value_if_false`. + +So the previous example could be rewritten: + +```julia +n = n < 0 ? 0 : n +``` + +Parentheses are not required by the compiler, but may improve readability. + +## Instructions + +In this exercise you will be writing code to analyze the production of an assembly line in a car factory. +The assembly line's speed can range from `0` (off) to `10` (maximum). + +At its lowest speed (`1`), `221` cars are produced each hour. +The production increases linearly with the speed. +So with the speed set to `4`, it should produce `4 * 221 = 884` cars per hour. +However, higher speeds increase the likelihood that faulty cars are produced, which then have to be discarded. + +You have three tasks. +Each of the required functions takes a single integer parameter, the speed of the assembly line. + +## 1. Calculate the success rate + +Implement the `success_rate()` method to calculate the probability of an item being created without error for a given speed. +The following table shows how speed influences the success rate: + +- `0`: 0% success rate. +- `1` to `4`: 100% success rate. +- `5` to `8`: 90% success rate. +- `9`: 80% success rate. +- `10`: 77% success rate. + +```julia-repl +julia> success_rate(10) +0.77 +``` + +## 2. Calculate the production rate per hour + +Implement the `production_rate_per_hour()` method to calculate the assembly line's production rate per hour, taking into account its success rate. + +```julia-repl +julia> production_rate_per_hour(6) +1193.4 +``` + +Note that the value returned is floating-point. + +## 3. Calculate the number of working items produced per minute + +Implement the `working_items_per_minute()` method to calculate how many working cars are produced per minute: + +```julia-repl +julia> working_items_per_minute(6) +19 +``` + +Note that the value returned is an integer: incomplete items are not included. + +## Source + +### Created by + +- @colinleach \ No newline at end of file diff --git a/julia/cars-assemble/cars-assemble.jl b/julia/cars-assemble/cars-assemble.jl new file mode 100644 index 0000000..b734706 --- /dev/null +++ b/julia/cars-assemble/cars-assemble.jl @@ -0,0 +1,24 @@ +CARS_PER_HOUR = 221 + +function success_rate(speed) + if speed == 0 + success = 0 + elseif 1 ≤ speed ≤ 4 + success = 100 + elseif 5 ≤ speed ≤ 8 + success = 90 + elseif speed == 9 + success = 80 + elseif speed == 10 + success = 77 + end + return success / 100 +end + +function production_rate_per_hour(speed) + return CARS_PER_HOUR * speed * success_rate(speed) +end + +function working_items_per_minute(speed) + return Int(production_rate_per_hour(speed) ÷ 60) +end \ No newline at end of file diff --git a/julia/cars-assemble/runtests.jl b/julia/cars-assemble/runtests.jl new file mode 100644 index 0000000..d1abd3f --- /dev/null +++ b/julia/cars-assemble/runtests.jl @@ -0,0 +1,108 @@ +using Test + +include("cars-assemble.jl") + +@testset verbose = true "tests" begin + + @testset "success_rate" begin + @testset "Success rate for speed zero" begin + speed = 0 + @test isapprox(success_rate(speed), 0.0, atol=1e-3) + end + + @testset "Success rate for speed one" begin + speed = 1 + @test isapprox(success_rate(speed), 1.0, atol=1e-3) + end + + @testset "Success rate for speed four" begin + speed = 4 + @test isapprox(success_rate(speed), 1.0, atol=1e-3) + end + + @testset "Success rate for speed five" begin + speed = 5 + @test isapprox(success_rate(speed), 0.9, atol=1e-3) + end + + @testset "Success rate for speed nine" begin + speed = 9 + @test isapprox(success_rate(speed), 0.8, atol=1e-3) + end + + @testset "Success rate for speed ten" begin + speed = 10 + @test isapprox(success_rate(speed), 0.77, atol=1e-3) + end + end + + @testset "production_rate_per_hour" begin + @testset "Production rate per hour for speed zero" begin + speed = 0 + @test isapprox(production_rate_per_hour(speed), 0.0, atol=1e-3) + end + + @testset "Production rate per hour for speed one" begin + speed = 1 + @test isapprox(production_rate_per_hour(speed), 221.0, atol=1e-3) + end + + @testset "Production rate per hour for speed four" begin + speed = 4 + @test isapprox(production_rate_per_hour(speed), 884.0, atol=1e-3) + end + + @testset "Production rate per hour for speed seven" begin + speed = 7 + @test isapprox(production_rate_per_hour(speed), 1392.3, atol=1e-3) + end + + @testset "Production rate per hour for speed nine" begin + speed = 9 + @test isapprox(production_rate_per_hour(speed), 1591.2, atol=1e-3) + end + + @testset "Production rate per hour for speed ten" begin + speed = 10 + @test isapprox(production_rate_per_hour(speed), 1701.7, atol=1e-3) + end + end + + @testset "working_items_per_minute" begin + @testset "Working items per minute for speed zero" begin + speed = 0 + @test typeof(working_items_per_minute(speed)) == Int + @test working_items_per_minute(speed) == 0 + end + + @testset "Working items per minute for speed one" begin + speed = 1 + @test typeof(working_items_per_minute(speed)) == Int + @test working_items_per_minute(speed) == 3 + end + + @testset "Working items per minute for speed five" begin + speed = 5 + @test typeof(working_items_per_minute(speed)) == Int + @test working_items_per_minute(speed) == 16 + end + + @testset "Working items per minute for speed eight" begin + speed = 8 + @test typeof(working_items_per_minute(speed)) == Int + @test working_items_per_minute(speed) == 26 + end + + @testset "Working items per minute for speed nine" begin + speed = 9 + @test typeof(working_items_per_minute(speed)) == Int + @test working_items_per_minute(speed) == 26 + end + + @testset "Working items per minute for speed ten" begin + speed = 10 + @test typeof(working_items_per_minute(speed)) == Int + @test working_items_per_minute(speed) == 28 + end + end +end diff --git a/julia/chessboard/.exercism/config.json b/julia/chessboard/.exercism/config.json new file mode 100644 index 0000000..81a1222 --- /dev/null +++ b/julia/chessboard/.exercism/config.json @@ -0,0 +1,20 @@ +{ + "authors": [ + "colinleach" + ], + "files": { + "solution": [ + "chessboard.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "forked_from": [ + "elixir/chessboard" + ], + "blurb": "Learn about ranges by building a chessboard." +} diff --git a/julia/chessboard/.exercism/metadata.json b/julia/chessboard/.exercism/metadata.json new file mode 100644 index 0000000..fa3c72d --- /dev/null +++ b/julia/chessboard/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"chessboard","id":"dc930c6af16b45df91a8634905880861","url":"https://exercism.org/tracks/julia/exercises/chessboard","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/chessboard/HELP.md b/julia/chessboard/HELP.md new file mode 100644 index 0000000..4b44a2c --- /dev/null +++ b/julia/chessboard/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit chessboard.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/chessboard/HINTS.md b/julia/chessboard/HINTS.md new file mode 100644 index 0000000..ae64208 --- /dev/null +++ b/julia/chessboard/HINTS.md @@ -0,0 +1,22 @@ +# Hints + +This is a short and simple exercise, so it is best to avoid complicating it. + +## 1. Define the rank range + +- You need to return a range of integers + +## 2. Define the file range + +- You need to return a range of uppercase characters. +- Characters use single-quotes, such as `'W'`, + +## 3. Transform the rank range into a list of ranks + +- The [`collect()`][collect] function is your friend here. + +## 4. Transform the file range into a list of files + +- See task 3. + +[collect]: https://docs.julialang.org/en/v1/base/collections/#Base.collect-Tuple{Any} \ No newline at end of file diff --git a/julia/chessboard/README.md b/julia/chessboard/README.md new file mode 100644 index 0000000..d9f5a9a --- /dev/null +++ b/julia/chessboard/README.md @@ -0,0 +1,149 @@ +# Chessboard + +Welcome to Chessboard on Exercism's Julia 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 + +Suppose you want all the non-negative integers up to 1000. +It would be ridiculous if you had to type these into an array. + +For this we have the `range` type: + +```julia-repl +julia> 0:1000 +0:1000 + +julia> typeof(0:1000) +UnitRange{Int64} +``` + +Ranges are very common: not just to save you typing, but also as return types from functions. + +Note that ranges are _not_ vectors. +They are just a set of instructions to generate a sequence ("lazy" evaluation, or an "iterator"). + +If you need a range as a vector, use the `collect()` function for conversion: + +```julia-repl +julia> collect(0:5) +6-element Vector{Int64}: + 0 + 1 + 2 + 3 + 4 + 5 +``` + +The step size can be specified, in this case 0.3: + +```julia-repl +julia> collect(1.0:0.3:2.0) +4-element Vector{Float64}: + 1.0 + 1.3 + 1.6 + 1.9 +``` + +So the syntax is `start:stepsize:stop`. +Both end limits are _inclusive_, as seen in the integer example. +If the step size does not divide exactly into `stop - start`, the last element will avoid exceeding `stop`. + +## Letter ranges + +Non-numeric sequences can also be used in ranges. +The simplest example is ASCII letters: + +```julia-repl +julia> 'a':'d' +'a':1:'d' + +julia> typeof('a':'d') +StepRange{Char, Int64} + +julia> collect('a':'d') +4-element Vector{Char}: + 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) + 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase) + 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase) + 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase) +``` + +The `Char` type will be covered in more detail in another Concept. +For now, just treat these as single characters in single-quotes. + +## Functions and operators for ranges + +Check the limits of a range with `first()` and `last()`. + +```julia + r = 1:10 # => 1:10 + first(r) # => 1 + last(r) # => 10 +``` + +## More on vector indexing + +Integer ranges and vectors can be used in vector indexing: + +```julia +nums = collect(10.0:50.0) +nums[3:2:7] # gives [12.0, 14.0, 16.0] +nums[ [3, 5, 7] ] # also gives [12.0, 14.0, 16.0] +``` + +## Instructions + +As a chess enthusiast, you would like to write your own version of the game. Yes, there maybe plenty of implementations of chess available online already, but yours will be unique! + +But before you can let your imagination run wild, you need to take care of the basics. Let's start by generating the board. + +Each square of the chessboard is identified by a letter-number pair. The vertical columns of squares, called files, are labeled A through H. The horizontal rows of squares, called ranks, are numbered 1 to 8. + +## 1. Define the rank range + +Implement the `rank_range()` function. It should return a range of integers, from 1 to 8. + +```julia-repl +julia> rank_range() +# output omitted +``` + +## 2. Define the file range + +Implement the `file_range()` function. +It should return a range of integers, from the uppercase letter A, to the uppercase letter H. + +```julia-repl +julia> file_range() +# output omitted +``` + +## 3. Transform the rank range into a vector of ranks + +Implement the `ranks()` function. It should return a vector of integers, from 1 to 8. +Do not write the vector by hand, generate it from the range returned by the `rank_range()` function. + +```julia-repl +julia> ranks() +[1, 2, 3, 4, 5, 6, 7, 8] +``` + +## 4. Transform the file range into a vector of files + +Implement the `files` function. It should return a vector of characters, from 'A' to 'H'. +Do not write the vector by hand, generate it from the range returned by the `file_range()` function. + +```julia-repl +julia> files() +['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] +``` + +## Source + +### Created by + +- @colinleach \ No newline at end of file diff --git a/julia/chessboard/chessboard.jl b/julia/chessboard/chessboard.jl new file mode 100644 index 0000000..c2f69e8 --- /dev/null +++ b/julia/chessboard/chessboard.jl @@ -0,0 +1,15 @@ +function rank_range() + return 1:8 +end + +function file_range() + return 'A':'H' +end + +function ranks() + return collect(rank_range()) +end + +function files() + return collect(file_range()) +end diff --git a/julia/chessboard/runtests.jl b/julia/chessboard/runtests.jl new file mode 100644 index 0000000..71cc58e --- /dev/null +++ b/julia/chessboard/runtests.jl @@ -0,0 +1,31 @@ +using Test + +include("chessboard.jl") + +@testset verbose = true "tests" begin + + @testset "rank_range is a range from 1 to 8" begin + result = rank_range() + @test first(result) == 1 + @test last(result) == 8 + @test length(result) == 8 + @test typeof(result) == UnitRange{Int} + end + + @testset "file_range is a range from 'A' to 'H'" begin + result = file_range() + @test first(result) == 'A' + @test last(result) == 'H' + @test length(result) == 8 + @test typeof(result) == StepRange{Char, Int} + end + + @testset "ranks is a vector of integers from 1 to 8" begin + @test ranks() == [1, 2, 3, 4, 5, 6, 7, 8] + end + + @testset "files is a vector of characters from 'A' to 'H'" begin + @test ranks() == [1, 2, 3, 4, 5, 6, 7, 8] + end + +end diff --git a/julia/collatz-conjecture/.exercism/config.json b/julia/collatz-conjecture/.exercism/config.json new file mode 100644 index 0000000..2176674 --- /dev/null +++ b/julia/collatz-conjecture/.exercism/config.json @@ -0,0 +1,22 @@ +{ + "authors": [ + "SaschaMann" + ], + "contributors": [ + "guilhermebodin" + ], + "files": { + "solution": [ + "collatz-conjecture.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Calculate the number of steps to reach 1 using the Collatz conjecture.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Collatz_conjecture" +} diff --git a/julia/collatz-conjecture/.exercism/metadata.json b/julia/collatz-conjecture/.exercism/metadata.json new file mode 100644 index 0000000..59114de --- /dev/null +++ b/julia/collatz-conjecture/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"collatz-conjecture","id":"3beda5faa27740749db53e30351afca0","url":"https://exercism.org/tracks/julia/exercises/collatz-conjecture","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/collatz-conjecture/HELP.md b/julia/collatz-conjecture/HELP.md new file mode 100644 index 0000000..1a7f91b --- /dev/null +++ b/julia/collatz-conjecture/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit collatz-conjecture.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/collatz-conjecture/README.md b/julia/collatz-conjecture/README.md new file mode 100644 index 0000000..cc9e822 --- /dev/null +++ b/julia/collatz-conjecture/README.md @@ -0,0 +1,51 @@ +# Collatz Conjecture + +Welcome to Collatz Conjecture on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Introduction + +One evening, you stumbled upon an old notebook filled with cryptic scribbles, as though someone had been obsessively chasing an idea. +On one page, a single question stood out: **Can every number find its way to 1?** +It was tied to something called the **Collatz Conjecture**, a puzzle that has baffled thinkers for decades. + +The rules were deceptively simple. +Pick any positive integer. + +- If it's even, divide it by 2. +- If it's odd, multiply it by 3 and add 1. + +Then, repeat these steps with the result, continuing indefinitely. + +Curious, you picked number 12 to test and began the journey: + +12 ➜ 6 ➜ 3 ➜ 10 ➜ 5 ➜ 16 ➜ 8 ➜ 4 ➜ 2 ➜ 1 + +Counting from the second number (6), it took 9 steps to reach 1, and each time the rules repeated, the number kept changing. +At first, the sequence seemed unpredictable — jumping up, down, and all over. +Yet, the conjecture claims that no matter the starting number, we'll always end at 1. + +It was fascinating, but also puzzling. +Why does this always seem to work? +Could there be a number where the process breaks down, looping forever or escaping into infinity? +The notebook suggested solving this could reveal something profound — and with it, fame, [fortune][collatz-prize], and a place in history awaits whoever could unlock its secrets. + +[collatz-prize]: https://mathprize.net/posts/collatz-conjecture/ + +## Instructions + +Given a positive integer, return the number of steps it takes to reach 1 according to the rules of the Collatz Conjecture. + +## Source + +### Created by + +- @SaschaMann + +### Contributed to by + +- @guilhermebodin + +### Based on + +Wikipedia - https://en.wikipedia.org/wiki/Collatz_conjecture \ No newline at end of file diff --git a/julia/collatz-conjecture/collatz-conjecture.jl b/julia/collatz-conjecture/collatz-conjecture.jl new file mode 100644 index 0000000..01dd7b8 --- /dev/null +++ b/julia/collatz-conjecture/collatz-conjecture.jl @@ -0,0 +1,23 @@ +function is_even(n::Int) + return n % 2 == 0 +end + +function is_odd(n::Int) + return n % 2 != 0 +end + +function collatz_steps(n::Int) + if n <= 0 + throw(DomainError("Input must be a positive integer.")) + end + steps = 0 + while n != 1 + if is_even(n) + n ÷= 2 + else + n = 3 * n + 1 + end + steps += 1 + end + return steps +end \ No newline at end of file diff --git a/julia/collatz-conjecture/runtests.jl b/julia/collatz-conjecture/runtests.jl new file mode 100644 index 0000000..c7b05f1 --- /dev/null +++ b/julia/collatz-conjecture/runtests.jl @@ -0,0 +1,15 @@ +using Test + +include("collatz-conjecture.jl") + +@testset verbose = true "tests" begin + # canonical data + @testset "Canonical data" begin + @test collatz_steps(1) == 0 + @test collatz_steps(16) == 4 + @test collatz_steps(12) == 9 + @test collatz_steps(1000000) == 152 + @test_throws DomainError collatz_steps(0) + @test_throws DomainError collatz_steps(-15) + end +end diff --git a/julia/currency-exchange/.exercism/config.json b/julia/currency-exchange/.exercism/config.json new file mode 100644 index 0000000..cddbf54 --- /dev/null +++ b/julia/currency-exchange/.exercism/config.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "colinleach" + ], + "files": { + "solution": [ + "currency-exchange.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "forked_from": [ + "python/currency-exchange" + ], + "icon": "hyperia-forex", + "blurb": "Learn about numbers by solving Chandler's currency exchange conundrums." +} diff --git a/julia/currency-exchange/.exercism/metadata.json b/julia/currency-exchange/.exercism/metadata.json new file mode 100644 index 0000000..937fd12 --- /dev/null +++ b/julia/currency-exchange/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"currency-exchange","id":"57c3aae34f93402a953b2840e9fbe904","url":"https://exercism.org/tracks/julia/exercises/currency-exchange","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/currency-exchange/HELP.md b/julia/currency-exchange/HELP.md new file mode 100644 index 0000000..909e284 --- /dev/null +++ b/julia/currency-exchange/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit currency-exchange.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/currency-exchange/HINTS.md b/julia/currency-exchange/HINTS.md new file mode 100644 index 0000000..05d5620 --- /dev/null +++ b/julia/currency-exchange/HINTS.md @@ -0,0 +1,41 @@ +# Hints + +## General + +## 1. Estimate value after exchange + +- You can use the [division operator][division-operator] to get the value of exchanged currency. + +## 2. Calculate currency left after an exchange + +- You can use the [subtraction operator][subtraction-operator] to get the amount of change. + +## 3. Calculate value of bills + +- You can use the [multiplication operator][multiplication-operator] to get the value of bills. + +## 4. Calculate number of bills + +- You need to divide `amount` into `denomination`. +- To remove decimal places from a floating point value, you can use the [`floor()`][floor] function. +- You need an integer to get the exact number of bills. + The `floor` function can take the desired output type as a parameter. + + **Note:** The [`÷` operator][div], or `div()` function, also does floor division. However, if an operand is floating point the result is still floating point. + +## 5. Calculate leftover after exchanging into bills + +- You need to find the remainder of `amount` that does not equal a whole `denomination`. +- The [Modulo operator][div] `%` can help find the remainder. + +## 6. Calculate value after exchange + +- You need to calculate `spread` percent of `exchange_rate` using multiplication operator and add it to `exchange_rate` to get the exchanged currency. +- The actual rate needs to be computed. Remember to add exchange _rate_ and exchange _fee_. +- You can get exchanged money affected by commission by using a divide operation, plus type casting to integer if necessary. + +[division-operator]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Arithmetic-Operators +[multiplication-operator]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Arithmetic-Operators#Arithmetic-Operators +[subtraction-operator]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Arithmetic-Operators +[floor]: https://docs.julialang.org/en/v1/base/math/#Base.floor +[div]: https://benlauwens.github.io/ThinkJulia.jl/latest/book.html#_floor_division_and_modulus \ No newline at end of file diff --git a/julia/currency-exchange/README.md b/julia/currency-exchange/README.md new file mode 100644 index 0000000..5d2a16a --- /dev/null +++ b/julia/currency-exchange/README.md @@ -0,0 +1,313 @@ +# Currency Exchange + +Welcome to Currency Exchange on Exercism's Julia 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 + +Julia is a general-purpose language that can be used for most programming tasks. +In practice, however, the main use cases tend to be in engineering and science. +Fast, versatile, sophisticated numerical calculations are central to the design. + +## Integers + +An integer is a "round" number with no decimal point. + +In the [Basics][basics] concept, we saw that an integer value can be assigned to a variable without specifying a type. + +For readability, underscores can be used as a digit separator. +They are ignored by the compiler. + +```julia-repl +julia> x = 3 +3 + +julia> typeof(x) +Int64 + +julia> large_number = 1_234_567_890 +1234567890 +``` + + +## Floating-point + +It will be no surprise that floating-point numbers have a decimal point, and a fractional part after the point. + +```julia-repl +julia> f = 3.45 +3.45 + +julia> typeof(f) +Float64 +``` + +Of course, scientific notation is supported. + +```julia-repl +julia> avogadro = 6.02e23 +6.02e23 +``` + +The maximum and minimum values may come as a surprise: + +```julia-repl +julia> typemax(Float64) +Inf + +julia> typemin(Float64) +-Inf +``` + +Infinity is a valid value! + +## Arithmetic operators + +As discussed in the Basics concept, arithmetic operators mostly work the same as standard arithmetic, as taught to children. +Note that exponentiation uses `^`, _not_ `**` (both are common in other languages). + +```julia +2 + 3 # 5 (addition) +2 - 3 # -1 (subtraction) +2 * 3 # 6 (multiplication) +8 / 2 # 4.0 (division) +8 % 3 # 2 (remainder) +2 ^ 3 # 8 (exponentiation) +``` + +However, a few Julia-specific details are worth discussing. + +### Multiplication + +```julia-repl +julia> x = 4.2 +4.2 + +julia> 2 * x +8.4 + +julia> 2x +8.4 + +julia> 2.4x +10.08 +``` + +That may be surprising. + +It is always possible to use `*` as an infix operator, as in most other computer languages. + +However, Julia is designed by people who believe that code should look as much as possible like mathematical equations. + +Because variable names must start with a letter, prefacing the name with a number (integer or floating-point) is treated as implicit multiplication. + +For example, if we want the surface area of a sphere, instead of `4 * pi * r * r` we could do this : + +```julia-repl +julia> surface(r) = 4π * r^2 +surface (generic function with 1 method) + +julia> surface(3) +113.09733552923255 +``` + +Although π is a built-in constant, it is also a (Greek) letter. +The parser therefore still needs one explicit `*` to separate `π` from `r`. + +### Division + +Using `/` as the infix operator will always give a floating-point result, even for integer inputs. + +For integer division, there are more options. + +```julia-repl +julia> 10 / 3 # floating-point division +3.3333333333333335 + +julia> div(10, 3) # integer division +3 + +julia> 10 ÷ 3 # synonym for div() +3 + +julia> 10 // 3 # rational number (fraction) +10//3 +``` + +The `div()` function is for integer division, with the result truncated towards zero: downwards for positive numbers, upwards for negative numbers. + +As a synonym, we can use the infix operator `÷`, again aiming to make it look more mathematical. +If you are using a Julia-aware editor, enter this as `\div` then hit the `` key. + +The `//` operator is beyond the scope of this Concept. +For now, we can just say that the result of `//` is a "rational" number, which most people call a _fraction_. + +## Conversion of numeric types + +This can often happen automatically: + +```julia-repl +julia> x = 2 + 3.5 +5.5 + +julia> typeof(x) +Float64 +``` + +We added an `Int64` to a `Float64`, and got a `Float64` result. + +In fact, the integer was silently converted to a `Float64` before doing the addition. + +**Float-to-integer** conversions are inevitably more complicated. +What do you want to do with anything after the decimal point? + +- The `round()` function converts to the nearest whole number, with ties such as 4.5 rounding to the nearest _even_ whole number. +- `floor()` rounds down, `ceil()` rounds up, `trunc()` rounds towards zero. +- Attempting to cast directly, for example with `Int32()`, will fail with an `InexactError`. + +However, by default these functions do not return the integer type you might have wanted. +The desired output type can be specified. + +```julia-repl +julia> round(4.5) +4.0 + +julia> ceil(Int, 4.3) +5 +``` + +Rounding to a specified number of digits after the decimal point is also possible with the `digits` keyword. + +```julia-repl +julia> round(π, digits=10) +3.1415926536 +``` + +## Divide-by-zero + +Surely this just throws an error? +In fact, the situation is not that simple. + +Integer division with `÷` or `//` will result in an error, as you might expect. + +Floating-point division with `/` takes what might be considered an engineering approach, rather than a standard computer science approach: + +```julia-repl +julia> 2 / 0 +Inf + +julia> 0 / 0 +NaN +``` + +As discussed in a previous section, infinity is a valid floating-point number in Julia, represented by `Inf`. + +When the numerator is also zero, the result is mathematically undefined. +Julia then treats it as "not a number", represented by `NaN`. + +[basics]: https://exercism.org/tracks/julia/concepts/basics + +## Instructions + +Your friend Chandler plans to visit exotic countries all around the world. Sadly, Chandler's math skills aren't good. He's pretty worried about being scammed by currency exchanges during his trip - and he wants you to make a currency calculator for him. Here are his specifications for the app: + +## 1. Estimate value after exchange + +Create the `exchange_money()` function, taking 2 parameters: + +1. `budget` : The amount of money you are planning to exchange. +2. `exchange_rate` : The amount of domestic currency equal to one unit of foreign currency. + +This function should return the value of the exchanged currency. + +**Note:** If your currency is USD and you want to exchange USD for EUR with an exchange rate of `1.20`, then `1.20 USD == 1 EUR`. + +```julia +julia> exchange_money(127.5, 1.2) +106.25 +``` + +## 2. Calculate currency left after an exchange + +Create the `get_change()` function, taking 2 parameters: + +1. `budget` : Amount of money before exchange. +2. `exchanging_value` : Amount of money that is *taken* from the budget to be exchanged. + +This function should return the amount of money that *is left* from the budget. + +```julia +julia> get_change(127.5, 120) +7.5 +``` + +## 3. Calculate value of bills + +Create the `get_value_of_bills()` function, taking 2 parameters: + +1. `denomination` : The value of a single bill. +2. `number_of_bills` : The total number of bills. + +This exchanging booth only deals in cash of certain increments. +The total you receive must be divisible by the value of one "bill" or unit, which can leave behind a fraction or remainder. +Your function should return only the total value of the bills (_excluding fractional amounts_) the booth would give back. +Unfortunately, the booth gets to keep the remainder/change as an added bonus. + +```julia +julia> get_value_of_bills(5, 128) +640 +``` + +## 4. Calculate number of bills + +Create the `get_number_of_bills()` function, taking `amount` and `denomination`. + +This function should return the _number of currency bills_ that you can receive within the given _amount_. +In other words: How many _whole bills_ of currency fit into the starting amount? +Remember -- you can only receive _whole bills_, not fractions of bills, so remember to divide accordingly. +Effectively, you are rounding _down_ to the nearest whole bill/denomination. + +```julia +julia> get_number_of_bills(127.5, 5) +25 +``` + +## 5. Calculate leftover after exchanging into bills + +Create the `get_leftover_of_bills()` function, taking `amount` and `denomination`. + +This function should return the _leftover amount_ that cannot be returned from your starting _amount_ given the denomination of bills. +It is very important to know exactly how much the booth gets to keep. + +```julia +julia> get_leftover_of_bills(127.5, 20) +7.5 +``` + +## 6. Calculate value after exchange + +Create the `exchangeable_value()` function, taking `budget`, `exchange_rate`, `spread`, and `denomination`. + +Parameter `spread` is the *percentage taken* as an exchange fee, written as an integer. +It needs to be converted to decimal by dividing it by 100. +If `1.00 EUR == 1.20 USD` and the *spread* is `10`, the actual exchange rate will be: `1.00 EUR == 1.32 USD` because 10% of 1.20 is 0.12, and this additional fee is added to the exchange. + +This function should return the maximum value of the new currency after calculating the *exchange rate* plus the *spread*. +Remember that the currency *denomination* is a whole number, and cannot be sub-divided. + +**Note:** Returned value should be an integer type. + +```julia +julia> exchangeable_value(127.25, 1.20, 10, 20) +80 + +julia> exchangeable_value(127.25, 1.20, 10, 5) +95 +``` + +## Source + +### Created by + +- @colinleach \ No newline at end of file diff --git a/julia/currency-exchange/currency-exchange.jl b/julia/currency-exchange/currency-exchange.jl new file mode 100644 index 0000000..3041f1b --- /dev/null +++ b/julia/currency-exchange/currency-exchange.jl @@ -0,0 +1,24 @@ +function exchange_money(budget, exchange_rate) + return budget / exchange_rate +end + +function get_change(budget, exchanging_value) + return budget - exchanging_value +end + +function get_value_of_bills(denomination, number_of_bills) + return denomination * number_of_bills +end + +function get_number_of_bills(amount, denomination) + return amount ÷ denomination +end + +function get_leftover_of_bills(amount, denomination) + return amount % denomination +end + +function exchangeable_value(budget, exchange_rate, spread, denomination) + actual_exchange_rate = exchange_rate * (1 + spread / 100) + return floor(Int, budget / actual_exchange_rate / denomination) * denomination +end diff --git a/julia/currency-exchange/runtests.jl b/julia/currency-exchange/runtests.jl new file mode 100644 index 0000000..d3a2e95 --- /dev/null +++ b/julia/currency-exchange/runtests.jl @@ -0,0 +1,41 @@ +using Test + +include("currency-exchange.jl") + +@testset verbose = true "tests" begin + @testset "1. exchange_money" begin + @test isapprox(exchange_money(100000, 0.8), 125000; atol=0.1) + @test isapprox(exchange_money(700000, 10.0), 70000; atol=0.1) + end + + @testset "2. get_change" begin + @test isapprox(get_change(463000, 5000), 458000; atol=0.1) + @test isapprox(get_change(1250, 120), 1130; atol=0.1) + @test isapprox(get_change(15000, 1380), 13620; atol=0.1) + end + + @testset "3. get_value_of_bills" begin + @test get_value_of_bills(10000, 128) == 1280000 + @test get_value_of_bills(50, 360) == 18000 + @test get_value_of_bills(200, 200) == 40000 + end + + @testset "4. get_number_of_bills" begin + @test get_number_of_bills(163270, 50000) == 3 + @test get_number_of_bills(54361, 1000) == 54 + end + + @testset "5. get_leftover_of_bills" begin + @test isapprox(get_leftover_of_bills(10.1, 10), 0.1; atol=1e-8) + @test isapprox(get_leftover_of_bills(654321.0, 5), 1.0; atol=1e-8) + @test isapprox(get_leftover_of_bills(3.14, 2) , 1.14; atol=1e-8) + end + + @testset "6. exchangeable_value" begin + @test exchangeable_value(100000, 10.61, 10, 1) == 8568 + @test exchangeable_value(1500, 0.84, 25, 40) == 1400 + @test exchangeable_value(470000, 1050, 30, 10000000000) == 0 + @test exchangeable_value(470000, 0.00000009, 30, 700) == 4017094016600 + @test exchangeable_value(425.33, 0.0009, 30, 700) == 363300 + end +end diff --git a/julia/darts/.exercism/config.json b/julia/darts/.exercism/config.json new file mode 100644 index 0000000..bf3a2d9 --- /dev/null +++ b/julia/darts/.exercism/config.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "vyu" + ], + "contributors": [ + "cmcaine" + ], + "files": { + "solution": [ + "darts.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Calculate the points scored in a single toss of a Darts game.", + "source": "Inspired by an exercise created by a professor Della Paolera in Argentina" +} diff --git a/julia/darts/.exercism/metadata.json b/julia/darts/.exercism/metadata.json new file mode 100644 index 0000000..a9ac530 --- /dev/null +++ b/julia/darts/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"darts","id":"f274fafe88954ab6bace971d3f6adf19","url":"https://exercism.org/tracks/julia/exercises/darts","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/darts/HELP.md b/julia/darts/HELP.md new file mode 100644 index 0000000..5809957 --- /dev/null +++ b/julia/darts/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit darts.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/darts/README.md b/julia/darts/README.md new file mode 100644 index 0000000..08bf9f5 --- /dev/null +++ b/julia/darts/README.md @@ -0,0 +1,50 @@ +# Darts + +Welcome to Darts on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Calculate the points scored in a single toss of a Darts game. + +[Darts][darts] is a game where players throw darts at a [target][darts-target]. + +In our particular instance of the game, the target rewards 4 different amounts of points, depending on where the dart lands: + +![Our dart scoreboard with values from a complete miss to a bullseye](https://assets.exercism.org/images/exercises/darts/darts-scoreboard.svg) + +- If the dart lands outside the target, player earns no points (0 points). +- If the dart lands in the outer circle of the target, player earns 1 point. +- If the dart lands in the middle circle of the target, player earns 5 points. +- If the dart lands in the inner circle of the target, player earns 10 points. + +The outer circle has a radius of 10 units (this is equivalent to the total radius for the entire target), the middle circle a radius of 5 units, and the inner circle a radius of 1. +Of course, they are all centered at the same point — that is, the circles are [concentric][] defined by the coordinates (0, 0). + +Given a point in the target (defined by its [Cartesian coordinates][cartesian-coordinates] `x` and `y`, where `x` and `y` are [real][real-numbers]), calculate the correct score earned by a dart landing at that point. + +## Credit + +The scoreboard image was created by [habere-et-dispertire][habere-et-dispertire] using [Inkscape][inkscape]. + +[darts]: https://en.wikipedia.org/wiki/Darts +[darts-target]: https://en.wikipedia.org/wiki/Darts#/media/File:Darts_in_a_dartboard.jpg +[concentric]: https://mathworld.wolfram.com/ConcentricCircles.html +[cartesian-coordinates]: https://www.mathsisfun.com/data/cartesian-coordinates.html +[real-numbers]: https://www.mathsisfun.com/numbers/real-numbers.html +[habere-et-dispertire]: https://exercism.org/profiles/habere-et-dispertire +[inkscape]: https://en.wikipedia.org/wiki/Inkscape + +## Source + +### Created by + +- @vyu + +### Contributed to by + +- @cmcaine + +### Based on + +Inspired by an exercise created by a professor Della Paolera in Argentina \ No newline at end of file diff --git a/julia/darts/darts.jl b/julia/darts/darts.jl new file mode 100644 index 0000000..da1ad3b --- /dev/null +++ b/julia/darts/darts.jl @@ -0,0 +1,12 @@ +function score(x, y) + dist = sqrt(x^2 + y^2) + if dist <= 1 + return 10 + elseif dist <= 5 + return 5 + elseif dist <= 10 + return 1 + else + return 0 + end +end diff --git a/julia/darts/runtests.jl b/julia/darts/runtests.jl new file mode 100644 index 0000000..6a74512 --- /dev/null +++ b/julia/darts/runtests.jl @@ -0,0 +1,57 @@ +using Test + +include("darts.jl") + +@testset verbose = true "tests" begin + @testset "Missed target" begin + @test score(-9, 9) == 0 + end + + @testset "On the outer circle" begin + @test score(0, 10) == 1 + end + + @testset "On the middle circle" begin + @test score(-5, 0) == 5 + end + + @testset "On the inner circle" begin + @test score(0, -1) == 10 + end + + @testset "Exactly on centre" begin + @test score(0, 0) == 10 + end + + @testset "Near the centre" begin + @test score(-0.1, -0.1) == 10 + end + + @testset "Just within the inner circle" begin + @test score(0.7, 0.7) == 10 + end + + @testset "Just outside the inner circle" begin + @test score(0.8, -0.8) == 5 + end + + @testset "Just within the middle circle" begin + @test score(-3.5, 3.5) == 5 + end + + @testset "Just outside the middle circle" begin + @test score(-3.6, -3.6) == 1 + end + + @testset "Just within the outer circle" begin + @test score(-7.0, 7.0) == 1 + end + + @testset "Just outside the outer circle" begin + @test score(7.1, -7.1) == 0 + end + + @testset "Asymmetric position between the inner and middle circles" begin + @test score(0.5, -4) == 5 + end +end diff --git a/julia/difference-of-squares/.exercism/config.json b/julia/difference-of-squares/.exercism/config.json new file mode 100644 index 0000000..5119537 --- /dev/null +++ b/julia/difference-of-squares/.exercism/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "SaschaMann" + ], + "contributors": [ + "bovine3dom", + "cmcaine" + ], + "files": { + "solution": [ + "difference-of-squares.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.", + "source": "Problem 6 at Project Euler", + "source_url": "https://projecteuler.net/problem=6" +} diff --git a/julia/difference-of-squares/.exercism/metadata.json b/julia/difference-of-squares/.exercism/metadata.json new file mode 100644 index 0000000..d7740fe --- /dev/null +++ b/julia/difference-of-squares/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"difference-of-squares","id":"43726f141cb245cbb9d9c8b9cbdc4dc7","url":"https://exercism.org/tracks/julia/exercises/difference-of-squares","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/difference-of-squares/HELP.md b/julia/difference-of-squares/HELP.md new file mode 100644 index 0000000..8dcc6dc --- /dev/null +++ b/julia/difference-of-squares/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit difference-of-squares.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/difference-of-squares/README.md b/julia/difference-of-squares/README.md new file mode 100644 index 0000000..756f96e --- /dev/null +++ b/julia/difference-of-squares/README.md @@ -0,0 +1,34 @@ +# Difference of Squares + +Welcome to Difference of Squares on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Find the difference between the square of the sum and the sum of the squares of the first N natural numbers. + +The square of the sum of the first ten natural numbers is +(1 + 2 + ... + 10)² = 55² = 3025. + +The sum of the squares of the first ten natural numbers is +1² + 2² + ... + 10² = 385. + +Hence the difference between the square of the sum of the first ten natural numbers and the sum of the squares of the first ten natural numbers is 3025 - 385 = 2640. + +You are not expected to discover an efficient solution to this yourself from first principles; research is allowed, indeed, encouraged. +Finding the best algorithm for the problem is a key skill in software engineering. + +## Source + +### Created by + +- @SaschaMann + +### Contributed to by + +- @bovine3dom +- @cmcaine + +### Based on + +Problem 6 at Project Euler - https://projecteuler.net/problem=6 \ No newline at end of file diff --git a/julia/difference-of-squares/difference-of-squares.jl b/julia/difference-of-squares/difference-of-squares.jl new file mode 100644 index 0000000..657f0ee --- /dev/null +++ b/julia/difference-of-squares/difference-of-squares.jl @@ -0,0 +1,14 @@ +"Square the sum of the first `n` positive integers" +function square_of_sum(n) + return sum(1:n)^2 +end + +"Sum the squares of the first `n` positive integers" +function sum_of_squares(n) + return sum((1:n).^2) +end + +"Subtract the sum of squares from square of the sum of the first `n` positive ints" +function difference(n) + return square_of_sum(n) - sum_of_squares(n) +end diff --git a/julia/difference-of-squares/runtests.jl b/julia/difference-of-squares/runtests.jl new file mode 100644 index 0000000..16d3e95 --- /dev/null +++ b/julia/difference-of-squares/runtests.jl @@ -0,0 +1,27 @@ +using Test + +include("difference-of-squares.jl") + +@testset verbose = true "tests" begin + @testset "Square the sum of the numbers up to the given number" begin + @test square_of_sum(1)::Integer == 1 + @test square_of_sum(5)::Integer == 225 + @test square_of_sum(10)::Integer == 3025 + @test square_of_sum(100)::Integer == 25502500 + end + + @testset "Sum the squares of the numbers up to the given number" begin + @test sum_of_squares(1)::Integer == 1 + @test sum_of_squares(5)::Integer == 55 + @test sum_of_squares(10)::Integer == 385 + @test sum_of_squares(100)::Integer == 338350 + end + + @testset "Subtract sum of squares from square of sums" begin + @test difference(0)::Integer == 0 + @test difference(1)::Integer == 0 + @test difference(5)::Integer == 170 + @test difference(10)::Integer == 2640 + @test difference(100)::Integer == 25164150 + end +end diff --git a/julia/eliuds-eggs/.exercism/config.json b/julia/eliuds-eggs/.exercism/config.json new file mode 100644 index 0000000..0be81f4 --- /dev/null +++ b/julia/eliuds-eggs/.exercism/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "eliuds-eggs.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Help Eliud count the number of eggs in her chicken coop by counting the number of 1 bits in a binary representation.", + "source": "Christian Willner, Eric Willigers", + "source_url": "https://forum.exercism.org/t/new-exercise-suggestion-pop-count/7632/5" +} diff --git a/julia/eliuds-eggs/.exercism/metadata.json b/julia/eliuds-eggs/.exercism/metadata.json new file mode 100644 index 0000000..aa187b0 --- /dev/null +++ b/julia/eliuds-eggs/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"eliuds-eggs","id":"52e0e72667584ac59823a6b0a8e8671e","url":"https://exercism.org/tracks/julia/exercises/eliuds-eggs","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/eliuds-eggs/HELP.md b/julia/eliuds-eggs/HELP.md new file mode 100644 index 0000000..3143866 --- /dev/null +++ b/julia/eliuds-eggs/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit eliuds-eggs.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/eliuds-eggs/README.md b/julia/eliuds-eggs/README.md new file mode 100644 index 0000000..42bfc36 --- /dev/null +++ b/julia/eliuds-eggs/README.md @@ -0,0 +1,89 @@ +# Eliud's Eggs + +Welcome to Eliud's Eggs on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Introduction + +Your friend Eliud inherited a farm from her grandma Tigist. +Her granny was an inventor and had a tendency to build things in an overly complicated manner. +The chicken coop has a digital display showing an encoded number representing the positions of all eggs that could be picked up. + +Eliud is asking you to write a program that shows the actual number of eggs in the coop. + +The position information encoding is calculated as follows: + +1. Scan the potential egg-laying spots and mark down a `1` for an existing egg or a `0` for an empty spot. +2. Convert the number from binary to decimal. +3. Show the result on the display. + +## Example 1 + +![Seven individual nest boxes arranged in a row whose first, third, fourth and seventh nests each have a single egg.](https://assets.exercism.org/images/exercises/eliuds-eggs/example-1-coop.svg) + +```text + _ _ _ _ _ _ _ +|E| |E|E| | |E| +``` + +### Resulting Binary + +![1011001](https://assets.exercism.org/images/exercises/eliuds-eggs/example-1-binary.svg) + +```text + _ _ _ _ _ _ _ +|1|0|1|1|0|0|1| +``` + +### Decimal number on the display + +89 + +### Actual eggs in the coop + +4 + +## Example 2 + +![Seven individual nest boxes arranged in a row where only the fourth nest has an egg.](https://assets.exercism.org/images/exercises/eliuds-eggs/example-2-coop.svg) + +```text + _ _ _ _ _ _ _ +| | | |E| | | | +``` + +### Resulting Binary + +![0001000](https://assets.exercism.org/images/exercises/eliuds-eggs/example-2-binary.svg) + +```text + _ _ _ _ _ _ _ +|0|0|0|1|0|0|0| +``` + +### Decimal number on the display + +8 + +### Actual eggs in the coop + +1 + +## Instructions + +Your task is to count the number of 1 bits in the binary representation of a number. + +## Restrictions + +Keep your hands off that bit-count functionality provided by your standard library! +Solve this one yourself using other basic tools instead. + +## Source + +### Created by + +- @BNAndras + +### Based on + +Christian Willner, Eric Willigers - https://forum.exercism.org/t/new-exercise-suggestion-pop-count/7632/5 \ No newline at end of file diff --git a/julia/eliuds-eggs/eliuds-eggs.jl b/julia/eliuds-eggs/eliuds-eggs.jl new file mode 100644 index 0000000..871f965 --- /dev/null +++ b/julia/eliuds-eggs/eliuds-eggs.jl @@ -0,0 +1,3 @@ +function eggcount(number) + return count_ones(number) +end diff --git a/julia/eliuds-eggs/runtests.jl b/julia/eliuds-eggs/runtests.jl new file mode 100644 index 0000000..43dfd79 --- /dev/null +++ b/julia/eliuds-eggs/runtests.jl @@ -0,0 +1,21 @@ +using Test + +include("eliuds-eggs.jl") + +@testset verbose = true "tests" begin + @testset "0 eggs" begin + @test eggcount(0) == 0 + end + + @testset "1 egg" begin + @test eggcount(16) == 1 + end + + @testset "4 eggs" begin + @test eggcount(89) == 4 + end + + @testset "13 eggs" begin + @test eggcount(2000000000) == 13 + end +end \ No newline at end of file diff --git a/julia/elyses-enchantments/.exercism/config.json b/julia/elyses-enchantments/.exercism/config.json new file mode 100644 index 0000000..383cf08 --- /dev/null +++ b/julia/elyses-enchantments/.exercism/config.json @@ -0,0 +1,24 @@ +{ + "authors": [ + "colinleach" + ], + "contributors": [ + "cmcaine", + "SaschaMann" + ], + "files": { + "solution": [ + "elyses-enchantments.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "forked_from": [ + "javascript/enchantments" + ], + "blurb": "Help Elyse with her Enchantments and learn about vectors in the process." +} diff --git a/julia/elyses-enchantments/.exercism/metadata.json b/julia/elyses-enchantments/.exercism/metadata.json new file mode 100644 index 0000000..b9c1154 --- /dev/null +++ b/julia/elyses-enchantments/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"elyses-enchantments","id":"8ff6920e905b4432a422b226ce01e7d4","url":"https://exercism.org/tracks/julia/exercises/elyses-enchantments","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/elyses-enchantments/HELP.md b/julia/elyses-enchantments/HELP.md new file mode 100644 index 0000000..a6abaf4 --- /dev/null +++ b/julia/elyses-enchantments/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit elyses-enchantments.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/elyses-enchantments/HINTS.md b/julia/elyses-enchantments/HINTS.md new file mode 100644 index 0000000..49a9683 --- /dev/null +++ b/julia/elyses-enchantments/HINTS.md @@ -0,0 +1,42 @@ +# Hints + +## 1. Retrieve a card from a stack + +- `Vector` indices start at `1`. +- You can retrieve the `n`th value in a vector `v` with `v[n]`. + +## 2. Exchange a card in the stack + +- `Vector`s are mutable, you can change their contents at any time by assigning a new value. + +## 3. Insert a card at the of top of the stack + +- There is a method [`push!`][push] in Base to add a new value to the end of a collection. + +## 4. Remove a card from the stack + +- There is a method [`deleteat!`][deleteat] in Base to delete an element from a `Vector` at a given index. + +## 5. Remove the top card from the stack + +- There is a method [`pop!`][pop] in Base to remove an element at the end of a collection. + +## 6. Insert a card at the bottom of the stack + +- There is a method [`pushfirst!`][pushfirst] in Base to insert a new value to start of a collection. + +## 7. Remove a card from the bottom of the stack + +- There is a method [`popfirst!`][popfirst] in Base to remove an element at the start of a collection. + +## 8. Check the size of the stack + +- There is a method [`length`][length] in Base to retrieve the length of a collection. + +[push]: https://docs.julialang.org/en/v1/base/collections/#Base.push! +[pop]: https://docs.julialang.org/en/v1/base/collections/#Base.pop! +[pushfirst]: https://docs.julialang.org/en/v1/base/collections/#Base.pushfirst! +[popfirst]: https://docs.julialang.org/en/v1/base/collections/#Base.popfirst! +[insert]: https://docs.julialang.org/en/v1/base/collections/#Base.insert! +[deleteat]: https://docs.julialang.org/en/v1/base/collections/#Base.deleteat! +[length]: https://docs.julialang.org/en/v1/base/collections/#Base.length \ No newline at end of file diff --git a/julia/elyses-enchantments/README.md b/julia/elyses-enchantments/README.md new file mode 100644 index 0000000..0889289 --- /dev/null +++ b/julia/elyses-enchantments/README.md @@ -0,0 +1,243 @@ +# Elyses Enchantments + +Welcome to Elyses Enchantments on Exercism's Julia 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 + +A central aim of Julia is to be able to perform calculations on numerical data, quickly and efficiently. +_Lots_ of numerical data. + +Typically, the data will be stored in arrays (or some related type), so it is reasonable to say that arrays are at the heart of the Julia language. + +Arrays can be of arbitrary size (subject only to memory constraints in your hardware), and can have arbitrarily many dimensions. + +This introductory Concept concentrates on the basics of 1-dimensional arrays, which are called Vectors. + +## Creating Vectors + +In Julia, a Vector is an ordered sequence of values that can be accessed by index number. + +The simplest way to create a Vector is to list the values in square brackets: + +```julia-repl +julia> num_vec = [1, 4, 9] +3-element Vector{Int64}: + 1 + 4 + 9 + +julia> str_vec = ["arrays", "are", "important"] +3-element Vector{String}: + "arrays" + "are" + "important" +``` + +The Vector type matches the type of each element. + +_So Vectors need to be homogeneous (all elements the same type)?_ + +At some level, yes — and it is recommended to aim for this if you want the best performance. +However, Julia can work round this limitation (when necessary) by using the `Any` type: + +```julia-repl +julia> mixed_vector = [1, "str", 'c'] +3-element Vector{Any}: + 1 + "str" + 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase) +``` + +Please read and remember this rule: + +- ***By default, indexing in Julia starts at 1, not 0***. + +This is familiar to anyone who has used other data science languages (R, Matlab, Fortran...), but may seem shocking to computer scientists with a background in C-like languages. + +Otherwise, indexes work as you might guess: just put them in square brackets: + +```julia +squares = [0, 1, 4, 9, 16] +squares[1] # 0 +squares[3] # 4 +squares[begin] # 0 ("begin" is synonym for 1) +squares[end] # 16 ("end" is synonym for length(squares)) +``` + +Note the convenience of indexing with `end` (which is very useful) and `begin` (which is probably not). + +Python programmers may be wondering about negative indices. +Don't: these are not part of Julia, and will raise a `BoundsError`, as will any index smaller than 1 or bigger than `length(squares)`. + +## Vector operations + +Vectors in Julia are _mutable_: we can change the contents of individual cells. + +```julia-repl +julia> vals = [1, 3, 5, 7] +4-element Vector{Int64}: + 1 + 3 + 5 + 7 + +julia> vals[2] = 4 # reassign the value of this element +4 + +# Only the value at position 2 changes: +julia> vals +4-element Vector{Int64}: + 1 + 4 + 5 + 7 +``` + +There are many functions available for manipulating vectors, though the Julia documentation generalizes them to "collections" rather than vectors. + +Note that, by convention, functions that mutate their input have `!` in the name. +The compiler will not enforce this, but it is a very _strong_ convention in the Julia world. + +These are a few of the useful functions: + +- To add values to the end of the vector, use `push!()`. +- To remove the last value, use `pop!()`. +- To operate on the start of the vector, the corresponding functions are `pushfirst!()` and `popfirst!()`. +- To insert or remove an element at any position, there is `insert!()` and `deleteat!()`. + +```julia-repl +julia> vals = [1, 3] +2-element Vector{Int64}: + 1 + 3 + +julia> push!(vals, 5, 6) # can add multiple values +4-element Vector{Int64}: + 1 + 3 + 5 + 6 + +julia> pop!(vals) # mutates vals, return popped value +6 + +julia> vals +3-element Vector{Int64}: + 1 + 3 + 5 +``` + +## Instructions + +As a magician-to-be, Elyse needs to practice some basics. +She has a stack of cards that she wants to manipulate. + +To make things a bit easier she only uses the cards 1 to 10 so her stack of cards can be represented by a vector of numbers. +The position of a certain card corresponds to the index in the vector. + +## 1. Retrieve a card from a stack + +To pick a card, return the card at index `position` from the given stack. + +```julia-repl +julia> stack = [1, 2, 4, 1]; +julia> position = 3; +julia> get_item(stack, position) +4 +``` + +## 2. Exchange a card in the stack + +Perform some sleight of hand and exchange the card at index `position` with the replacement card provided. +Return the adjusted stack. + +```julia-repl +julia> stack = [1, 2, 4, 1]; +julia> position = 3; +julia> replacement_card = 6; +julia> set_item!(stack, position, replacement_card) +[1, 2, 6, 1] +``` + +## 3. Insert a card at the top of the stack + +Make a card appear by inserting a new card at the top of the stack. +Return the adjusted stack. + +```julia-repl +julia> stack = [5, 9, 7, 1]; +julia> new_card = 8; +julia> insert_item_at_top!(stack, new_card) +[5, 9, 7, 1, 8] +``` + +## 4. Remove a card from the stack + +Make a card disappear by removing the card at the given `position` from the stack. +Return the adjusted stack. + +```julia-repl +julia> stack = [3, 2, 6, 4, 8]; +julia> position = 3; +julia> remove_item!(stack, position) +[3, 2, 4, 8] +``` + +## 5. Remove the top card from the stack + +Make a card disappear by removing the card at the top of the stack. +Return the adjusted stack. + +```julia-repl +julia> stack = [3, 2, 6, 4, 8]; +julia> remove_item_from_top!(stack) +[3, 2, 6, 4] +``` + +## 6. Insert a card at the bottom of the stack + +Make a card appear by inserting a new card at the bottom of the stack. +Return the adjusted stack. + +```julia-repl +julia> stack = [5, 9, 7, 1]; +julia> new_card = 8; +julia> insert_item_at_bottom!(stack, new_card) +[8, 5, 9, 7, 1] +``` + +## 7. Remove a card from the bottom of the stack + +Make a card disappear by removing the card at the bottom of the stack. +Return the adjusted stack. + +```julia-repl +julia> stack = [8, 5, 9, 7, 1]; +julia> remove_item_at_bottom!(stack) +[5, 9, 7, 1] +``` + +## 8. Check the size of the stack + +Check whether the size of the stack is equal to `stack_size` or not. + +```julia-repl +julia> stack = [3, 2, 6, 4, 8]; +julia> stack_size = 4; +julia> check_size_of_stack(stack, stack_size) +false +``` + +## Source + +### Created by + +- @colinleach + +### Contributed to by + +- @cmcaine +- @SaschaMann \ No newline at end of file diff --git a/julia/elyses-enchantments/elyses-enchantments.jl b/julia/elyses-enchantments/elyses-enchantments.jl new file mode 100644 index 0000000..4bb5187 --- /dev/null +++ b/julia/elyses-enchantments/elyses-enchantments.jl @@ -0,0 +1,50 @@ +function get_item(stack, position) + if position < 1 || position > length(stack) + error("Position out of bounds") + end + return stack[position] +end + +function set_item!(stack, position, replacement_card) + if position < 1 || position > length(stack) + error("Position out of bounds") + end + stack[position] = replacement_card + return stack +end + +function insert_item_at_top!(stack, new_card) + push!(stack, new_card) + return stack +end + +function remove_item!(stack, position) + if position < 1 || position > length(stack) + error("Position out of bounds") + end + deleteat!(stack, position) +end + +function remove_item_from_top!(stack) + if isempty(stack) + error("Stack is empty") + end + return deleteat!(stack, length(stack)) +end + +function insert_item_at_bottom!(stack, new_card) + pushfirst!(stack, new_card) + return stack +end + +function remove_item_at_bottom!(stack) + if isempty(stack) + error("Stack is empty") + end + popfirst!(stack) + return stack +end + +function check_size_of_stack(stack, stack_size) + return length(stack) == stack_size +end diff --git a/julia/elyses-enchantments/runtests.jl b/julia/elyses-enchantments/runtests.jl new file mode 100644 index 0000000..1bc6692 --- /dev/null +++ b/julia/elyses-enchantments/runtests.jl @@ -0,0 +1,229 @@ +using Test + +include("elyses-enchantments.jl") + +@testset verbose = true "tests" begin + @testset "Retrieve a card from a deck" begin + + @testset "get the first card" begin + stack = [1, 2, 3] + position = 1 + @test get_item(stack, position) == 1 + end + + @testset "get the middle card" begin + stack = [4, 5, 6] + position = 2 + @test get_item(stack, position) == 5 + end + + @testset "get the last card" begin + stack = [9, 8, 7] + position = 3 + @test get_item(stack, position) == 7 + end + + end + + @testset "Replace a card in a deck" begin + + @testset "replace the first card with a 7" begin + stack = [1, 2, 3] + position = 1 + replacement_card = 7 + @test set_item!(stack, position, replacement_card) == [7, 2, 3] + end + + @testset "replace the middle card with a 5" begin + stack = [2, 2, 2] + position = 2 + replacement_card = 5 + @test set_item!(stack, position, replacement_card) == [2, 5, 2] + end + + @testset "replace the last card with a 7" begin + stack = [7, 7, 6] + position = 3 + replacement_card = 7 + @test set_item!(stack, position, replacement_card) == [7, 7, 7] + end + + end + + @testset "Add a card at the top" begin + + @testset "adding a second card at the top" begin + stack = [1] + new_card = 5 + @test insert_item_at_top!(stack, new_card) == [1, 5] + end + + @testset "adding a third card at the top" begin + stack = [1, 5] + new_card = 9 + @test insert_item_at_top!(stack, new_card) == [1, 5, 9] + end + + @testset "adding a fourth card at the top" begin + stack = [1, 5, 9] + new_card = 2 + @test insert_item_at_top!(stack, new_card) == [1, 5, 9, 2] + end + + @testset "adding a different fourth card at the top" begin + stack = [1, 5, 9] + new_card = 8 + @test insert_item_at_top!(stack, new_card) == [1, 5, 9, 8] + end + + end + + @testset "Removing a card" begin + + @testset "remove the card at the bottom" begin + stack = [1, 2, 3, 4] + position = 1 + @test remove_item!(stack, position) == [2, 3, 4] + end + + @testset "remove the card at the top" begin + stack = [1, 2, 3, 4] + position = 4 + @test remove_item!(stack, position) == [1, 2, 3] + end + + @testset "remove the second card" begin + stack = [1, 2, 3, 4] + position = 2 + @test remove_item!(stack, position) == [1, 3, 4] + end + + end + + @testset "Removing a card from the top" begin + + @testset "remove the only card from the top" begin + stack = [1] + @test remove_item_from_top!(stack) == [] + end + + @testset "remove the card from the top" begin + stack = [1, 2, 3] + @test remove_item_from_top!(stack) == [1, 2] + end + + end + + @testset "Add a card at the bottom" begin + + @testset "adding a second card to the bottom" begin + stack = [1] + new_card = 5 + @test insert_item_at_bottom!(stack, new_card) == [5, 1] + end + + @testset "adding a third card to the bottom" begin + stack = [5, 1] + new_card = 9 + @test insert_item_at_bottom!(stack, new_card) == [9, 5, 1] + end + + @testset "adding a fourth card to the bottom" begin + stack = [9, 5, 1] + new_card = 2 + @test insert_item_at_bottom!(stack, new_card) == [2, 9, 5, 1] + end + + @testset "adding a different fourth card to the bottom" begin + stack = [9, 5, 1] + new_card = 8 + @test insert_item_at_bottom!(stack, new_card) == [8, 9, 5, 1] + end + + end + + @testset "Remove a card from the bottom" begin + + @testset "remove the only card from the bottom" begin + stack = [1] + @test remove_item_at_bottom!(stack) == [] + end + + @testset "remove the card from the bottom" begin + stack = [1, 2, 3] + @test remove_item_at_bottom!(stack) == [2, 3] + end + + end + + @testset "Check size of stack" begin + + @testset "an empty stack of cards" begin + stack = [] + stack_size = 0 + @test check_size_of_stack(stack, stack_size) == true + end + + @testset "an empty stack of cards" begin + stack = [] + stack_size = 1 + @test check_size_of_stack(stack, stack_size) == false + end + + @testset "has exactly 1 card" begin + stack = [7] + stack_size = 0 + @test check_size_of_stack(stack, stack_size) == false + end + + @testset "has exactly 1 card" begin + stack = [7] + stack_size = 1 + @test check_size_of_stack(stack, stack_size) == true + end + + @testset "has exactly 1 card" begin + stack = [7] + stack_size = 2 + @test check_size_of_stack(stack, stack_size) == false + end + + @testset "has exactly 4 cards" begin + stack = [2, 4, 6, 8] + stack_size = 3 + @test check_size_of_stack(stack, stack_size) == false + end + + @testset "has exactly 4 cards" begin + stack = [2, 4, 6, 8] + stack_size = 4 + @test check_size_of_stack(stack, stack_size) == true + end + + @testset "has exactly 4 cards" begin + stack = [2, 4, 6, 8] + stack_size = 15 + @test check_size_of_stack(stack, stack_size) == false + end + + @testset "has exactly 5 cards" begin + stack = [1, 3, 5, 7, 9] + stack_size = 3 + @test check_size_of_stack(stack, stack_size) == false + end + + @testset "has exactly 5 cards" begin + stack = [1, 3, 5, 7, 9] + stack_size = 4 + @test check_size_of_stack(stack, stack_size) == false + end + + @testset "has exactly 5 cards" begin + stack = [1, 3, 5, 7, 9] + stack_size = 5 + @test check_size_of_stack(stack, stack_size) == true + end + + end + +end diff --git a/julia/hello-world/.exercism/config.json b/julia/hello-world/.exercism/config.json new file mode 100644 index 0000000..76a7e45 --- /dev/null +++ b/julia/hello-world/.exercism/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "SaschaMann" + ], + "files": { + "solution": [ + "hello-world.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Exercism's classic introductory exercise. Just say \"Hello, World!\".", + "source": "This is an exercise to introduce users to using Exercism", + "source_url": "https://en.wikipedia.org/wiki/%22Hello,_world!%22_program" +} diff --git a/julia/hello-world/.exercism/metadata.json b/julia/hello-world/.exercism/metadata.json new file mode 100644 index 0000000..fdab958 --- /dev/null +++ b/julia/hello-world/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"hello-world","id":"c59bb6656d48428d9b0d411c2144f108","url":"https://exercism.org/tracks/julia/exercises/hello-world","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/hello-world/HELP.md b/julia/hello-world/HELP.md new file mode 100644 index 0000000..4b1d28b --- /dev/null +++ b/julia/hello-world/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit hello-world.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/hello-world/README.md b/julia/hello-world/README.md new file mode 100644 index 0000000..b3d339f --- /dev/null +++ b/julia/hello-world/README.md @@ -0,0 +1,31 @@ +# Hello World + +Welcome to Hello World on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +The classical introductory exercise. +Just say "Hello, World!". + +["Hello, World!"][hello-world] is the traditional first program for beginning programming in a new language or environment. + +The objectives are simple: + +- Modify the provided code so that it produces the string "Hello, World!". +- Run the test suite and make sure that it succeeds. +- Submit your solution and check it at the website. + +If everything goes well, you will be ready to fetch your first real exercise. + +[hello-world]: https://en.wikipedia.org/wiki/%22Hello,_world!%22_program + +## Source + +### Created by + +- @SaschaMann + +### Based on + +This is an exercise to introduce users to using Exercism - https://en.wikipedia.org/wiki/%22Hello,_world!%22_program \ No newline at end of file diff --git a/julia/hello-world/hello-world.jl b/julia/hello-world/hello-world.jl new file mode 100644 index 0000000..6ae75bf --- /dev/null +++ b/julia/hello-world/hello-world.jl @@ -0,0 +1,3 @@ +function hello() + return "Hello, World!" +end diff --git a/julia/hello-world/runtests.jl b/julia/hello-world/runtests.jl new file mode 100644 index 0000000..2b99ccc --- /dev/null +++ b/julia/hello-world/runtests.jl @@ -0,0 +1,9 @@ +using Test + +include("hello-world.jl") + +@testset verbose = true "tests" begin + @testset "Say Hi!" begin + @test hello() == "Hello, World!" + end +end diff --git a/julia/lasagna/.exercism/config.json b/julia/lasagna/.exercism/config.json new file mode 100644 index 0000000..7e1785c --- /dev/null +++ b/julia/lasagna/.exercism/config.json @@ -0,0 +1,26 @@ +{ + "authors": [ + "SaschaMann" + ], + "contributors": [ + "ErikSchierboom", + "glennj", + "colinleach" + ], + "files": { + "solution": [ + "lasagna.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "language_versions": "≥1.0", + "forked_from": [ + "fsharp/lucians-luscious-lasagna" + ], + "blurb": "Learn the basics of functions in Julia by cooking delicious lasagna." +} diff --git a/julia/lasagna/.exercism/metadata.json b/julia/lasagna/.exercism/metadata.json new file mode 100644 index 0000000..a8364a0 --- /dev/null +++ b/julia/lasagna/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"lasagna","id":"72394dfe8aac4bf0a1eda56025bdb913","url":"https://exercism.org/tracks/julia/exercises/lasagna","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/lasagna/HELP.md b/julia/lasagna/HELP.md new file mode 100644 index 0000000..0f7decd --- /dev/null +++ b/julia/lasagna/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit lasagna.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/lasagna/HINTS.md b/julia/lasagna/HINTS.md new file mode 100644 index 0000000..1072198 --- /dev/null +++ b/julia/lasagna/HINTS.md @@ -0,0 +1,26 @@ +# Hints + +## General + +- You will need to define [functions][functions] and use [arithmetic operators][arithmetics]. + +## 1. Store the expected bake time in a constant + +- Define a [const][const] to store this value. + +## 2. Calculate the preparation time in minutes + +- Use the [`times` arithmetic operator][arithmetics] to multiply the argument by `2`. + +## 3. Calculate the remaining oven time in minutes + +- Use the [`minus` arithmetic operator][arithmetics] to subtract the argument from `60`. + +## 4. Calculate the total working time in minutes + +- Reuse the `preparation_time` function defined in the first step. +- Use the [`plus` arithmetic operator][arithmetics] to add the return value of `preparation_time` to the argument. + +[const]: https://docs.julialang.org/en/v1/base/base/#const +[functions]: https://docs.julialang.org/en/v1/manual/functions/ +[arithmetics]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Arithmetic-Operators-1 \ No newline at end of file diff --git a/julia/lasagna/README.md b/julia/lasagna/README.md new file mode 100644 index 0000000..ac42930 --- /dev/null +++ b/julia/lasagna/README.md @@ -0,0 +1,164 @@ +# Lasagna + +Welcome to Lasagna on Exercism's Julia 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 + +The entire Julia track will require you to treat your solution like small libraries, i.e. you need to define functions, types etc. which will then be run against a test suite. +For that reason, we will introduce named functions as the very first concept. + +Julia is a dynamic, strongly-typed programming langauge. +The programming style is mainly functional, though with more flexibility than in languages such as Haskell. + +## Variables and assignment + +There is no need to declare a variable in advance. +Just assign a value to a suitable name: + +```julia-repl +julia> myvar = 42 # an integer +42 + +julia> name = "Maria" # strings are surrounded by double-quotes "" +"Maria" +``` + +## Constants + +If a value needs to be available throughout the program, but is not expected to change, it is best to mark it as a constant. + +Prefacing an assignment with the `const` keyword allows the compiler to generate more efficient code than is possible for a variable. + +Constants also help to protect you against errors in coding. +Accidentally trying to change the `const` value will give a warning: + +```julia-repl +julia> const answer = 42 +42 + +julia> answer = 24 +WARNING: redefinition of constant Main.answer. This may fail, cause incorrect answers, or produce other errors. +24 +``` + +Note that a `const` can only be declared *outside* any function. +This will typically be near the top of the `*.jl` file, before the function definitions. + +## Arithmetic operators + +These are the same as in many other languages: + +```julia +2 + 3 # 5 (addition) +2 - 3 # -1 (subtraction) +2 * 3 # 6 (multiplication) +8 / 2 # 4.0 (division with floating-point result) +8 % 3 # 2 (remainder) +``` + +## Functions + +There are two common ways to define a named function in Julia: + +1. Using the `function` keyword + + ```julia + function muladd(x, y, z) + x * y + z + end + ``` + + Indentation by 4 spaces is conventional for readability, but the compiler ignores this. + The `end` keyword is essential. + + Note that we could have written `return x * y + z`. + However, Julia functions always return the last expression evaluated, so the `return` keyword is optional. + Many programmers prefer to include it to make their intentions more explicit. + +2. Using the "assignment form" + + ```julia + muladd(x, y, z) = x * y + z + ``` + + This is most commonly used for making concise single-expression functions. + + A `return` keyword is *never* used in the assignment form. + +The two forms are equivalent, and are used in exactly the same way, so choose whichever is more readable. + +Invoking a function is done by specifying its name and passing arguments for each of the function's parameters: + +```julia +# invoking a function +muladd(10, 5, 1) + +# and of course you can invoke a function within the body of another function: +square_plus_one(x) = muladd(x, x, 1) +``` + +## Naming conventions + +Like many languages, Julia requires that names (of variables, functions, and many other things) start with a letter, followed by any combination of letters, digits and underscores. + +By convention, variable, constant, and function names are *lowercase*, with underscores kept to a reasonable minimum. + +## Instructions + +In this exercise you're going to write some code to help you cook a brilliant lasagna from your favorite cooking book. + +You have four tasks, all related to the time spent cooking the lasagna. + +## 1. Store the expected bake time in a constant + +Define the `expected_bake_time` constant that returns how many minutes the lasagna should bake in the oven. + +According to the cooking book, lasagna needs to be in the oven for a total of 60 minutes. + +```julia-repl +julia> expected_bake_time +60 +``` + +## 2. Calculate the preparation time in minutes + +Define the `preparation_time` function that takes the number of layers you added to the lasagna as an argument and returns how many minutes you spent preparing the lasagna, assuming each layer takes you 2 minutes to prepare. + +```julia-repl +julia> preparation_time(4) +8 +``` + +## 3. Calculate the remaining oven time in minutes + +Define the `remaining_time` function that takes the actual minutes the lasagna has been in the oven as a parameter and returns how many minutes the lasagna still has to remain in the oven. + +```julia-repl +julia> remaining_time(50) +10 +``` + +## 4. Calculate the total working time in minutes + +Define the `total_working_time` function that takes two arguments: the first argument is the number of layers you added to the lasagna, and the second argument is the number of minutes the lasagna has been in the oven. + +The function should return how many minutes in total you've worked on cooking the lasagna, which is the sum of the preparation time in minutes, and the time in minutes the lasagna has spent in the oven at the moment. + +```julia-repl +julia> total_working_time(3, 20) +26 +``` + +## Source + +### Created by + +- @SaschaMann + +### Contributed to by + +- @ErikSchierboom +- @glennj +- @colinleach \ No newline at end of file diff --git a/julia/lasagna/lasagna.jl b/julia/lasagna/lasagna.jl new file mode 100644 index 0000000..d714d73 --- /dev/null +++ b/julia/lasagna/lasagna.jl @@ -0,0 +1,14 @@ +# Define the `expected_bake_time` constant` +const expected_bake_time = 60 +# Define the `preparation_time(layers)` function. +function preparation_time(layers) + return layers * 2 +end +# Define the `remaining_time(time_in_oven)` function. +function remaining_time(time_in_oven) + return expected_bake_time - time_in_oven +end +# Define the `total_working_time(layers, time_in_oven)` function. +function total_working_time(layers, time_in_oven) + return preparation_time(layers) + time_in_oven +end diff --git a/julia/lasagna/runtests.jl b/julia/lasagna/runtests.jl new file mode 100644 index 0000000..fbcd182 --- /dev/null +++ b/julia/lasagna/runtests.jl @@ -0,0 +1,29 @@ +using Test + +include("lasagna.jl") + +@testset verbose = true "tests" begin + + @testset "expected bake time" begin + @test expected_bake_time == 60 + if VERSION > v"1.7" + @test isconst(@__MODULE__, :expected_bake_time) == true + end + end + + @testset "preparation time" begin + @test preparation_time(2) == 4 + @test preparation_time(3) == 6 + @test preparation_time(8) == 16 + end + + @testset "remaining time" begin + @test remaining_time(30) == 30 + @test remaining_time(50) == 10 + @test remaining_time(60) == 0 + end + + @testset "total working time" begin + @test total_working_time(3, 20) == 26 + end +end diff --git a/julia/leap/.exercism/config.json b/julia/leap/.exercism/config.json new file mode 100644 index 0000000..bea48d2 --- /dev/null +++ b/julia/leap/.exercism/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "andrej-makarov-skrt" + ], + "contributors": [ + "cmcaine", + "SaschaMann" + ], + "files": { + "solution": [ + "leap.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://web.archive.org/web/20240907033714/https://coderanch.com/t/718816/Leap" +} diff --git a/julia/leap/.exercism/metadata.json b/julia/leap/.exercism/metadata.json new file mode 100644 index 0000000..7f52ddc --- /dev/null +++ b/julia/leap/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"leap","id":"d3610687536242a2866418473aae6ee8","url":"https://exercism.org/tracks/julia/exercises/leap","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/leap/HELP.md b/julia/leap/HELP.md new file mode 100644 index 0000000..9956e8f --- /dev/null +++ b/julia/leap/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit leap.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/leap/README.md b/julia/leap/README.md new file mode 100644 index 0000000..0703992 --- /dev/null +++ b/julia/leap/README.md @@ -0,0 +1,40 @@ +# Leap + +Welcome to Leap on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Introduction + +A leap year (in the Gregorian calendar) occurs: + +- In every year that is evenly divisible by 4. +- Unless the year is evenly divisible by 100, in which case it's only a leap year if the year is also evenly divisible by 400. + +Some examples: + +- 1997 was not a leap year as it's not divisible by 4. +- 1900 was not a leap year as it's not divisible by 400. +- 2000 was a leap year! + +~~~~exercism/note +For a delightful, four-minute explanation of the whole phenomenon of leap years, check out [this YouTube video](https://www.youtube.com/watch?v=xX96xng7sAE). +~~~~ + +## Instructions + +Your task is to determine whether a given year is a leap year. + +## Source + +### Created by + +- @andrej-makarov-skrt + +### Contributed to by + +- @cmcaine +- @SaschaMann + +### Based on + +CodeRanch Cattle Drive, Assignment 3 - https://web.archive.org/web/20240907033714/https://coderanch.com/t/718816/Leap \ No newline at end of file diff --git a/julia/leap/leap.jl b/julia/leap/leap.jl new file mode 100644 index 0000000..7d8d9d2 --- /dev/null +++ b/julia/leap/leap.jl @@ -0,0 +1,18 @@ +""" + is_leap_year(year) + +Return `true` if `year` is a leap year in the gregorian calendar. + +""" +function divisible_by_4(year) + return year % 4 == 0 +end + +function divisible_by_100_and_400(year) + return year % 100 != 0 || year % 400 == 0 +end + + +function is_leap_year(year) + return divisible_by_4(year) && divisible_by_100_and_400(year) +end diff --git a/julia/leap/runtests.jl b/julia/leap/runtests.jl new file mode 100644 index 0000000..756c521 --- /dev/null +++ b/julia/leap/runtests.jl @@ -0,0 +1,45 @@ +using Test + +include("leap.jl") + +@testset verbose = true "tests" begin + @testset "Year not divisible by 4: common year" begin + @test !is_leap_year(2015) + end + + @testset "Year divisible by 2, not divisible by 4: common year" begin + @test !is_leap_year(1970) + end + + @testset "Year divisible by 4, not divisible by 100: leap year" begin + @test is_leap_year(1996) + end + + @testset "Year divisible by 4 and 5: leap year" begin + @test is_leap_year(1960) + end + + @testset "Year divisible by 4, not divisible by 100: leap year" begin + @test is_leap_year(2016) + end + + @testset "Year divisible by 100, not divisible by 400: common year" begin + @test !is_leap_year(2100) + end + + @testset "Year divisible by 100 but not by 3: common year" begin + @test !is_leap_year(1900) + end + + @testset "Year divisible by 400: leap year" begin + @test is_leap_year(2000) + end + + @testset "Year divisible by 400 but not by 125: leap year" begin + @test is_leap_year(2400) + end + + @testset "Year divisible by 200, not divisible by 400: common year" begin + @test !is_leap_year(1800) + end +end diff --git a/julia/mixed-juices/.exercism/config.json b/julia/mixed-juices/.exercism/config.json new file mode 100644 index 0000000..b349eb7 --- /dev/null +++ b/julia/mixed-juices/.exercism/config.json @@ -0,0 +1,20 @@ +{ + "authors": [ + "colinleach" + ], + "files": { + "solution": [ + "mixed-juices.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "forked_from": [ + "javascript/mixed-juices" + ], + "blurb": "Help Li Mei operate her juice store with loops" +} diff --git a/julia/mixed-juices/.exercism/metadata.json b/julia/mixed-juices/.exercism/metadata.json new file mode 100644 index 0000000..eb5f10b --- /dev/null +++ b/julia/mixed-juices/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"mixed-juices","id":"2bcf07bd0c844f98af28a5616fcafdae","url":"https://exercism.org/tracks/julia/exercises/mixed-juices","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/mixed-juices/HELP.md b/julia/mixed-juices/HELP.md new file mode 100644 index 0000000..bdfeccc --- /dev/null +++ b/julia/mixed-juices/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit mixed-juices.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/mixed-juices/HINTS.md b/julia/mixed-juices/HINTS.md new file mode 100644 index 0000000..f4e2187 --- /dev/null +++ b/julia/mixed-juices/HINTS.md @@ -0,0 +1,21 @@ +# Hints + +## 1. Determine how long it takes to mix a juice + +- Julia has no `switch` statement, in contrast to many other languages. +- The `if` ... `elsefif` ... `else` syntax was covered in the Conditionals concept. + +## 2. Replenish the lime wedge supply + +- A `while` loop can run until you have enough lime wedges. +- The `popfirst!()` function was covered in the Vectors concept. + +## 3. List the times to mix each order in the queue + +- Looping over a vector is easy with `for` ... `in`. +- Building a new vector could use `push!()`, which was covered in the Vectors concept. +- Later in the syllabus we will explore various other ways to do this in Julia. + +## 4. Finish up the shift + +- See task 2. \ No newline at end of file diff --git a/julia/mixed-juices/README.md b/julia/mixed-juices/README.md new file mode 100644 index 0000000..d0af0d0 --- /dev/null +++ b/julia/mixed-juices/README.md @@ -0,0 +1,148 @@ +# Mixed Juices + +Welcome to Mixed Juices on Exercism's Julia 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 + +There are basically two types of loops: + +1. Loop until a condition is satisfied. +2. Loop over the elements in a collection. + +Both are possible in Julia, though the second may be more common. + +## The `while` loop + +For open-ended problems where the number of times round the loop is unknown in advance, Julia has the `while` loop. + +The basic form is fairly simple: + +```julia +while condition + do_something() +end +``` + +In this case, the program will keep going round the loop until `condition` is no longer `true`. + +Two ways to exit the loop early are available: + +- A `break` causes the loop to exit, with execution continuing at the next line after the loop `end`. +- A `return x` stops execution of the current function, passing the return value `x` back to the caller. + +With these options available, it can sometimes be convenient to create an "infinite" loop with `while true ... end`, then rely on finding a stopping condition within the loop body to trigger a `break` or `return`. + +## Loop over a collection + +The simplest illustration is to loop over a range. + +If we want to do something 10 times: + +```julia +for n in 1:10 + do_something(n) +end +``` + +If the current iteration fails to satisfy some condition, it is possible to skip immediately to the next iteration with a `continue`: + +```julia +for n in 1:10 + if is_useless(n) + continue + end + + # we decided this iteration could be useful + do_something_slow(n) +end +``` + +In a shorter form, the `if` block could be replaced by `is_useless(n) && continue`. + +Many other collection types can be looped over: elements in an array, characters in a string, keys in a dictionary... + +The examples so far loop over the range `1:10`, where the value is also the loop index. + +More generally, the index may be needed and not just the value. +For this, the `eachindex()` function is used, for example `for i in eachindex(my_array) ... end`. + +## Instructions + +Your friend Li Mei runs a juice bar where she sells delicious mixed fruit juices. +You are a frequent customer in her shop and realized you could make your friend's life easier. +You decide to use your coding skills to help Li Mei with her job. + +## 1. Determine how long it takes to mix a juice + +Li Mei likes to tell her customers in advance how long they have to wait for a juice from the menu that they ordered. +She has a hard time remembering the exact numbers because the time it takes to mix the juices varies. +`"Pure Strawberry Joy"` takes 0.5 minutes, `"Energizer"` and `"Green Garden"` take 1.5 minutes each, `"Tropical Island"` takes 3 minutes and `"All or Nothing"` takes 5 minutes. +For all other drinks (e.g., special offers) you can assume a preparation time of 2.5 minutes. + +To help your friend, write a function `time_to_mix_juice` that takes a juice from the menu as an argument and returns the number of minutes it takes to mix that drink. + +```julia-repl +julia> time_to_mix_juice("Tropical Island") +3 + +julia> time_to_mix_juice("Berries & Lime") +2.5 +``` + +## 2. Replenish the lime wedge supply + +A lot of Li Mei's creations include lime wedges, either as an ingredient or as part of the decoration. +So when she starts her shift in the morning she needs to make sure the bin of lime wedges is full for the day ahead. + +Implement the function `limes_to_cut` which takes the number of lime wedges Li Mei needs to cut and an array representing the supply of whole limes she has at hand. +She can get 6 wedges from a `"small"` lime, 8 wedges from a `"medium"` lime and 10 from a `"large"` lime. +She always cuts the limes in the order in which they appear in the list, starting with the first item. +She keeps going until she reached the number of wedges that she needs or until she runs out of limes. + +Li Mei would like to know in advance how many limes she needs to cut. +The `limes_to_cut` function should return the number of limes to cut. + +```julia-repl +julia> limes_to_cut(25, ["small", "small", "large", "medium", "small"]) +4 +``` + +## 3. List the times to mix each order in the queue + +Li Mei likes to keep track of how long it will take to mix the orders customers are waiting for. + +Implement the `order_times` function, which takes a queue of orders and returns a vector of times to mix. + +```julia-repl +julia> order_times(["Energizer", "Tropical Island"]) +[1.5, 3.0] +``` + +## 4. Finish up the shift + +Li Mei always works until 3pm. +Then her employee Dmitry takes over. +There are often drinks that have been ordered but are not prepared yet when Li Mei's shift ends. +Dmitry will then prepare the remaining juices. + +To make the hand-over easier, implement a function `remaining_orders` which takes the number of minutes left in Li Mei"s shift and an array of juices that have been ordered but not prepared yet. +The function should return the orders that Li Mei cannot start preparing before the end of her workday. + +The time left in the shift will always be greater than 0. +The array of juices to prepare will never be empty. +Furthermore, the orders are prepared in the order in which they appear in the array. +If Li Mei starts to mix a certain juice, she will always finish it even if she has to work a bit longer. +If there are no remaining orders left that Dmitry needs to take care of, an empty vector should be returned. + +```julia-repl +julia> remaining_orders(5, ["Energizer", "All or Nothing", "Green Garden"]) +["Green Garden"] +``` + +## Source + +### Created by + +- @colinleach \ No newline at end of file diff --git a/julia/mixed-juices/mixed-juices.jl b/julia/mixed-juices/mixed-juices.jl new file mode 100644 index 0000000..c11e099 --- /dev/null +++ b/julia/mixed-juices/mixed-juices.jl @@ -0,0 +1,19 @@ +function time_to_mix_juice(juice) + +end + +function wedges_from_lime(size) + +end + +function limes_to_cut(needed, limes) + +end + +function order_times(orders) + +end + +function remaining_orders(time_left, orders) + +end diff --git a/julia/mixed-juices/runtests.jl b/julia/mixed-juices/runtests.jl new file mode 100644 index 0000000..07d808d --- /dev/null +++ b/julia/mixed-juices/runtests.jl @@ -0,0 +1,171 @@ +using Test + +include("mixed-juices.jl") + +@testset verbose = true "tests" begin + @testset "1. time_to_mix_juice" begin + @testset "Returns the correct time for 'Pure Strawberry Joy'" begin + @test time_to_mix_juice("Pure Strawberry Joy") == 0.5 + end + + @testset "Returns the correct time for 'Energizer'" begin + @test time_to_mix_juice("Energizer") == 1.5 + end + + @testset "Returns the correct time for 'Green Garden'" begin + @test time_to_mix_juice("Green Garden") == 1.5 + end + + @testset "Returns the correct time for 'Tropical Island'" begin + @test time_to_mix_juice("Tropical Island") == 3 + end + + @testset "Returns the correct time for 'All or Nothing'" begin + @test time_to_mix_juice("All or Nothing") == 5 + end + + @testset "Returns the correct time for all other juices" begin + default_time = 2.5 + @test time_to_mix_juice("Limetime") == default_time + @test time_to_mix_juice("Manic Organic") == default_time + @test time_to_mix_juice("Papaya & Peach") == default_time + end + end + + @testset "2. limes_to_cut" begin + @testset "Medium order" begin + limes = [ + "small", + "large", + "large", + "medium", + "small", + "large", + "large", + "medium" + ] + @test limes_to_cut(42, limes) == 6 + end + + @testset "Small order" begin + limes = [ + "medium", + "small" + ] + @test limes_to_cut(4, limes) == 1 + end + + @testset "Large order" begin + limes = [ + "small", + "large", + "large", + "medium", + "small", + "large", + "large" + ] + @test limes_to_cut(80, limes) == 7 + end + + @testset "If no new wedges are needed, no limes are cut" begin + limes = [ + "small", + "large", + "medium" + ] + @test limes_to_cut(0, limes) == 0 + end + + @testset "works if no limes are available" begin + limes = [] + @test limes_to_cut(10, limes) == 0 + end + end + + @testset "3. order_times" begin + @testset "correctly determines the times for current orders" begin + orders = [ + "Tropical Island", + "Energizer", + "Limetime", + "All or Nothing", + "Pure Strawberry Joy" + ] + expected = [3.0, 1.5, 2.5, 5.0, 0.5] + @test order_times(orders) == expected + end + + @testset "correctly determines the times for current orders" begin + orders = [ + "Pure Strawberry Joy", + "Pure Strawberry Joy", + "Vitality", + "Tropical Island", + "All or Nothing", + "All or Nothing", + "All or Nothing", + "Green Garden", + "Limetime" + ] + expected = [0.5, 0.5, 2.5, 3.0, 5.0, 5.0, 5.0, 1.5, 2.5] + @test order_times(orders) == expected + end + + @testset "correctly returns an empty list if there are no orders" begin + orders = [] + @test order_times(orders) == [] + end + end + + @testset "4. remaining_orders" begin + @testset "correctly determines the remaining orders" begin + orders = [ + "Tropical Island", + "Energizer", + "Limetime", + "All or Nothing", + "Pure Strawberry Joy" + ] + expected = ["All or Nothing", "Pure Strawberry Joy"] + @test remaining_orders(7, orders) == expected + end + + @testset "correctly determines the remaining orders" begin + orders = [ + "Pure Strawberry Joy", + "Pure Strawberry Joy", + "Vitality", + "Tropical Island", + "All or Nothing", + "All or Nothing", + "All or Nothing", + "Green Garden", + "Limetime" + ] + expected = ["All or Nothing", "Green Garden", "Limetime"] + @test remaining_orders(13, orders) == expected + end + + @testset "counts all orders as fulfilled if there is enough time" begin + orders = [ + "Energizer", + "Green Garden", + "Ruby Glow", + "Pure Strawberry Joy", + "Tropical Island", + "Limetime" + ] + @test remaining_orders(12, orders) == [] + end + + @testset "works if there is only very little time left" begin + orders = [ + "Bananas Gone Wild", + "Pure Strawberry Joy" + ] + expected = ["Pure Strawberry Joy"] + @test remaining_orders(0.2, orders) == expected + end + end +end diff --git a/julia/perfect-numbers/.exercism/config.json b/julia/perfect-numbers/.exercism/config.json new file mode 100644 index 0000000..2f21f61 --- /dev/null +++ b/julia/perfect-numbers/.exercism/config.json @@ -0,0 +1,25 @@ +{ + "authors": [ + "Akshat-mehrotra" + ], + "contributors": [ + "cmcaine", + "miguelraz", + "SaschaMann", + "logankilpatrick" + ], + "files": { + "solution": [ + "perfect-numbers.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Determine if a number is perfect, abundant, or deficient based on Nicomachus' (60 - 120 CE) classification scheme for positive integers.", + "source": "Taken from Chapter 2 of Functional Thinking by Neal Ford.", + "source_url": "https://www.oreilly.com/library/view/functional-thinking/9781449365509/" +} diff --git a/julia/perfect-numbers/.exercism/metadata.json b/julia/perfect-numbers/.exercism/metadata.json new file mode 100644 index 0000000..accacd2 --- /dev/null +++ b/julia/perfect-numbers/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"perfect-numbers","id":"63be4afee8e04dce908a953310580ba6","url":"https://exercism.org/tracks/julia/exercises/perfect-numbers","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/perfect-numbers/HELP.md b/julia/perfect-numbers/HELP.md new file mode 100644 index 0000000..34c91b7 --- /dev/null +++ b/julia/perfect-numbers/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit perfect-numbers.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/perfect-numbers/README.md b/julia/perfect-numbers/README.md new file mode 100644 index 0000000..dae4be5 --- /dev/null +++ b/julia/perfect-numbers/README.md @@ -0,0 +1,61 @@ +# Perfect Numbers + +Welcome to Perfect Numbers on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Determine if a number is perfect, abundant, or deficient based on Nicomachus' (60 - 120 CE) classification scheme for positive integers. + +The Greek mathematician [Nicomachus][nicomachus] devised a classification scheme for positive integers, identifying each as belonging uniquely to the categories of [perfect](#perfect), [abundant](#abundant), or [deficient](#deficient) based on their [aliquot sum][aliquot-sum]. +The _aliquot sum_ is defined as the sum of the factors of a number not including the number itself. +For example, the aliquot sum of `15` is `1 + 3 + 5 = 9`. + +## Perfect + +A number is perfect when it equals its aliquot sum. +For example: + +- `6` is a perfect number because `1 + 2 + 3 = 6` +- `28` is a perfect number because `1 + 2 + 4 + 7 + 14 = 28` + +## Abundant + +A number is abundant when it is less than its aliquot sum. +For example: + +- `12` is an abundant number because `1 + 2 + 3 + 4 + 6 = 16` +- `24` is an abundant number because `1 + 2 + 3 + 4 + 6 + 8 + 12 = 36` + +## Deficient + +A number is deficient when it is greater than its aliquot sum. +For example: + +- `8` is a deficient number because `1 + 2 + 4 = 7` +- Prime numbers are deficient + +## Task + +Implement a way to determine whether a given number is [perfect](#perfect). +Depending on your language track, you may also need to implement a way to determine whether a given number is [abundant](#abundant) or [deficient](#deficient). + +[nicomachus]: https://en.wikipedia.org/wiki/Nicomachus +[aliquot-sum]: https://en.wikipedia.org/wiki/Aliquot_sum + +## Source + +### Created by + +- @Akshat-mehrotra + +### Contributed to by + +- @cmcaine +- @miguelraz +- @SaschaMann +- @logankilpatrick + +### Based on + +Taken from Chapter 2 of Functional Thinking by Neal Ford. - https://www.oreilly.com/library/view/functional-thinking/9781449365509/ \ No newline at end of file diff --git a/julia/perfect-numbers/perfect-numbers.jl b/julia/perfect-numbers/perfect-numbers.jl new file mode 100644 index 0000000..323866f --- /dev/null +++ b/julia/perfect-numbers/perfect-numbers.jl @@ -0,0 +1,14 @@ +function get_divisors(n) + n > 0 || throw(DomainError(n)) + return sum(i for i in 1:n÷2 if iszero(n % i)) +end + +function isperfect(number) + return get_divisors(number) ≡ number +end +function isabundant(number) + return get_divisors(number) > number +end +function isdeficient(number) + return get_divisors(number) < number +end \ No newline at end of file diff --git a/julia/perfect-numbers/runtests.jl b/julia/perfect-numbers/runtests.jl new file mode 100644 index 0000000..ffa44f8 --- /dev/null +++ b/julia/perfect-numbers/runtests.jl @@ -0,0 +1,88 @@ +using Test + +include("perfect-numbers.jl") + +@testset verbose = true "tests" begin + @testset "Perfect numbers" begin + + @testset "Smallest perfect number is classified correctly" begin + @test isperfect(6) + end + + @testset "Medium perfect number is classified correctly" begin + @test isperfect(28) + end + + @testset "Large perfect number is classified correctly" begin + @test isperfect(33550336) + end + + @testset "Correctly handles non-perfect numbers" begin + @test !isperfect(12) + @test !isperfect(4) + end + end + + @testset "Abundant numbers" begin + + @testset "Smallest abundant number is classified correctly" begin + @test isabundant(12) + end + + @testset "Medium abundant number is classified correctly" begin + @test isabundant(30) + end + + @testset "Large abundant number is classified correctly" begin + @test isabundant(33550335) + end + + @testset "Correctly handles non-abundant numbers" begin + @test !isabundant(6) + @test !isabundant(32) + end + end + + @testset "Deficient numbers" begin + + @testset "Smallest prime deficient number is classified correctly" begin + @test isdeficient(2) + end + + @testset "Smallest non-prime deficient number is classified correctly" begin + @test isdeficient(4) + end + + @testset "Medium deficient number is classified correctly" begin + @test isdeficient(32) + end + + @testset "Large deficient number is classified correctly" begin + @test isdeficient(33550337) + end + + @testset "Edge case (no factors other than itself) is classified correctly" begin + @test isdeficient(1) + end + + @testset "Correctly handles non-deficient numbers" begin + @test !isdeficient(28) + @test !isdeficient(30) + end + end + + @testset "Invalid inputs" begin + + @testset "Zero is rejected (not a natural number)" begin + @test_throws DomainError isdeficient(0) + @test_throws DomainError isperfect(0) + @test_throws DomainError isabundant(0) + end + + @testset "Negative integer is rejected (not a natural number)" begin + @test_throws DomainError isdeficient(-1) + @test_throws DomainError isperfect(-1) + @test_throws DomainError isabundant(-1) + end + end +end diff --git a/julia/raindrops/.exercism/config.json b/julia/raindrops/.exercism/config.json new file mode 100644 index 0000000..a7d9f60 --- /dev/null +++ b/julia/raindrops/.exercism/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "andrej-makarov-skrt" + ], + "contributors": [ + "cmcaine", + "SaschaMann" + ], + "files": { + "solution": [ + "raindrops.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Convert a number into its corresponding raindrop sounds - Pling, Plang and Plong.", + "source": "A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division.", + "source_url": "https://en.wikipedia.org/wiki/Fizz_buzz" +} diff --git a/julia/raindrops/.exercism/metadata.json b/julia/raindrops/.exercism/metadata.json new file mode 100644 index 0000000..d0930e5 --- /dev/null +++ b/julia/raindrops/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"raindrops","id":"db442d635d8643bf9d7f0fa48936e303","url":"https://exercism.org/tracks/julia/exercises/raindrops","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/raindrops/HELP.md b/julia/raindrops/HELP.md new file mode 100644 index 0000000..a460c04 --- /dev/null +++ b/julia/raindrops/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit raindrops.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/raindrops/README.md b/julia/raindrops/README.md new file mode 100644 index 0000000..4028b7e --- /dev/null +++ b/julia/raindrops/README.md @@ -0,0 +1,48 @@ +# Raindrops + +Welcome to Raindrops on Exercism's Julia Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Introduction + +Raindrops is a slightly more complex version of the FizzBuzz challenge, a classic interview question. + +## Instructions + +Your task is to convert a number into its corresponding raindrop sounds. + +If a given number: + +- is divisible by 3, add "Pling" to the result. +- is divisible by 5, add "Plang" to the result. +- is divisible by 7, add "Plong" to the result. +- **is not** divisible by 3, 5, or 7, the result should be the number as a string. + +## Examples + +- 28 is divisible by 7, but not 3 or 5, so the result would be `"Plong"`. +- 30 is divisible by 3 and 5, but not 7, so the result would be `"PlingPlang"`. +- 34 is not divisible by 3, 5, or 7, so the result would be `"34"`. + +~~~~exercism/note +A common way to test if one number is evenly divisible by another is to compare the [remainder][remainder] or [modulus][modulo] to zero. +Most languages provide operators or functions for one (or both) of these. + +[remainder]: https://exercism.org/docs/programming/operators/remainder +[modulo]: https://en.wikipedia.org/wiki/Modulo_operation +~~~~ + +## Source + +### Created by + +- @andrej-makarov-skrt + +### Contributed to by + +- @cmcaine +- @SaschaMann + +### Based on + +A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division. - https://en.wikipedia.org/wiki/Fizz_buzz \ No newline at end of file diff --git a/julia/raindrops/raindrops.jl b/julia/raindrops/raindrops.jl new file mode 100644 index 0000000..3ec0548 --- /dev/null +++ b/julia/raindrops/raindrops.jl @@ -0,0 +1,16 @@ +function raindrops(number) + res = "" + if number % 3 == 0 + res *= "Pling" + end + if number % 5 == 0 + res *= "Plang" + end + if number % 7 == 0 + res *= "Plong" + end + if number % 3 != 0 && number % 5 != 0 && number % 7 != 0 + res *= string(number) + end + return res +end diff --git a/julia/raindrops/runtests.jl b/julia/raindrops/runtests.jl new file mode 100644 index 0000000..c423f34 --- /dev/null +++ b/julia/raindrops/runtests.jl @@ -0,0 +1,74 @@ +using Test + +include("raindrops.jl") + +@testset verbose = true "tests" begin + @testset "detect numbers" begin + @testset "the sound for 1 is 1" begin + @test raindrops(1) == "1" + end + @testset "2 to the power 3 does not make a raindrop sound as 3 is the exponent not the base" begin + @test raindrops(8) == "8" + end + @testset "the sound for 52 is 52" begin + @test raindrops(52) == "52" + end + end + + @testset "detect pling" begin + @testset "the sound for 3 is Pling" begin + @test raindrops(3) == "Pling" + end + @testset "the sound for 6 is Pling as it has a factor 3" begin + @test raindrops(6) == "Pling" + end + @testset "the sound for 9 is Pling as it has a factor 3" begin + @test raindrops(9) == "Pling" + end + @testset "the sound for 27 is Pling as it has a factor 3" begin + @test raindrops(27) == "Pling" + end + end + + @testset "detect plang" begin + @testset "the sound for 5 is Plang" begin + @test raindrops(5) == "Plang" + end + @testset "the sound for 10 is Plang as it has a factor 5" begin + @test raindrops(10) == "Plang" + end + @testset "the sound for 25 is Plang as it has a factor 5" begin + @test raindrops(25) == "Plang" + end + @testset "the sound for 3125 is Plang as it has a factor 5" begin + @test raindrops(3125) == "Plang" + end + end + + @testset "detect plong" begin + @testset "the sound for 7 is Plong" begin + @test raindrops(7) == "Plong" + end + @testset "the sound for 14 is Plong as it has a factor of 7" begin + @test raindrops(14) == "Plong" + end + @testset "the sound for 49 is Plong as it has a factor 7" begin + @test raindrops(49) == "Plong" + end + end + + @testset "detect multiple sounds" begin + @testset "the sound for 15 is PlingPlang as it has factors 3 and 5" begin + @test raindrops(15) == "PlingPlang" + end + @testset "the sound for 21 is PlingPlong as it has factors 3 and 7" begin + @test raindrops(21) == "PlingPlong" + end + @testset "the sound for 35 is PlangPlong as it has factors 5 and 7" begin + @test raindrops(35) == "PlangPlong" + end + @testset "the sound for 105 is PlingPlangPlong as it has factors 3, 5 and 7" begin + @test raindrops(105) == "PlingPlangPlong" + end + end +end diff --git a/julia/secrets/.exercism/config.json b/julia/secrets/.exercism/config.json new file mode 100644 index 0000000..a06bf83 --- /dev/null +++ b/julia/secrets/.exercism/config.json @@ -0,0 +1,20 @@ +{ + "authors": [ + "colinleach" + ], + "files": { + "solution": [ + "secrets.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "forked_from": [ + "java/secrets" + ], + "blurb": "Learn about bit manipulation by writing a program to decrypt a message." +} diff --git a/julia/secrets/.exercism/metadata.json b/julia/secrets/.exercism/metadata.json new file mode 100644 index 0000000..d4c4021 --- /dev/null +++ b/julia/secrets/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"julia","exercise":"secrets","id":"3bbfeb59334b4b14a09c7f5a345b04e5","url":"https://exercism.org/tracks/julia/exercises/secrets","handle":"Kimawari","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/julia/secrets/HELP.md b/julia/secrets/HELP.md new file mode 100644 index 0000000..3a00c76 --- /dev/null +++ b/julia/secrets/HELP.md @@ -0,0 +1,34 @@ +# Help + +## Running the tests + +To run the tests, run this command from within the exercise directory: + +```bash +$ julia runtests.jl +``` + +## Submitting your solution + +You can submit your solution using the `exercism submit secrets.jl` 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 [Julia track's documentation](https://exercism.org/docs/tracks/julia) +- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia) +- [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, we recommend that you submit your code and request mentoring :) + +If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/). \ No newline at end of file diff --git a/julia/secrets/HINTS.md b/julia/secrets/HINTS.md new file mode 100644 index 0000000..7475ea9 --- /dev/null +++ b/julia/secrets/HINTS.md @@ -0,0 +1,21 @@ +# Hints + +Some (not all) of the tests assume the value is `Int32`, so please avoid forcing it to be anything else. + +## 1. Shift back the bits + +- This is a right-shift. +- Note the instruction that the results should be left-filled with zeros. + +## 2. Set some bits + +- Bits are set by bitwise OR with a mask. This is extremely common. + +## 3. Flip specific bits + +- There is an old joke among programmers that cryptographers discovered XOR and forgot to read the rest of the manual. + +## 4. Clear specific bits + +- Simple AND logic will do the opposite of what you need. +- How do you flip all the bits in the mask? \ No newline at end of file diff --git a/julia/secrets/README.md b/julia/secrets/README.md new file mode 100644 index 0000000..710542a --- /dev/null +++ b/julia/secrets/README.md @@ -0,0 +1,185 @@ +# Secrets + +Welcome to Secrets on Exercism's Julia 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 + +Binary digits ultimately map directly to the transistors in your CPU or RAM, and whether each is "on" or "off". + +Low-level manipulation, informally called "bit-twiddling", is particularly important in system languages. + +High-level languages like Julia usually abstract away most of this detail. +However, a full range of bit-level operations are available in the base language. + +***Note:*** To see human-readable binary output in the REPL, nearly all the examples below need to be wrapped in a `bitstring()` function. +This is visually distracting, so most occurrences of this function have been edited out. + +## Bit-shift operations + +Integer types, signed or unsigned, can be represented as a string of 1's and 0's. + +```julia-repl +julia> bitstring(UInt8(5)) +"00000101" +``` + +Bit-shifts just move everything to the left or right by a specified number of positions. +With `UInt` types, some bits drop off one end, and the other end is padded with zeros: + +```julia-repl +julia> ux::UInt8 = 5 +5 + +julia> bitstring(ux) +"00000101" + +julia> ux << 2 # left by 2 +"00010100" + +julia> ux >> 1 # right by 1 +"00000010" +``` + +Each left-shift doubles the value and each right-shift halves it (subject to truncation). +This is more obvious in decimal representation: + +```julia-repl +julia> 3 << 2 +12 + +julia> 24 >> 3 +3 +``` + +Such bit-shifting is much faster than "proper" arithmetic, making the technique very popular in low-level coding. + +With signed integers, we need to be a bit more careful. + +Left shifts are relatively simple: + +```julia-repl +julia> sx = Int8(5) +5 + +julia> sx # positive integer +"00000101" + +julia> sx << 2 +"00010100" + +julia> -sx # negative integer +"11111011" + +julia> -sx << 2 +"11101100" +``` + +Left-shifting positive signed integers is thus the same as with unsigned integers. + +Negative values are stored in [two's complement][2complement] form, which means that the left-most bit is 1. +No problem for a left-shift, but when right-shifting how do we pad the left-most bits? + +```julia-repl +julia> sx >> 2 # simple for positive values! +"00000001" + +julia> -sx # negative integer +"11111011" + +julia> -sx >> 2 # pad with repeated sign bit +"11111110" + +julia> -sx >>> 2 # pad with 0 +"00111110" +``` + +The `>>` operator performs arithmetic shift, preserving the sign bit. + +The `>>>` operator performs logical shift, padding with zeros as if the number was unsigned. + +## Bitwise logic + +We saw in a previous Concept that the operators `&&` (and), `||` (or) and `!` (not) are used with boolean values. + +There are equivalent operators `&` (bitwise and), `|` (bitwise or) and `~` (a tilde, bitwise not) to compare the bits in two integers. + +```julia-repl +julia> 0b1011 & 0b0010 # bit is 1 in both numbers +"00000010" + +julia> 0b1011 | 0b0010 # bit is 1 in at least one number +"00001011" + +julia> ~0b1011 # flip all bits +"11110100" + +julia> xor(0b1011, 0b0010) # bit is 1 in exactly one number, not both +"00001001" +``` + +Here, `xor()` is exclusive-or, used as a function. + +[2complement]: https://en.wikipedia.org/wiki/Two%27s_complement + +## Instructions + +Your friend has just sent you a message with an important secret. +Not wanting to make it easy for others to read it, the message was encrypted by performing a series of bit manipulations. +You will need to write the functions to help decrypt the message. + +## 1. Shift back the bits + +The first step in decrypting the message is to undo the shifting from the encryption process by shifting the bits back to the right. +There will be further steps in the decryption process that assume 0s are inserted from the left hand side. + +Implement the `shift_back()` function that takes a value and the number of places to shift and peforms the shift. + +```julia +shift_back(0b1001, 2) # => 0b0010 +``` + +## 2. Set some bits + +Next, there are some bits that need to be set to 1. + +Implement the `set_bits()` function that takes a value and a mask and returns the result of setting the bits in value to 1. +A bit from `value` should be set to 1 where the bit in the `mask` is also 1. +All other bits should be kept unchanged. + +```julia +set_bits(0b0110, 0b0101) # => 0b0111 +``` + +## 3. Flip specific bits + +Some bits are flipped during encryption. +They will need to be flipped back to decrypt the message. + +Implement the `flip_bits()` function that takes a value and the mask. +The mask indicates which bits in the value to flip. +If the bit is 1 in `mask`, the bit is flipped in the `value`. +All other bits are kept unchanged. + +```julia +flip_bits(0b1100, 0b0101) # => 0b1001 +``` + +## 4. Clear specific bits + +Lastly, there are also certain bits that always decrypt to 0. + +Implement the `clear_bits()` function that takes a value and a mask. +The bits in the `value` should be set to 0 where the bit in the mask is 1. +All other bits should be kept unchanged. + +```julia +clear_bits(0b0110, 0b0101) # => 0b0010 +``` + +## Source + +### Created by + +- @colinleach \ No newline at end of file diff --git a/julia/secrets/runtests.jl b/julia/secrets/runtests.jl new file mode 100644 index 0000000..40eb844 --- /dev/null +++ b/julia/secrets/runtests.jl @@ -0,0 +1,30 @@ +using Test + +include("secrets.jl") + +@testset verbose = true "tests" begin + + @testset "1. Shift back the bits" begin + @test shift_back(8, 2) == 2 + + # The original Java code uses a signed integer, so we use Int32 here + # Fails with Int64! + @test shift_back(Int32(-2_144_333_657), 3) == 268_829_204 + end + + @testset "2. Set bits" begin + @test set_bits(5, 3) == 7 + @test set_bits(5_652, 26_150) == 30_262 + end + + @testset "3. Flip bits" begin + @test flip_bits(5, 11) == 14 + @test flip_bits(38_460, 15_471) == 43_603 + end + + @testset "4. Clear bits" begin + @test clear_bits(5, 11) == 4 + @test clear_bits(90, 240) == 10 + end + +end diff --git a/julia/secrets/secrets.jl b/julia/secrets/secrets.jl new file mode 100644 index 0000000..3112f4c --- /dev/null +++ b/julia/secrets/secrets.jl @@ -0,0 +1,15 @@ +function shift_back(value, amount) + return value >>> amount +end + +function set_bits(value, mask) + return value | mask +end + +function flip_bits(value, mask) + return value ⊻ mask +end + +function clear_bits(value, mask) + return value & ~mask +end