diff --git a/.github/workflows/auto-rebase.yml b/.github/workflows/auto-rebase.yml index d325e971..5d4d5fed 100644 --- a/.github/workflows/auto-rebase.yml +++ b/.github/workflows/auto-rebase.yml @@ -8,7 +8,7 @@ jobs: if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - name: Automatic Rebase uses: cirrus-actions/rebase@b87d48154a87a85666003575337e27b8cd65f691 env: diff --git a/.github/workflows/exercise-tests.yml b/.github/workflows/exercise-tests.yml index e1cf4fa8..7b6ccd47 100644 --- a/.github/workflows/exercise-tests.yml +++ b/.github/workflows/exercise-tests.yml @@ -23,16 +23,19 @@ jobs: fail-fast: false matrix: julia-version: ["1.6", "1", nightly] - os: [ubuntu-22.04, windows-2022, macOS-latest] + os: [ubuntu-22.04, windows-2022, macos-14] + exclude: + - julia-version: 1.6 + os: macos-14 steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: julia-actions/setup-julia@f40c4b69330df1d22e7590c12e76dc2f9c66e0bc + - uses: julia-actions/setup-julia@f2258781c657ad9b4b88072c5eeaf9ec8c370874 with: version: ${{ matrix.julia-version }} - - uses: julia-actions/cache@569d290d51d6c22c1cd4ceec591a1bf112aab9c0 + - uses: julia-actions/cache@d48542bb7b6239a9391789f01d21a6bdde9ad5df - name: Install test dependencies run: julia --color=yes --project -e "using Pkg; Pkg.instantiate()" @@ -45,20 +48,20 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - name: Pull julia-test-runner image run: docker pull exercism/julia-test-runner - name: Install Julia dependencies run: julia --color=yes --project -e "using Pkg; Pkg.instantiate()" - + - name: Generate test reports using julia-test-runner id: generate-reports run: julia --color=yes --project runtestrunner.jl - + - name: Upload reports as artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 with: name: test-reports path: ${{ steps.generate-reports.outputs.results-path }} diff --git a/.github/workflows/no-important-files-changed.yml b/.github/workflows/no-important-files-changed.yml new file mode 100644 index 00000000..812e9129 --- /dev/null +++ b/.github/workflows/no-important-files-changed.yml @@ -0,0 +1,23 @@ +name: No important files changed + +on: + pull_request_target: + types: [opened] + branches: [main] + paths: + - "exercises/concept/**" + - "exercises/practice/**" + - "!exercises/*/*/.approaches/**" + - "!exercises/*/*/.articles/**" + - "!exercises/*/*/.docs/**" + - "!exercises/*/*/.meta/**" + +permissions: + pull-requests: write + +jobs: + check: + uses: exercism/github-actions/.github/workflows/check-no-important-files-changed.yml@main + with: + repository: ${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.pull_request.head.repo.name }} + ref: ${{ github.head_ref }} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 4389c002..e0d8bd37 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -90,7 +90,7 @@ This policy was initially adopted from the Front-end London Slack community and A version history can be seen on [GitHub](https://github.com/exercism/website-copy/edit/main/pages/code_of_conduct.md). _This policy is a "living" document, and subject to refinement and expansion in the future. -This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Slack, Twitter, email) and any other Exercism entity or event._ +This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Discord, Forum, Twitter, email) and any other Exercism entity or event._ ## Addendum diff --git a/config.json b/config.json index 786d6447..0d57bce6 100644 --- a/config.json +++ b/config.json @@ -691,6 +691,14 @@ "unicode" ] }, + { + "slug": "resistor-color", + "name": "Resistor Color", + "uuid": "ef7e22db-1f66-4d44-87f9-23d97f794628", + "practices": [], + "prerequisites": [], + "difficulty": 1 + }, { "slug": "resistor-color-trio", "name": "Resistor Color Trio", @@ -881,6 +889,22 @@ "practices": [], "prerequisites": [], "difficulty": 1 + }, + { + "slug": "two-fer", + "name": "Two-Fer", + "uuid": "91a8a9c0-041c-4e2e-97fc-dae149ef69f9", + "practices": [], + "prerequisites": [], + "difficulty": 1 + }, + { + "slug": "connect", + "name": "Connect", + "uuid": "6cd9edb0-35ba-4f32-b51b-a734d98e3a88", + "practices": [], + "prerequisites": [], + "difficulty": 5 } ] }, diff --git a/exercises/concept.wip/annalyns-infiltration/runtests.jl b/exercises/concept.wip/annalyns-infiltration/runtests.jl index c31ae3a5..26e4fdd1 100644 --- a/exercises/concept.wip/annalyns-infiltration/runtests.jl +++ b/exercises/concept.wip/annalyns-infiltration/runtests.jl @@ -9,61 +9,63 @@ if VERSION < v"1.1" @eval eachrow(A) = (view(A, i, :) for i in axes(A, 1)) end -@testset "fast attack" begin - @test !can_do_fast_attack(true) - @test can_do_fast_attack(false) -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; - ] + @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] + for state in eachrow(character_state_combinations) + @test can_spy(state[1:3]...) == state[4] + end end -end -@testset "signaling prisoner" begin - character_state_combinations = Bool[ - 0 0 0; - 0 1 1; - 1 0 0; - 1 1 0; - ] + @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] + for state in eachrow(character_state_combinations) + @test can_signal_prisoner(state[1:2]...) == state[3] + end 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; - ] + @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] + for state in eachrow(character_state_combinations) + @test can_free_prisoner(state[1:4]...) == state[5] + end end end diff --git a/exercises/concept.wip/annalyns-infiltration2/runtests.jl b/exercises/concept.wip/annalyns-infiltration2/runtests.jl index 9bca8c30..ffcb7540 100644 --- a/exercises/concept.wip/annalyns-infiltration2/runtests.jl +++ b/exercises/concept.wip/annalyns-infiltration2/runtests.jl @@ -5,19 +5,21 @@ include("game.jl") # This exercise isn't about mathematical methods to determine the distribution of a random sample, # therefore we only test that all possible values are returned at least once. -@testset "fog" begin - @test Set(is_foggy() for _ in 1:1000) == Set([true, false]) -end +@testset verbose = true "tests" begin + @testset "fog" begin + @test Set(is_foggy() for _ in 1:1000) == Set([true, false]) + end -@testset "distracted dog" begin - @test Set(is_dog_distracted() for _ in 1:1000) == Set([true, false]) -end + @testset "distracted dog" begin + @test Set(is_dog_distracted() for _ in 1:1000) == Set([true, false]) + end -@testset "loot purse" begin - @test Set(loot() for _ in 1:1000) == Set(3:13) -end + @testset "loot purse" begin + @test Set(loot() for _ in 1:1000) == Set(3:13) + end -@testset "loot crate" begin - crate = Set(["Cabbage", "Daring Dagger", "Sneaky Shoes"]) - @test Set(loot(crate) for _ in 1:1000) == crate + @testset "loot crate" begin + crate = Set(["Cabbage", "Daring Dagger", "Sneaky Shoes"]) + @test Set(loot(crate) for _ in 1:1000) == crate + end end diff --git a/exercises/concept.wip/dnd-char/runtests.jl b/exercises/concept.wip/dnd-char/runtests.jl index b432f088..209f1048 100644 --- a/exercises/concept.wip/dnd-char/runtests.jl +++ b/exercises/concept.wip/dnd-char/runtests.jl @@ -2,49 +2,51 @@ using Test include("dnd-character.jl") -@testset "Randomly generated ability is within range" begin - for i in 1:1000 - @test 3 <= ability() <= 18 +@testset verbose = true "tests" begin + @testset "Randomly generated ability is within range" begin + for i in 1:1000 + @test 3 <= ability() <= 18 + end end -end - -@testset "Ability modifiers are integers" begin - @test typeof(modifier(7)) <: Integer -end -@testset "Ability modifiers" begin - @test modifier(3) == -4 - @test modifier(4) == -3 - @test modifier(5) == -3 - @test modifier(6) == -2 - @test modifier(7) == -2 - @test modifier(8) == -1 - @test modifier(9) == -1 - @test modifier(10) == 0 - @test modifier(11) == 0 - @test modifier(12) == 1 - @test modifier(13) == 1 - @test modifier(14) == 2 - @test modifier(15) == 2 - @test modifier(16) == 3 - @test modifier(17) == 3 - @test modifier(18) == 4 -end + @testset "Ability modifiers are integers" begin + @test typeof(modifier(7)) <: Integer + end -@testset "Randomly generated character is valid" begin - # Helper method to check if all abilities of a character are within the expected ranges. - function ischaracter(c) - 3 <= c.strength <= 18 && - 3 <= c.dexterity <= 18 && - 3 <= c.constitution <= 18 && - 3 <= c.intelligence <= 18 && - 3 <= c.wisdom <= 18 && - 3 <= c.charisma <= 18 && - c.hitpoints == 10 + modifier(c.constitution) + @testset "Ability modifiers" begin + @test modifier(3) == -4 + @test modifier(4) == -3 + @test modifier(5) == -3 + @test modifier(6) == -2 + @test modifier(7) == -2 + @test modifier(8) == -1 + @test modifier(9) == -1 + @test modifier(10) == 0 + @test modifier(11) == 0 + @test modifier(12) == 1 + @test modifier(13) == 1 + @test modifier(14) == 2 + @test modifier(15) == 2 + @test modifier(16) == 3 + @test modifier(17) == 3 + @test modifier(18) == 4 end - for i in 1:1000 - c = DNDCharacter() - @test ischaracter(c) + @testset "Randomly generated character is valid" begin + # Helper method to check if all abilities of a character are within the expected ranges. + function ischaracter(c) + 3 <= c.strength <= 18 && + 3 <= c.dexterity <= 18 && + 3 <= c.constitution <= 18 && + 3 <= c.intelligence <= 18 && + 3 <= c.wisdom <= 18 && + 3 <= c.charisma <= 18 && + c.hitpoints == 10 + modifier(c.constitution) + end + + for i in 1:1000 + c = DNDCharacter() + @test ischaracter(c) + end end end diff --git a/exercises/concept.wip/documented-lasagna/runtests.jl b/exercises/concept.wip/documented-lasagna/runtests.jl index 36e870d8..489917e7 100644 --- a/exercises/concept.wip/documented-lasagna/runtests.jl +++ b/exercises/concept.wip/documented-lasagna/runtests.jl @@ -22,24 +22,26 @@ function hasdocstring(s::Symbol) haskey(meta, Docs.Binding(@__MODULE__, s)) end -@testset "solution still works" begin - @test preptime(2) == 4 - @test preptime(3) == 6 - @test preptime(8) == 16 - @test remaining_time(30) == 30 - @test remaining_time(50) == 10 - @test remaining_time(60) == 0 - @test total_working_time(3, 20) == 26 -end - -@testset "preptime has a docstring" begin - @test hasdocstring(:preptime) -end - -@testset "remaining_time has a docstring" begin - @test hasdocstring(:remaining_time) -end - -@testset "total_working_time has a docstring" begin - @test hasdocstring(:total_working_time) +@testset verbose = true "tests" begin + @testset "solution still works" begin + @test preptime(2) == 4 + @test preptime(3) == 6 + @test preptime(8) == 16 + @test remaining_time(30) == 30 + @test remaining_time(50) == 10 + @test remaining_time(60) == 0 + @test total_working_time(3, 20) == 26 + end + + @testset "preptime has a docstring" begin + @test hasdocstring(:preptime) + end + + @testset "remaining_time has a docstring" begin + @test hasdocstring(:remaining_time) + end + + @testset "total_working_time has a docstring" begin + @test hasdocstring(:total_working_time) + end end diff --git a/exercises/concept.wip/elyses-analytic-enchantments/runtests.jl b/exercises/concept.wip/elyses-analytic-enchantments/runtests.jl index e77ba65d..b4376f77 100644 --- a/exercises/concept.wip/elyses-analytic-enchantments/runtests.jl +++ b/exercises/concept.wip/elyses-analytic-enchantments/runtests.jl @@ -2,37 +2,39 @@ using Test include("enchantments.jl") -@testset "Determine if a card is present" begin - @test has_card([2, 3, 4, 5], 3) -end +@testset verbose = true "tests" begin + @testset "Determine if a card is present" begin + @test has_card([2, 3, 4, 5], 3) + end -@testset "Find the position of a card" begin - @test find_card([3], 3) == 1 - @test find_card([9, 7, 3, 2], 2) == 4 - @test find_card([8, 3, 9, 5], 8) == 1 - @test isnothing(find_card([5, 3, 1, 9], 2)) -end + @testset "Find the position of a card" begin + @test find_card([3], 3) == 1 + @test find_card([9, 7, 3, 2], 2) == 4 + @test find_card([8, 3, 9, 5], 8) == 1 + @test isnothing(find_card([5, 3, 1, 9], 2)) + end -@testset "Determine if each card is even" begin - @test !all_cards_even([1]) - @test !all_cards_even([2, 5]) - @test all_cards_even([2, 4, 8, 6]) -end + @testset "Determine if each card is even" begin + @test !all_cards_even([1]) + @test !all_cards_even([2, 5]) + @test all_cards_even([2, 4, 8, 6]) + end -@testset "Check if the deck contains an odd-value card" begin - @test !any_odd_cards([2, 4, 6]) - @test any_odd_cards([2, 5]) - @test any_odd_cards([1, 3, 5, 7]) -end + @testset "Check if the deck contains an odd-value card" begin + @test !any_odd_cards([2, 4, 6]) + @test any_odd_cards([2, 5]) + @test any_odd_cards([1, 3, 5, 7]) + end -@testset "Determine the position of the first card that is even" begin - @test first_even_card_idx([2, 4, 1, 3]) == 1 - @test first_even_card_idx([1, 2]) == 2 - @test isnothing(first_even_card_idx([1, 3, 5])) -end + @testset "Determine the position of the first card that is even" begin + @test first_even_card_idx([2, 4, 1, 3]) == 1 + @test first_even_card_idx([1, 2]) == 2 + @test isnothing(first_even_card_idx([1, 3, 5])) + end -@testset "Get the first odd card from the deck" begin - @test first_odd_card([2, 4, 1, 3]) == 1 - @test first_odd_card([1, 2]) == 1 - @test isnothing(first_odd_card([4, 2, 6])) + @testset "Get the first odd card from the deck" begin + @test first_odd_card([2, 4, 1, 3]) == 1 + @test first_odd_card([1, 2]) == 1 + @test isnothing(first_odd_card([4, 2, 6])) + end end diff --git a/exercises/concept.wip/elyses-enchantments/runtests.jl b/exercises/concept.wip/elyses-enchantments/runtests.jl index dd287852..fd0cb951 100644 --- a/exercises/concept.wip/elyses-enchantments/runtests.jl +++ b/exercises/concept.wip/elyses-enchantments/runtests.jl @@ -2,45 +2,47 @@ using Test include("enchantments.jl") -@testset "Retrieve a card from a deck" begin - @test card([1, 3, 4, 1], 2) == 3 - @test_throws BoundsError card([1, 3, 4, 1], 0) -end - -@testset "Exchange a card in the deck" begin - @test replace_card!([1, 3, 4, 1], 2 => 6) == [1, 6, 4, 1] - @test_throws BoundsError replace_card!([1, 3, 4, 1], 5 => 6) -end - -@testset "Insert a card at the of top the deck" begin - @test insert_card_at_top!([1, 3, 4, 1], 8) == [1, 3, 4, 1, 8] -end - -@testset "Remove a card from the deck" begin - @test remove_card!([1, 3, 4, 1], 2) == [1, 4, 1] - @test_throws BoundsError remove_card!([], 0) - @test_throws BoundsError remove_card!([], 1) - @test_throws BoundsError remove_card!([1, 3, 4, 1], 0) - @test_throws BoundsError remove_card!([1, 3, 4, 1], 5) -end - -@testset "Remove the top card from the deck" begin - @test remove_card_from_top!([1, 3, 4, 1]) == [1, 3, 4] - @test_throws ArgumentError remove_card_from_top!([]) -end - -@testset "Insert a card at the bottom of the deck" begin - @test insert_card_at_bottom!([1, 3, 4, 1], 8) == [8, 1, 3, 4, 1] -end - -@testset "Remove a card from the bottom of the deck" begin - @test remove_card_from_bottom!([1, 3, 4, 1]) == [3, 4, 1] - @test_throws ArgumentError remove_card_from_bottom!([]) -end - -@testset "Check size of the deck" begin - @test check_deck_size([1, 3, 4, 1], 4) - @test !check_deck_size([1, 3, 4, 1, 5], 4) - @test !check_deck_size([1, 3, 4], 4) - @test check_deck_size([], 0) +@testset verbose = true "tests" begin + @testset "Retrieve a card from a deck" begin + @test card([1, 3, 4, 1], 2) == 3 + @test_throws BoundsError card([1, 3, 4, 1], 0) + end + + @testset "Exchange a card in the deck" begin + @test replace_card!([1, 3, 4, 1], 2 => 6) == [1, 6, 4, 1] + @test_throws BoundsError replace_card!([1, 3, 4, 1], 5 => 6) + end + + @testset "Insert a card at the of top the deck" begin + @test insert_card_at_top!([1, 3, 4, 1], 8) == [1, 3, 4, 1, 8] + end + + @testset "Remove a card from the deck" begin + @test remove_card!([1, 3, 4, 1], 2) == [1, 4, 1] + @test_throws BoundsError remove_card!([], 0) + @test_throws BoundsError remove_card!([], 1) + @test_throws BoundsError remove_card!([1, 3, 4, 1], 0) + @test_throws BoundsError remove_card!([1, 3, 4, 1], 5) + end + + @testset "Remove the top card from the deck" begin + @test remove_card_from_top!([1, 3, 4, 1]) == [1, 3, 4] + @test_throws ArgumentError remove_card_from_top!([]) + end + + @testset "Insert a card at the bottom of the deck" begin + @test insert_card_at_bottom!([1, 3, 4, 1], 8) == [8, 1, 3, 4, 1] + end + + @testset "Remove a card from the bottom of the deck" begin + @test remove_card_from_bottom!([1, 3, 4, 1]) == [3, 4, 1] + @test_throws ArgumentError remove_card_from_bottom!([]) + end + + @testset "Check size of the deck" begin + @test check_deck_size([1, 3, 4, 1], 4) + @test !check_deck_size([1, 3, 4, 1, 5], 4) + @test !check_deck_size([1, 3, 4], 4) + @test check_deck_size([], 0) + end end diff --git a/exercises/concept.wip/emoji-times/runtests.jl b/exercises/concept.wip/emoji-times/runtests.jl index 6f8e34ed..f495d942 100644 --- a/exercises/concept.wip/emoji-times/runtests.jl +++ b/exercises/concept.wip/emoji-times/runtests.jl @@ -2,25 +2,27 @@ using Test include("emoji-times.jl") -@testset "Addition" begin - @test 🕐 + 🕒 == 🕓 - @test 🕒 + 🕧 == 🕞 -end +@testset verbose = true "tests" begin + @testset "Addition" begin + @test 🕐 + 🕒 == 🕓 + @test 🕒 + 🕧 == 🕞 + end -@testset "Addition overflow" begin - @test 🕚 + 🕚 == 🕙 -end + @testset "Addition overflow" begin + @test 🕚 + 🕚 == 🕙 + end -@testset "Subtraction" begin - @test 🕗 - 🕔 == 🕒 - @test 🕤 - 🕞 == 🕕 -end + @testset "Subtraction" begin + @test 🕗 - 🕔 == 🕒 + @test 🕤 - 🕞 == 🕕 + end -@testset "Subtraction underflow" begin - @test 🕓 - 🕘 == 🕖 -end + @testset "Subtraction underflow" begin + @test 🕓 - 🕘 == 🕖 + end -@testset "0-element" begin - @test 🕚 + 🕛 == 🕚 - @test 🕚 - 🕛 == 🕚 + @testset "0-element" begin + @test 🕚 + 🕛 == 🕚 + @test 🕚 - 🕛 == 🕚 + end end diff --git a/exercises/concept.wip/encounters/runtests.jl b/exercises/concept.wip/encounters/runtests.jl index d292dfd6..b5b4d4c1 100644 --- a/exercises/concept.wip/encounters/runtests.jl +++ b/exercises/concept.wip/encounters/runtests.jl @@ -2,73 +2,73 @@ using Test include("encounters.jl") -@testset "type abstraction" begin - @test Dog <: Pet - @test Cat <: Pet -end - -# create some pets -buddy = Dog("Buddy") -sadie = Dog("Sadie") -minka = Cat("Minka") -felix = Cat("Felix") - -@testset "names" begin - @test name(buddy) == "Buddy" - @test name(sadie) == "Sadie" - @test name(minka) == "Minka" - @test name(felix) == "Felix" -end - -@testset "encounters" begin - @test encounter(sadie, buddy) == "Sadie meets Buddy and sniffs." - @test encounter(buddy, felix) == "Buddy meets Felix and chases." - @test encounter(minka, sadie) == "Minka meets Sadie and hisses." - @test encounter(felix, minka) == "Felix meets Minka and slinks." -end - # define a new type of Pet to test the fallback -# this belongs to the testset below but struct definitions within the local scope of testsets are not supported in Julia <1.1 +# this belongs to a testset below but struct definitions within the local scope of testsets are not supported in Julia <1.1 struct Horse <: Pet name::String end name(h::Horse) = h.name -jenny = Horse("Jenny") - -@testset "pet fallbacks" begin - @test encounter(buddy, jenny) == "Buddy meets Jenny and is cautious." - @test encounter(sadie, jenny) == "Sadie meets Jenny and is cautious." - @test encounter(minka, jenny) == "Minka meets Jenny and is cautious." - @test encounter(felix, jenny) == "Felix meets Jenny and is cautious." - - @test encounter(jenny, buddy) == "Jenny meets Buddy and is cautious." - @test encounter(jenny, sadie) == "Jenny meets Sadie and is cautious." - @test encounter(jenny, minka) == "Jenny meets Minka and is cautious." - @test encounter(jenny, felix) == "Jenny meets Felix and is cautious." -end - struct Car license_plate::String end name(c::Car) = c.license_plate +# create some pets +buddy = Dog("Buddy") +sadie = Dog("Sadie") +minka = Cat("Minka") +felix = Cat("Felix") +jenny = Horse("Jenny") car = Car("W-12345X") -@testset "non-pet fallback" begin - @test encounter(buddy, car) == "Buddy meets W-12345X and runs away." - @test encounter(minka, car) == "Minka meets W-12345X and runs away." - @test encounter(jenny, car) == "Jenny meets W-12345X and runs away." -end +@testset verbose = true "tests" begin + @testset "type abstraction" begin + @test Dog <: Pet + @test Cat <: Pet + end + + @testset "names" begin + @test name(buddy) == "Buddy" + @test name(sadie) == "Sadie" + @test name(minka) == "Minka" + @test name(felix) == "Felix" + end + + @testset "encounters" begin + @test encounter(sadie, buddy) == "Sadie meets Buddy and sniffs." + @test encounter(buddy, felix) == "Buddy meets Felix and chases." + @test encounter(minka, sadie) == "Minka meets Sadie and hisses." + @test encounter(felix, minka) == "Felix meets Minka and slinks." + end + + @testset "pet fallbacks" begin + @test encounter(buddy, jenny) == "Buddy meets Jenny and is cautious." + @test encounter(sadie, jenny) == "Sadie meets Jenny and is cautious." + @test encounter(minka, jenny) == "Minka meets Jenny and is cautious." + @test encounter(felix, jenny) == "Felix meets Jenny and is cautious." + + @test encounter(jenny, buddy) == "Jenny meets Buddy and is cautious." + @test encounter(jenny, sadie) == "Jenny meets Sadie and is cautious." + @test encounter(jenny, minka) == "Jenny meets Minka and is cautious." + @test encounter(jenny, felix) == "Jenny meets Felix and is cautious." + end + + @testset "non-pet fallback" begin + @test encounter(buddy, car) == "Buddy meets W-12345X and runs away." + @test encounter(minka, car) == "Minka meets W-12345X and runs away." + @test encounter(jenny, car) == "Jenny meets W-12345X and runs away." + end -# Test generic fallback with a random type -# In practice this would be nonsense, but here we want to ensure the student doesn't implement a specific method for a given type -typename = Symbol("RandomType", rand(UInt)) -@eval struct $typename end -@eval name(::$typename) = $(string(typename)) -@eval t = $typename() + # Test generic fallback with a random type + # In practice this would be nonsense, but here we want to ensure the student doesn't implement a specific method for a given type + typename = Symbol("RandomType", rand(UInt)) + @eval struct $typename end + @eval name(::$typename) = $(string(typename)) + @eval t = $typename() -@testset "generic fallback" begin - @test encounter(t, buddy) == "$(name(t)) meets Buddy and nothing happens." - @test encounter(buddy, t) == "Buddy meets $(name(t)) and runs away." + @testset "generic fallback" begin + @test encounter(t, buddy) == "$(name(t)) meets Buddy and nothing happens." + @test encounter(buddy, t) == "Buddy meets $(name(t)) and runs away." + end end diff --git a/exercises/concept.wip/exercism-matrix/runtests.jl b/exercises/concept.wip/exercism-matrix/runtests.jl index 5e418e33..252ce50c 100644 --- a/exercises/concept.wip/exercism-matrix/runtests.jl +++ b/exercises/concept.wip/exercism-matrix/runtests.jl @@ -2,172 +2,174 @@ using Test include("exercism-matrix.jl") -@testset "construct E" begin - @test E == [ - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; - 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; - 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - ] - @test isconst(@__MODULE__, :E) -end +@testset verbose = true "tests" begin + @testset "construct E" begin + @test E == [ + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; + 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; + 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + ] + @test isconst(@__MODULE__, :E) + end -@testset "Sadxercism" begin - @test frown(E) == [ - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; - 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; - 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; - 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - ] + @testset "Sadxercism" begin + @test frown(E) == [ + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; + 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; + 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + ] - Ẽ = copy(E) - frown!(Ẽ) - @test Ẽ == [ - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; - 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; - 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; - 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - ] + Ẽ = copy(E) + frown!(Ẽ) + @test Ẽ == [ + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; + 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; + 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + ] - @test Ẽ != E -end + @test Ẽ != E + end -@testset "rot -90° / +270°" begin - @test rot270(E) == [ - 0 0 0 0 0 1 0 0 0 0 0; - 0 1 1 1 1 0 1 1 1 1 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 0 0 1 0 0 0 0 0 0 0; - 0 0 1 0 0 0 0 0 0 0 0; - 0 0 0 1 0 0 1 0 0 0 0; - 0 0 0 0 0 0 0 1 0 0 0; - 0 0 0 0 0 0 0 0 1 0 0; - 0 0 0 0 0 0 0 0 1 0 0; - 0 0 0 0 0 0 0 1 0 0 0; - 0 0 0 1 0 0 1 0 0 0 0; - 0 0 1 0 0 0 0 0 0 0 0; - 0 0 0 1 0 0 0 0 0 0 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 1 1 1 1 0 1 1 1 1 0; - 0 0 0 0 0 1 0 0 0 0 0; - ] + @testset "rot -90° / +270°" begin + @test rot270(E) == [ + 0 0 0 0 0 1 0 0 0 0 0; + 0 1 1 1 1 0 1 1 1 1 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 0 0 1 0 0 0 0 0 0 0; + 0 0 1 0 0 0 0 0 0 0 0; + 0 0 0 1 0 0 1 0 0 0 0; + 0 0 0 0 0 0 0 1 0 0 0; + 0 0 0 0 0 0 0 0 1 0 0; + 0 0 0 0 0 0 0 0 1 0 0; + 0 0 0 0 0 0 0 1 0 0 0; + 0 0 0 1 0 0 1 0 0 0 0; + 0 0 1 0 0 0 0 0 0 0 0; + 0 0 0 1 0 0 0 0 0 0 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 1 1 1 1 0 1 1 1 1 0; + 0 0 0 0 0 1 0 0 0 0 0; + ] - @test rot270(frown(E)) == [ - 0 0 0 0 0 1 0 0 0 0 0; - 0 1 1 1 1 0 1 1 1 1 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 0 0 1 0 0 0 0 0 0 0; - 0 0 1 0 0 0 0 0 0 0 0; - 0 0 0 1 0 0 0 0 1 0 0; - 0 0 0 0 0 0 0 1 0 0 0; - 0 0 0 0 0 0 1 0 0 0 0; - 0 0 0 0 0 0 1 0 0 0 0; - 0 0 0 0 0 0 0 1 0 0 0; - 0 0 0 1 0 0 0 0 1 0 0; - 0 0 1 0 0 0 0 0 0 0 0; - 0 0 0 1 0 0 0 0 0 0 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 1 1 1 1 0 1 1 1 1 0; - 0 0 0 0 0 1 0 0 0 0 0; - ] -end + @test rot270(frown(E)) == [ + 0 0 0 0 0 1 0 0 0 0 0; + 0 1 1 1 1 0 1 1 1 1 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 0 0 1 0 0 0 0 0 0 0; + 0 0 1 0 0 0 0 0 0 0 0; + 0 0 0 1 0 0 0 0 1 0 0; + 0 0 0 0 0 0 0 1 0 0 0; + 0 0 0 0 0 0 1 0 0 0 0; + 0 0 0 0 0 0 1 0 0 0 0; + 0 0 0 0 0 0 0 1 0 0 0; + 0 0 0 1 0 0 0 0 1 0 0; + 0 0 1 0 0 0 0 0 0 0 0; + 0 0 0 1 0 0 0 0 0 0 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 1 1 1 1 0 1 1 1 1 0; + 0 0 0 0 0 1 0 0 0 0 0; + ] + end -@testset "rot +90°" begin - @test rot90(E) == [ - 0 0 0 0 0 1 0 0 0 0 0; - 0 1 1 1 1 0 1 1 1 1 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 0 0 0 0 0 0 1 0 0 0; - 0 0 0 0 0 0 0 0 1 0 0; - 0 0 0 0 1 0 0 1 0 0 0; - 0 0 0 1 0 0 0 0 0 0 0; - 0 0 1 0 0 0 0 0 0 0 0; - 0 0 1 0 0 0 0 0 0 0 0; - 0 0 0 1 0 0 0 0 0 0 0; - 0 0 0 0 1 0 0 1 0 0 0; - 0 0 0 0 0 0 0 0 1 0 0; - 0 0 0 0 0 0 0 1 0 0 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 1 1 1 1 0 1 1 1 1 0; - 0 0 0 0 0 1 0 0 0 0 0; - ] + @testset "rot +90°" begin + @test rot90(E) == [ + 0 0 0 0 0 1 0 0 0 0 0; + 0 1 1 1 1 0 1 1 1 1 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 0 0 0 0 0 0 1 0 0 0; + 0 0 0 0 0 0 0 0 1 0 0; + 0 0 0 0 1 0 0 1 0 0 0; + 0 0 0 1 0 0 0 0 0 0 0; + 0 0 1 0 0 0 0 0 0 0 0; + 0 0 1 0 0 0 0 0 0 0 0; + 0 0 0 1 0 0 0 0 0 0 0; + 0 0 0 0 1 0 0 1 0 0 0; + 0 0 0 0 0 0 0 0 1 0 0; + 0 0 0 0 0 0 0 1 0 0 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 1 1 1 1 0 1 1 1 1 0; + 0 0 0 0 0 1 0 0 0 0 0; + ] - @test rot90(frown(E)) == [ - 0 0 0 0 0 1 0 0 0 0 0; - 0 1 1 1 1 0 1 1 1 1 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 0 0 0 0 0 0 1 0 0 0; - 0 0 0 0 0 0 0 0 1 0 0; - 0 0 1 0 0 0 0 1 0 0 0; - 0 0 0 1 0 0 0 0 0 0 0; - 0 0 0 0 1 0 0 0 0 0 0; - 0 0 0 0 1 0 0 0 0 0 0; - 0 0 0 1 0 0 0 0 0 0 0; - 0 0 1 0 0 0 0 1 0 0 0; - 0 0 0 0 0 0 0 0 1 0 0; - 0 0 0 0 0 0 0 1 0 0 0; - 1 0 0 0 0 0 0 0 0 0 1; - 1 0 0 0 0 0 0 0 0 0 1; - 0 1 1 1 1 0 1 1 1 1 0; - 0 0 0 0 0 1 0 0 0 0 0; - ] -end + @test rot90(frown(E)) == [ + 0 0 0 0 0 1 0 0 0 0 0; + 0 1 1 1 1 0 1 1 1 1 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 0 0 0 0 0 0 1 0 0 0; + 0 0 0 0 0 0 0 0 1 0 0; + 0 0 1 0 0 0 0 1 0 0 0; + 0 0 0 1 0 0 0 0 0 0 0; + 0 0 0 0 1 0 0 0 0 0 0; + 0 0 0 0 1 0 0 0 0 0 0; + 0 0 0 1 0 0 0 0 0 0 0; + 0 0 1 0 0 0 0 1 0 0 0; + 0 0 0 0 0 0 0 0 1 0 0; + 0 0 0 0 0 0 0 1 0 0 0; + 1 0 0 0 0 0 0 0 0 0 1; + 1 0 0 0 0 0 0 0 0 0 1; + 0 1 1 1 1 0 1 1 1 1 0; + 0 0 0 0 0 1 0 0 0 0 0; + ] + end -@testset "stickerwall" begin - @test stickerwall(E) == [ - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; - 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; - 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; - 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; - 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1; - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; - 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; - 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; - 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; - 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; - ] + @testset "stickerwall" begin + @test stickerwall(E) == [ + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; + 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; + 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; + 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0; + 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0; + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0; + 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0; + ] + end end diff --git a/exercises/concept.wip/fibonacci-iterator/runtests.jl b/exercises/concept.wip/fibonacci-iterator/runtests.jl index ee9dc405..ac13647d 100644 --- a/exercises/concept.wip/fibonacci-iterator/runtests.jl +++ b/exercises/concept.wip/fibonacci-iterator/runtests.jl @@ -4,33 +4,35 @@ include("fibonacci.jl") const fib = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025] -@testset "Fib is defined" begin - @test isdefined(@__MODULE__, :Fib) - @test typeof(Fib(100)) == Fib -end - -@testset "Can be iterated" begin - @test [a for a in Fib(50)] == fib -end +@testset verbose = true "tests" begin + @testset "Fib is defined" begin + @test isdefined(@__MODULE__, :Fib) + @test typeof(Fib(100)) == Fib + end -@testset "Fib does not contain fields to store state internally" begin - # Backport fieldtypes for Julia 1.0 - if VERSION < v"1.1" - @eval fieldtypes(T::Type) = ntuple(i -> fieldtype(T, i), fieldcount(T)) + @testset "Can be iterated" begin + @test [a for a in Fib(50)] == fib end - # Ensure only one numeric value (n) can be stored - # This should prevent Fib types that use a tuple or struct to store more state - @test fieldcount(Fib) == 1 - @test fieldtypes(Fib)[1] <: Number -end + @testset "Fib does not contain fields to store state internally" begin + # Backport fieldtypes for Julia 1.0 + if VERSION < v"1.1" + @eval fieldtypes(T::Type) = ntuple(i -> fieldtype(T, i), fieldcount(T)) + end -@testset "Can be collected" begin - @test collect(Fib(50)) == fib - @test Base.IteratorSize(Fib) == Base.HasLength() -end + # Ensure only one numeric value (n) can be stored + # This should prevent Fib types that use a tuple or struct to store more state + @test fieldcount(Fib) == 1 + @test fieldtypes(Fib)[1] <: Number + end -@testset "Has an eltype" begin - @test typeof(collect(Fib(50))) == Vector{Int} - @test Base.IteratorEltype(Fib) == Base.HasEltype() + @testset "Can be collected" begin + @test collect(Fib(50)) == fib + @test Base.IteratorSize(Fib) == Base.HasLength() + end + + @testset "Has an eltype" begin + @test typeof(collect(Fib(50))) == Vector{Int} + @test Base.IteratorEltype(Fib) == Base.HasEltype() + end end diff --git a/exercises/concept.wip/high-score/runtests.jl b/exercises/concept.wip/high-score/runtests.jl index ba9ab828..a019496f 100644 --- a/exercises/concept.wip/high-score/runtests.jl +++ b/exercises/concept.wip/high-score/runtests.jl @@ -2,174 +2,176 @@ using Test include("high-score.jl") -@testset "Adding players" begin - @testset "Add player with score to empty score dict" begin - scores = Dict{String, Int}() - add_player!(scores, "Kalei", 233_436) - @test scores == Dict( - "Kalei" => 233_436, - ) - end - - @testset "Add two players with scores to empty score dict" begin - scores = Dict{String, Int}() - add_player!(scores, "Léna", 901_806) - add_player!(scores, "Ljuba", 302_799) - @test scores == Dict( - "Léna" => 901_806, - "Ljuba" => 302_799, - ) - end - - @testset "Add player without score to empty score dict" begin - scores = Dict{String, Int}() - add_player!(scores, "Nicolet") - @test scores == Dict( - "Nicolet" => 0, - ) - end - - @testset "Add two players without score to empty dict" begin - scores = Dict{String, Int}() - add_player!(scores, "Dina") - add_player!(scores, "Yasu") - @test scores == Dict( - "Dina" => 0, - "Yasu" => 0, - ) - end -end - -@testset "Removing players" begin - @testset "Removing a player from empty score dict results in empty score dict" begin - scores = Dict{String, Int}() - remove_player!(scores, "Waldemar") - @test isempty(scores) - end - - @testset "Removing a player after adding results in empty score dict" begin - scores = Dict{String, Int}() - add_player!(scores, "Arisha") - remove_player!(scores, "Arisha") - @test isempty(scores) - end - - @testset "Removing the first player after adding two results in dict with remaining player" begin - scores = Dict{String, Int}() - add_player!(scores, "Fritjof") - add_player!(scores, "Valèria") - remove_player!(scores, "Fritjof") - @test scores == Dict( - "Valèria" => 0, - ) - end - - @testset "Removing the second player after adding two results in dict with remaining player" begin - scores = Dict{String, Int}() - add_player!(scores, "Fritjof") - add_player!(scores, "Valèria") - remove_player!(scores, "Valèria") - @test scores == Dict( - "Fritjof" => 0, - ) - end -end - -@testset "Updating scores" begin - @testset "Updating score for non-existent player initializes value" begin - scores = Dict{String, Int}() - update_score!(scores, "Dov", 721_957) - @test scores == Dict( - "Dov" => 721_957, - ) - end - - @testset "Updating score for existing player without score replaces previous score" begin - scores = Dict( - "Sabriyya" => 0, - ) - update_score!(scores, "Sabriyya", 560_806) - @test scores == Dict( - "Sabriyya" => 560_806, - ) - end - - @testset "Updating score for existing player with score replaces previous score" begin - scores = Dict( - "Edvard" => 151_216, - ) - update_score!(scores, "Edvard", 600_259) - @test scores == Dict( - "Edvard" => 600_259, - ) - end - - @testset "Updating score for existing player in a dict with several players with score replaces player's previous score" begin - scores = Dict( - "Əli" => 977_076, - "Lisbet" => 288_100, - ) - update_score!(scores, "Lisbet", 989_376) - @test scores == Dict( - "Əli" => 977_076, - "Lisbet" => 989_376, - ) - end -end - -@testset "Resetting scores" begin - @testset "Resetting score for existing player sets score to 0" begin - scores = Dict( - "Thea" => 307_261, - ) - reset_score!(scores, "Thea") - @test scores == Dict( - "Thea" => 0, - ) - end - - @testset "Resetting score for existing player in a dict with several players sets player's score to 0" begin - scores = Dict( - "Anelia" => 307_261, - "Robert" => 785_497, - ) - reset_score!(scores, "Anelia") - @test scores == Dict( - "Anelia" => 0, - "Robert" => 785_497, - ) - end - - @testset "Resetting score for non-existent player sets player score to 0" begin - scores = Dict{String, Int}() - reset_score!(scores, "Erwin") - @test scores == Dict( - "Erwin" => 0, - ) - end -end - -@testset "List of players" begin - @testset "Score board with one entry gives one result" begin - scores = Dict( - "Rodolfito" => 820_876 - ) - @test players(scores) == ["Rodolfito"] - end - - @testset "Score board with multiple entries gives results in unknown order" begin - scores = Dict( - "Naheed" => 97_506, - "Ivona" => 837_854, - "Iztok" => 160_855, - "Sara" => 936_371, - "Udo" => 25, - ) - @test sort(players(scores)) == ["Ivona", "Iztok", "Naheed", "Sara", "Udo"] - end - - @testset "Empty score board results in empty player list" begin - scores = Dict() - @test isempty(players(scores)) +@testset verbose = true "tests" begin + @testset "Adding players" begin + @testset "Add player with score to empty score dict" begin + scores = Dict{String, Int}() + add_player!(scores, "Kalei", 233_436) + @test scores == Dict( + "Kalei" => 233_436, + ) + end + + @testset "Add two players with scores to empty score dict" begin + scores = Dict{String, Int}() + add_player!(scores, "Léna", 901_806) + add_player!(scores, "Ljuba", 302_799) + @test scores == Dict( + "Léna" => 901_806, + "Ljuba" => 302_799, + ) + end + + @testset "Add player without score to empty score dict" begin + scores = Dict{String, Int}() + add_player!(scores, "Nicolet") + @test scores == Dict( + "Nicolet" => 0, + ) + end + + @testset "Add two players without score to empty dict" begin + scores = Dict{String, Int}() + add_player!(scores, "Dina") + add_player!(scores, "Yasu") + @test scores == Dict( + "Dina" => 0, + "Yasu" => 0, + ) + end + end + + @testset "Removing players" begin + @testset "Removing a player from empty score dict results in empty score dict" begin + scores = Dict{String, Int}() + remove_player!(scores, "Waldemar") + @test isempty(scores) + end + + @testset "Removing a player after adding results in empty score dict" begin + scores = Dict{String, Int}() + add_player!(scores, "Arisha") + remove_player!(scores, "Arisha") + @test isempty(scores) + end + + @testset "Removing the first player after adding two results in dict with remaining player" begin + scores = Dict{String, Int}() + add_player!(scores, "Fritjof") + add_player!(scores, "Valèria") + remove_player!(scores, "Fritjof") + @test scores == Dict( + "Valèria" => 0, + ) + end + + @testset "Removing the second player after adding two results in dict with remaining player" begin + scores = Dict{String, Int}() + add_player!(scores, "Fritjof") + add_player!(scores, "Valèria") + remove_player!(scores, "Valèria") + @test scores == Dict( + "Fritjof" => 0, + ) + end + end + + @testset "Updating scores" begin + @testset "Updating score for non-existent player initializes value" begin + scores = Dict{String, Int}() + update_score!(scores, "Dov", 721_957) + @test scores == Dict( + "Dov" => 721_957, + ) + end + + @testset "Updating score for existing player without score replaces previous score" begin + scores = Dict( + "Sabriyya" => 0, + ) + update_score!(scores, "Sabriyya", 560_806) + @test scores == Dict( + "Sabriyya" => 560_806, + ) + end + + @testset "Updating score for existing player with score replaces previous score" begin + scores = Dict( + "Edvard" => 151_216, + ) + update_score!(scores, "Edvard", 600_259) + @test scores == Dict( + "Edvard" => 600_259, + ) + end + + @testset "Updating score for existing player in a dict with several players with score replaces player's previous score" begin + scores = Dict( + "Əli" => 977_076, + "Lisbet" => 288_100, + ) + update_score!(scores, "Lisbet", 989_376) + @test scores == Dict( + "Əli" => 977_076, + "Lisbet" => 989_376, + ) + end + end + + @testset "Resetting scores" begin + @testset "Resetting score for existing player sets score to 0" begin + scores = Dict( + "Thea" => 307_261, + ) + reset_score!(scores, "Thea") + @test scores == Dict( + "Thea" => 0, + ) + end + + @testset "Resetting score for existing player in a dict with several players sets player's score to 0" begin + scores = Dict( + "Anelia" => 307_261, + "Robert" => 785_497, + ) + reset_score!(scores, "Anelia") + @test scores == Dict( + "Anelia" => 0, + "Robert" => 785_497, + ) + end + + @testset "Resetting score for non-existent player sets player score to 0" begin + scores = Dict{String, Int}() + reset_score!(scores, "Erwin") + @test scores == Dict( + "Erwin" => 0, + ) + end + end + + @testset "List of players" begin + @testset "Score board with one entry gives one result" begin + scores = Dict( + "Rodolfito" => 820_876 + ) + @test players(scores) == ["Rodolfito"] + end + + @testset "Score board with multiple entries gives results in unknown order" begin + scores = Dict( + "Naheed" => 97_506, + "Ivona" => 837_854, + "Iztok" => 160_855, + "Sara" => 936_371, + "Udo" => 25, + ) + @test sort(players(scores)) == ["Ivona", "Iztok", "Naheed", "Sara", "Udo"] + end + + @testset "Empty score board results in empty player list" begin + scores = Dict() + @test isempty(players(scores)) + end end end diff --git a/exercises/concept.wip/leap/runtests.jl b/exercises/concept.wip/leap/runtests.jl index f1f1b6b3..513137ef 100644 --- a/exercises/concept.wip/leap/runtests.jl +++ b/exercises/concept.wip/leap/runtests.jl @@ -2,38 +2,40 @@ using Test include("leap.jl") -@testset "year not divisible by 4 in common year" begin - @test !isleapyear(2015) -end - -@testset "year divisible by 2, not divisible by 4 in common year" begin - @test !isleapyear(1970) -end - -@testset "year divisible by 4, not divisible by 100 in leap year" begin - @test isleapyear(1996) -end - -@testset "year divisible by 4 and 5 is still a leap year" begin - @test isleapyear(1960) -end - -@testset "year divisible by 100, not divisible by 400 in common year" begin - @test !isleapyear(2100) -end - -@testset "year divisible by 100 but not by 3 is still not a leap year" begin - @test !isleapyear(1900) -end - -@testset "year divisible by 400 in leap year" begin - @test isleapyear(2000) -end - -@testset "year divisible by 400 but not by 125 is still a leap year" begin - @test isleapyear(2400) -end - -@testset "year divisible by 200, not divisible by 400 in common year" begin - @test !isleapyear(1800) +@testset verbose = true "tests" begin + @testset "year not divisible by 4 in common year" begin + @test !isleapyear(2015) + end + + @testset "year divisible by 2, not divisible by 4 in common year" begin + @test !isleapyear(1970) + end + + @testset "year divisible by 4, not divisible by 100 in leap year" begin + @test isleapyear(1996) + end + + @testset "year divisible by 4 and 5 is still a leap year" begin + @test isleapyear(1960) + end + + @testset "year divisible by 100, not divisible by 400 in common year" begin + @test !isleapyear(2100) + end + + @testset "year divisible by 100 but not by 3 is still not a leap year" begin + @test !isleapyear(1900) + end + + @testset "year divisible by 400 in leap year" begin + @test isleapyear(2000) + end + + @testset "year divisible by 400 but not by 125 is still a leap year" begin + @test isleapyear(2400) + end + + @testset "year divisible by 200, not divisible by 400 in common year" begin + @test !isleapyear(1800) + end end diff --git a/exercises/concept.wip/name-badge/runtests.jl b/exercises/concept.wip/name-badge/runtests.jl index f5e852ba..4cb77dfd 100644 --- a/exercises/concept.wip/name-badge/runtests.jl +++ b/exercises/concept.wip/name-badge/runtests.jl @@ -2,22 +2,24 @@ using Test include("namebadge.jl") -@testset "Full data" begin - @test badge(455, "Mary M. Brown", "MARKETING") == "[455] - Mary M. Brown - MARKETING" -end +@testset verbose = true "tests" begin + @testset "Full data" begin + @test badge(455, "Mary M. Brown", "MARKETING") == "[455] - Mary M. Brown - MARKETING" + end -@testset "Full data with mixed case department" begin - @test badge(7, "Eneus", "Wizardry & Witchcraft") == "[7] - Eneus - WIZARDRY & WITCHCRAFT" -end + @testset "Full data with mixed case department" begin + @test badge(7, "Eneus", "Wizardry & Witchcraft") == "[7] - Eneus - WIZARDRY & WITCHCRAFT" + end -@testset "No ID" begin - @test badge(nothing, "Amália Valéria Kóbor", "Security") == "Amália Valéria Kóbor - SECURITY" -end + @testset "No ID" begin + @test badge(nothing, "Amália Valéria Kóbor", "Security") == "Amália Valéria Kóbor - SECURITY" + end -@testset "Owner's Badge" begin - @test badge(1, "Anna Johnson", nothing) == "[1] - Anna Johnson - OWNER" -end + @testset "Owner's Badge" begin + @test badge(1, "Anna Johnson", nothing) == "[1] - Anna Johnson - OWNER" + end -@testset "Owner's Badge without ID" begin - @test badge(nothing, "Elvira McFee", nothing) == "Elvira McFee - OWNER" + @testset "Owner's Badge without ID" begin + @test badge(nothing, "Elvira McFee", nothing) == "Elvira McFee - OWNER" + end end diff --git a/exercises/concept.wip/stage-heralding/runtests.jl b/exercises/concept.wip/stage-heralding/runtests.jl index 65e91f99..85be6ac4 100644 --- a/exercises/concept.wip/stage-heralding/runtests.jl +++ b/exercises/concept.wip/stage-heralding/runtests.jl @@ -2,52 +2,54 @@ using Test include("card-generator.jl") -@testset "Speedrunning 101" begin - @test generate_card("»Speedrunning 101« – Sasha Duda Krall (they/them), from GDQU. Start: 13:00, Q&A: 13:20, End: 13:30") == """ - - Our next speaker is Sasha Duda Krall, from GDQU - - Their talk is called »Speedrunning 101« - - They will answer your questions in the Q&A session at the end of the talk, starting at 13:20 - - 13:00 - 13:20 - 13:30 - """ -end +@testset verbose = true "tests" begin + @testset "Speedrunning 101" begin + @test generate_card("»Speedrunning 101« – Sasha Duda Krall (they/them), from GDQU. Start: 13:00, Q&A: 13:20, End: 13:30") == """ + - Our next speaker is Sasha Duda Krall, from GDQU + - Their talk is called »Speedrunning 101« + - They will answer your questions in the Q&A session at the end of the talk, starting at 13:20 + + 13:00 - 13:20 - 13:30 + """ + end -@testset "How I learned to say Farewell" begin - @test generate_card("»How I learned to say Farewell« – Madeline (she/her). Start: 13:40, Q&A: 14:00, End: 14:05") == """ - - Our next speaker is Madeline - - Her talk is called »How I learned to say Farewell« - - She will answer your questions in the Q&A session at the end of the talk, starting at 14:00 - - 13:40 - 14:00 - 14:05 - """ -end + @testset "How I learned to say Farewell" begin + @test generate_card("»How I learned to say Farewell« – Madeline (she/her). Start: 13:40, Q&A: 14:00, End: 14:05") == """ + - Our next speaker is Madeline + - Her talk is called »How I learned to say Farewell« + - She will answer your questions in the Q&A session at the end of the talk, starting at 14:00 + + 13:40 - 14:00 - 14:05 + """ + end -@testset "How To Find a Good Title For Your Conference Talk" begin - @test generate_card("»How To Find a Good Title For Your Conference Talk« – Vítězslav Kruse (he/him). Start: 14:15, End: 14:40") == """ - - Our next speaker is Vítězslav Kruse - - His talk is called »How To Find a Good Title For Your Conference Talk« - - There will not be a Q&A session - - 14:15 - NO Q&A - 14:40 - """ -end + @testset "How To Find a Good Title For Your Conference Talk" begin + @test generate_card("»How To Find a Good Title For Your Conference Talk« – Vítězslav Kruse (he/him). Start: 14:15, End: 14:40") == """ + - Our next speaker is Vítězslav Kruse + - His talk is called »How To Find a Good Title For Your Conference Talk« + - There will not be a Q&A session + + 14:15 - NO Q&A - 14:40 + """ + end -@testset "Why Emoji Matter❣" begin - @test generate_card("»Why Emoji Matter❣« – Ash van Amelsvoort, from the University of 🧬🧪⚛. Start: 14:50, Q&A: 15:05, End: 15:10") == """ - - Our next speaker is Ash van Amelsvoort, from the University of 🧬🧪⚛ - - Ash's talk is called »Why Emoji Matter❣« - - Ash will answer your questions in the Q&A session at the end of the talk, starting at 15:05 - - 14:50 - 15:05 - 15:10 - """ -end + @testset "Why Emoji Matter❣" begin + @test generate_card("»Why Emoji Matter❣« – Ash van Amelsvoort, from the University of 🧬🧪⚛. Start: 14:50, Q&A: 15:05, End: 15:10") == """ + - Our next speaker is Ash van Amelsvoort, from the University of 🧬🧪⚛ + - Ash's talk is called »Why Emoji Matter❣« + - Ash will answer your questions in the Q&A session at the end of the talk, starting at 15:05 + + 14:50 - 15:05 - 15:10 + """ + end -@testset "»Can dogs look up?" begin - @test generate_card("»Can dogs look up?« – Kira \"k1ralli\" Sørensen. Start: 20:50, Q&A: 21:05, End: 21:10") == """ - - Our next speaker is Kira "k1ralli" Sørensen - - Kira's talk is called »Can dogs look up?« - - Kira will answer your questions in the Q&A session at the end of the talk, starting at 21:05 - - 20:50 - 21:05 - 21:10 - """ + @testset "»Can dogs look up?" begin + @test generate_card("»Can dogs look up?« – Kira \"k1ralli\" Sørensen. Start: 20:50, Q&A: 21:05, End: 21:10") == """ + - Our next speaker is Kira "k1ralli" Sørensen + - Kira's talk is called »Can dogs look up?« + - Kira will answer your questions in the Q&A session at the end of the talk, starting at 21:05 + + 20:50 - 21:05 - 21:10 + """ + end end diff --git a/exercises/concept.wip/tech-palace/runtests.jl b/exercises/concept.wip/tech-palace/runtests.jl index 7ff3b0dc..55bd8a44 100644 --- a/exercises/concept.wip/tech-palace/runtests.jl +++ b/exercises/concept.wip/tech-palace/runtests.jl @@ -2,48 +2,50 @@ using Test include("welcome.jl") -@testset "1. Create the welcome message" begin - @testset "Welcome message for customer with first letter capitalized" begin - @test welcome("Formora") == "Welcome to the Tech Palace, FORMORA" - end +@testset verbose = true "tests" begin + @testset "1. Create the welcome message" begin + @testset "Welcome message for customer with first letter capitalized" begin + @test welcome("Formora") == "Welcome to the Tech Palace, FORMORA" + end - @testset "Welcome message for customer with only lowercase letters" begin - @test welcome("oromis") == "Welcome to the Tech Palace, OROMIS" - end + @testset "Welcome message for customer with only lowercase letters" begin + @test welcome("oromis") == "Welcome to the Tech Palace, OROMIS" + end - @testset "Welcome message for customer with dash in name" begin - @test welcome("Svit-kona") == "Welcome to the Tech Palace, SVIT-KONA" - end + @testset "Welcome message for customer with dash in name" begin + @test welcome("Svit-kona") == "Welcome to the Tech Palace, SVIT-KONA" + end - @testset "Welcome message for customer with only uppercase letters" begin - @test welcome("ARVA") == "Welcome to the Tech Palace, ARVA" - end + @testset "Welcome message for customer with only uppercase letters" begin + @test welcome("ARVA") == "Welcome to the Tech Palace, ARVA" + end - @testset "Welcome message for customer with non-latin letters" begin - @test welcome("Andumë") == "Welcome to the Tech Palace, ANDUMË" + @testset "Welcome message for customer with non-latin letters" begin + @test welcome("Andumë") == "Welcome to the Tech Palace, ANDUMË" + end end -end -@testset "2. Add a fancy border" begin - @testset "Add border with 10 stars per line" begin - @test add_border("Welcome!", 10) == "**********\nWelcome!\n**********" - end + @testset "2. Add a fancy border" begin + @testset "Add border with 10 stars per line" begin + @test add_border("Welcome!", 10) == "**********\nWelcome!\n**********" + end - @testset "Add border with 2 stars per line" begin - @test add_border("Hi", 2) == "**\nHi\n**" + @testset "Add border with 2 stars per line" begin + @test add_border("Hi", 2) == "**\nHi\n**" + end end -end -@testset "3. Clean up old marketing messages" begin - @testset "Cleanup message with leading whitespace" begin - @test clean(" DISCOUNT") == "DISCOUNT" - end + @testset "3. Clean up old marketing messages" begin + @testset "Cleanup message with leading whitespace" begin + @test clean(" DISCOUNT") == "DISCOUNT" + end - @testset "Cleanup message with trailing whitespace" begin - @test clean("SALE ") == "SALE" - end + @testset "Cleanup message with trailing whitespace" begin + @test clean("SALE ") == "SALE" + end - @testset "Cleanup message with leading and trailing whitespace" begin - @test clean(" BUY NOW, SAVE 10% ") == "BUY NOW, SAVE 10%" + @testset "Cleanup message with leading and trailing whitespace" begin + @test clean(" BUY NOW, SAVE 10% ") == "BUY NOW, SAVE 10%" + end end end diff --git a/exercises/concept.wip/vehicle-purchase/runtests.jl b/exercises/concept.wip/vehicle-purchase/runtests.jl index ec92e682..814a2a4e 100644 --- a/exercises/concept.wip/vehicle-purchase/runtests.jl +++ b/exercises/concept.wip/vehicle-purchase/runtests.jl @@ -2,20 +2,22 @@ using Test include("vehicle-purchase.jl") -@testset "Affordability" begin - @test canibuy("1974 Ford Pinto", 516, 100) == "Yes! I'm getting a 1974 Ford Pinto." - @test canibuy("2014 Bugatti Veyron", 562_500, 5000) == "Damn! No 2014 Bugatti Veyron for me." - @test canibuy("2020 Gazelle Medeo", 3000, 50) == "I'll have to be frugal if I want a 2020 Gazelle Medeo." -end +@testset verbose = true "tests" begin + @testset "Affordability" begin + @test canibuy("1974 Ford Pinto", 516, 100) == "Yes! I'm getting a 1974 Ford Pinto." + @test canibuy("2014 Bugatti Veyron", 562_500, 5000) == "Damn! No 2014 Bugatti Veyron for me." + @test canibuy("2020 Gazelle Medeo", 3000, 50) == "I'll have to be frugal if I want a 2020 Gazelle Medeo." + end -@testset "Licence" begin - @test licence("2014 Bugatti Veyron", "car") == "The 2014 Bugatti Veyron requires a licence to operate." - @test licence("2020 Gazelle Medeo", "bike") == "The 2020 Gazelle Medeo requires no licence to operate." -end + @testset "Licence" begin + @test licence("2014 Bugatti Veyron", "car") == "The 2014 Bugatti Veyron requires a licence to operate." + @test licence("2020 Gazelle Medeo", "bike") == "The 2020 Gazelle Medeo requires no licence to operate." + end -@testset "Registration Fees" begin - @test fee( 562_500, 6, "car") == 2250 - @test fee( 25_000, 3, "car") == 175 - @test fee( 34_000, 30, "car") == 25 - @test fee( 3_000, 0, "bike") == 0 + @testset "Registration Fees" begin + @test fee( 562_500, 6, "car") == 2250 + @test fee( 25_000, 3, "car") == 175 + @test fee( 34_000, 30, "car") == 25 + @test fee( 3_000, 0, "bike") == 0 + end end diff --git a/exercises/concept/lasagna/runtests.jl b/exercises/concept/lasagna/runtests.jl index 0b9ead76..25b92a26 100644 --- a/exercises/concept/lasagna/runtests.jl +++ b/exercises/concept/lasagna/runtests.jl @@ -2,18 +2,20 @@ using Test include("lasagna.jl") -@testset "preparation time" begin - @test preptime(2) == 4 - @test preptime(3) == 6 - @test preptime(8) == 16 -end +@testset verbose = true "tests" begin + @testset "preparation time" begin + @test preptime(2) == 4 + @test preptime(3) == 6 + @test preptime(8) == 16 + end -@testset "remaining time" begin - @test remaining_time(30) == 30 - @test remaining_time(50) == 10 - @test remaining_time(60) == 0 -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 + @testset "total working time" begin + @test total_working_time(3, 20) == 26 + end end diff --git a/exercises/practice/accumulate/runtests.jl b/exercises/practice/accumulate/runtests.jl index eadffd0f..cbaecc3f 100644 --- a/exercises/practice/accumulate/runtests.jl +++ b/exercises/practice/accumulate/runtests.jl @@ -2,26 +2,28 @@ using Test include("accumulate.jl") -@testset "multiply" begin - @test accumulate(collect(1:10), *) == [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] -end +@testset verbose = true "tests" begin + @testset "multiply" begin + @test accumulate(collect(1:10), *) == [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] + end -@testset "divide" begin - @test accumulate(collect(1:10), /) == [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] -end + @testset "divide" begin + @test accumulate(collect(1:10), /) == [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + end -@testset "subtract" begin - @test accumulate(collect(1:10), -) == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -end + @testset "subtract" begin + @test accumulate(collect(1:10), -) == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + end -@testset "add" begin - @test accumulate(collect(1:10), +) == [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] -end + @testset "add" begin + @test accumulate(collect(1:10), +) == [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + end -@testset "mod" begin - @test accumulate(collect(1:10), %) == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -end + @testset "mod" begin + @test accumulate(collect(1:10), %) == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + end -@testset "square" begin - @test accumulate(collect(1:10), ^) == [1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489, 10000000000] + @testset "square" begin + @test accumulate(collect(1:10), ^) == [1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489, 10000000000] + end end diff --git a/exercises/practice/acronym/.docs/instructions.md b/exercises/practice/acronym/.docs/instructions.md index e0515b4d..133bd2cb 100644 --- a/exercises/practice/acronym/.docs/instructions.md +++ b/exercises/practice/acronym/.docs/instructions.md @@ -4,5 +4,14 @@ Convert a phrase to its acronym. Techies love their TLA (Three Letter Acronyms)! -Help generate some jargon by writing a program that converts a long name -like Portable Network Graphics to its acronym (PNG). +Help generate some jargon by writing a program that converts a long name like Portable Network Graphics to its acronym (PNG). + +Punctuation is handled as follows: hyphens are word separators (like whitespace); all other punctuation can be removed from the input. + +For example: + +| Input | Output | +| ------------------------- | ------ | +| As Soon As Possible | ASAP | +| Liquid-crystal display | LCD | +| Thank George It's Friday! | TGIF | diff --git a/exercises/practice/acronym/.meta/config.json b/exercises/practice/acronym/.meta/config.json index a8d1bbac..0078069d 100644 --- a/exercises/practice/acronym/.meta/config.json +++ b/exercises/practice/acronym/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Convert a long phrase to its acronym", + "blurb": "Convert a long phrase to its acronym.", "authors": [ "PseudoCodeNerd" ], diff --git a/exercises/practice/acronym/runtests.jl b/exercises/practice/acronym/runtests.jl index 68d01e56..05ca80aa 100644 --- a/exercises/practice/acronym/runtests.jl +++ b/exercises/practice/acronym/runtests.jl @@ -2,39 +2,40 @@ using Test include("acronym.jl") - -@testset "basic" begin - @test acronym("Portable Network Graphics") == "PNG" -end - -@testset "lowercase words" begin - @test acronym("Ruby on Rails") == "ROR" -end - -@testset "punctuation" begin - @test acronym("First In, First Out") == "FIFO" -end - -@testset "all caps word" begin - @test acronym("GNU Image Manipulation Program") == "GIMP" -end - -@testset "punctuation without whitespace" begin - @test acronym("Complementary metal-oxide semiconductor") == "CMOS" -end - -@testset "very long abbreviation" begin - @test acronym("Rolling On The Floor Laughing So Hard That My Dogs Came Over And Licked Me") == "ROTFLSHTMDCOALM" -end - -@testset "consecutive delimiters" begin - @test acronym("Something - I made up from thin air") == "SIMUFTA" -end - -@testset "apostrophes" begin - @test acronym("Halley's Comet") == "HC" -end - -@testset "underscore emphasis" begin - @test acronym("The Road _Not_ Taken") == "TRNT" +@testset verbose = true "tests" begin + @testset "basic" begin + @test acronym("Portable Network Graphics") == "PNG" + end + + @testset "lowercase words" begin + @test acronym("Ruby on Rails") == "ROR" + end + + @testset "punctuation" begin + @test acronym("First In, First Out") == "FIFO" + end + + @testset "all caps word" begin + @test acronym("GNU Image Manipulation Program") == "GIMP" + end + + @testset "punctuation without whitespace" begin + @test acronym("Complementary metal-oxide semiconductor") == "CMOS" + end + + @testset "very long abbreviation" begin + @test acronym("Rolling On The Floor Laughing So Hard That My Dogs Came Over And Licked Me") == "ROTFLSHTMDCOALM" + end + + @testset "consecutive delimiters" begin + @test acronym("Something - I made up from thin air") == "SIMUFTA" + end + + @testset "apostrophes" begin + @test acronym("Halley's Comet") == "HC" + end + + @testset "underscore emphasis" begin + @test acronym("The Road _Not_ Taken") == "TRNT" + end end diff --git a/exercises/practice/all-your-base/.docs/instructions.md b/exercises/practice/all-your-base/.docs/instructions.md index c39686f2..1b688b69 100644 --- a/exercises/practice/all-your-base/.docs/instructions.md +++ b/exercises/practice/all-your-base/.docs/instructions.md @@ -1,32 +1,28 @@ # Instructions -Convert a number, represented as a sequence of digits in one base, to any other base. +Convert a sequence of digits in one base, representing a number, into a sequence of digits in another base, representing the same number. -Implement general base conversion. Given a number in base **a**, -represented as a sequence of digits, convert it to base **b**. +~~~~exercism/note +Try to implement the conversion yourself. +Do not use something else to perform the conversion for you. +~~~~ -## Note +## About [Positional Notation][positional-notation] -- Try to implement the conversion yourself. - Do not use something else to perform the conversion for you. +In positional notation, a number in base **b** can be understood as a linear combination of powers of **b**. -## About [Positional Notation](https://en.wikipedia.org/wiki/Positional_notation) +The number 42, _in base 10_, means: -In positional notation, a number in base **b** can be understood as a linear -combination of powers of **b**. +`(4 × 10¹) + (2 × 10⁰)` -The number 42, *in base 10*, means: +The number 101010, _in base 2_, means: -(4 * 10^1) + (2 * 10^0) +`(1 × 2⁵) + (0 × 2⁴) + (1 × 2³) + (0 × 2²) + (1 × 2¹) + (0 × 2⁰)` -The number 101010, *in base 2*, means: +The number 1120, _in base 3_, means: -(1 * 2^5) + (0 * 2^4) + (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0) +`(1 × 3³) + (1 × 3²) + (2 × 3¹) + (0 × 3⁰)` -The number 1120, *in base 3*, means: +_Yes. Those three numbers above are exactly the same. Congratulations!_ -(1 * 3^3) + (1 * 3^2) + (2 * 3^1) + (0 * 3^0) - -I think you got the idea! - -*Yes. Those three numbers above are exactly the same. Congratulations!* +[positional-notation]: https://en.wikipedia.org/wiki/Positional_notation diff --git a/exercises/practice/all-your-base/.docs/introduction.md b/exercises/practice/all-your-base/.docs/introduction.md new file mode 100644 index 00000000..68aaffbe --- /dev/null +++ b/exercises/practice/all-your-base/.docs/introduction.md @@ -0,0 +1,8 @@ +# Introduction + +You've just been hired as professor of mathematics. +Your first week went well, but something is off in your second week. +The problem is that every answer given by your students is wrong! +Luckily, your math skills have allowed you to identify the problem: the student answers _are_ correct, but they're all in base 2 (binary)! +Amazingly, it turns out that each week, the students use a different base. +To help you quickly verify the student answers, you'll be building a tool to translate between bases. diff --git a/exercises/practice/all-your-base/runtests.jl b/exercises/practice/all-your-base/runtests.jl index 01580df0..e53dd849 100644 --- a/exercises/practice/all-your-base/runtests.jl +++ b/exercises/practice/all-your-base/runtests.jl @@ -2,86 +2,88 @@ using Test include("all-your-base.jl") -@testset "single bit one to decimal" begin - @test all_your_base([1], 2, 10) == [1] -end - -@testset "binary to single decimal" begin - @test all_your_base([1, 0, 1], 2, 10) == [5] -end - -@testset "single decimal to binary" begin - @test all_your_base([5], 10, 2) == [1, 0, 1] -end - -@testset "binary to multiple decimal" begin - @test all_your_base([1, 0, 1, 0, 1, 0], 2, 10) == [4, 2] -end - -@testset "decimal to binary" begin - @test all_your_base([4, 2], 10, 2) == [1, 0, 1, 0, 1, 0] -end - -@testset "trinary to hexadecimal" begin - @test all_your_base([1, 1, 2, 0], 3, 16) == [2, 10] -end - -@testset "hexadecimal to trinary" begin - @test all_your_base([2, 10], 16, 3) == [1, 1, 2, 0] -end - -@testset "15-bit integer" begin - @test all_your_base([3, 46, 60], 97, 73) == [6, 10, 45] -end - -@testset "empty list" begin - @test all_your_base([], 2, 10) == [0] -end - -@testset "single zero" begin - @test all_your_base([0], 10, 2) == [0] -end - -@testset "multiple zeros" begin - @test all_your_base([0, 0, 0], 10, 2) == [0] -end - -@testset "leading zeros" begin - @test all_your_base([0, 6, 0], 7, 10) == [4, 2] -end - -@testset "input base is one" begin - @test_throws DomainError all_your_base([0], 1, 10) -end - -@testset "input base is zero" begin - @test_throws DomainError all_your_base([], 0, 10) -end - -@testset "input base is negative" begin - @test_throws DomainError all_your_base([1], -2, 10) -end - -@testset "negative digit" begin - @test_throws DomainError all_your_base([1, -1, 1, 0, 1, 0], 2, 10) -end - -@testset "invalid positive digit" begin - @test_throws DomainError all_your_base([1, 2, 1, 0, 1, 0], 2, 10) -end - -@testset "output base is one" begin - @test_throws DomainError all_your_base([1, 0, 1, 0, 1, 0], 2, 1) -end - -@testset "output base is zero" begin - @test_throws DomainError all_your_base([7], 10, 0) -end - -@testset "output base is negative" begin - @test_throws DomainError all_your_base([1], 2, -7) -end - -@testset "both bases are negative" begin - @test_throws DomainError all_your_base([1], -2, -7) +@testset verbose = true "tests" begin + @testset "single bit one to decimal" begin + @test all_your_base([1], 2, 10) == [1] + end + + @testset "binary to single decimal" begin + @test all_your_base([1, 0, 1], 2, 10) == [5] + end + + @testset "single decimal to binary" begin + @test all_your_base([5], 10, 2) == [1, 0, 1] + end + + @testset "binary to multiple decimal" begin + @test all_your_base([1, 0, 1, 0, 1, 0], 2, 10) == [4, 2] + end + + @testset "decimal to binary" begin + @test all_your_base([4, 2], 10, 2) == [1, 0, 1, 0, 1, 0] + end + + @testset "trinary to hexadecimal" begin + @test all_your_base([1, 1, 2, 0], 3, 16) == [2, 10] + end + + @testset "hexadecimal to trinary" begin + @test all_your_base([2, 10], 16, 3) == [1, 1, 2, 0] + end + + @testset "15-bit integer" begin + @test all_your_base([3, 46, 60], 97, 73) == [6, 10, 45] + end + + @testset "empty list" begin + @test all_your_base([], 2, 10) == [0] + end + + @testset "single zero" begin + @test all_your_base([0], 10, 2) == [0] + end + + @testset "multiple zeros" begin + @test all_your_base([0, 0, 0], 10, 2) == [0] + end + + @testset "leading zeros" begin + @test all_your_base([0, 6, 0], 7, 10) == [4, 2] + end + + @testset "input base is one" begin + @test_throws DomainError all_your_base([0], 1, 10) + end + + @testset "input base is zero" begin + @test_throws DomainError all_your_base([], 0, 10) + end + + @testset "input base is negative" begin + @test_throws DomainError all_your_base([1], -2, 10) + end + + @testset "negative digit" begin + @test_throws DomainError all_your_base([1, -1, 1, 0, 1, 0], 2, 10) + end + + @testset "invalid positive digit" begin + @test_throws DomainError all_your_base([1, 2, 1, 0, 1, 0], 2, 10) + end + + @testset "output base is one" begin + @test_throws DomainError all_your_base([1, 0, 1, 0, 1, 0], 2, 1) + end + + @testset "output base is zero" begin + @test_throws DomainError all_your_base([7], 10, 0) + end + + @testset "output base is negative" begin + @test_throws DomainError all_your_base([1], 2, -7) + end + + @testset "both bases are negative" begin + @test_throws DomainError all_your_base([1], -2, -7) + end end diff --git a/exercises/practice/allergies/.docs/instructions.md b/exercises/practice/allergies/.docs/instructions.md index b8bbd5a3..daf8cfde 100644 --- a/exercises/practice/allergies/.docs/instructions.md +++ b/exercises/practice/allergies/.docs/instructions.md @@ -2,20 +2,18 @@ Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies. -An allergy test produces a single numeric score which contains the -information about all the allergies the person has (that they were -tested for). +An allergy test produces a single numeric score which contains the information about all the allergies the person has (that they were tested for). The list of items (and their value) that were tested are: -* eggs (1) -* peanuts (2) -* shellfish (4) -* strawberries (8) -* tomatoes (16) -* chocolate (32) -* pollen (64) -* cats (128) +- eggs (1) +- peanuts (2) +- shellfish (4) +- strawberries (8) +- tomatoes (16) +- chocolate (32) +- pollen (64) +- cats (128) So if Tom is allergic to peanuts and chocolate, he gets a score of 34. @@ -24,7 +22,6 @@ Now, given just that score of 34, your program should be able to say: - Whether Tom is allergic to any one of those allergens listed above. - All the allergens Tom is allergic to. -Note: a given score may include allergens **not** listed above (i.e. -allergens that score 256, 512, 1024, etc.). Your program should -ignore those components of the score. For example, if the allergy -score is 257, your program should only report the eggs (1) allergy. +Note: a given score may include allergens **not** listed above (i.e. allergens that score 256, 512, 1024, etc.). +Your program should ignore those components of the score. +For example, if the allergy score is 257, your program should only report the eggs (1) allergy. diff --git a/exercises/practice/allergies/.meta/config.json b/exercises/practice/allergies/.meta/config.json index 731a610d..03e83668 100644 --- a/exercises/practice/allergies/.meta/config.json +++ b/exercises/practice/allergies/.meta/config.json @@ -18,6 +18,6 @@ ".meta/example.jl" ] }, - "source": "Jumpstart Lab Warm-up", - "source_url": "http://jumpstartlab.com" + "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", + "source_url": "https://turing.edu" } diff --git a/exercises/practice/allergies/runtests.jl b/exercises/practice/allergies/runtests.jl index f314ae76..285a3fcb 100644 --- a/exercises/practice/allergies/runtests.jl +++ b/exercises/practice/allergies/runtests.jl @@ -2,86 +2,88 @@ using Test include("allergies.jl") -#canonical data -@testset "testing for single allergies" begin - @testset "testing for eggs allergy" begin - @test !allergic_to(0, "eggs") - @test allergic_to(1, "eggs") - @test allergic_to(3, "eggs") - @test !allergic_to(2, "eggs") - @test allergic_to(255, "eggs") - end +@testset verbose = true "tests" begin + #canonical data + @testset "testing for single allergies" begin + @testset "testing for eggs allergy" begin + @test !allergic_to(0, "eggs") + @test allergic_to(1, "eggs") + @test allergic_to(3, "eggs") + @test !allergic_to(2, "eggs") + @test allergic_to(255, "eggs") + end - @testset "testing for peanuts allergy" begin - @test !allergic_to(0, "peanuts") - @test allergic_to(2, "peanuts") - @test allergic_to(7, "peanuts") - @test !allergic_to(5, "peanuts") - @test allergic_to(255, "peanuts") - end + @testset "testing for peanuts allergy" begin + @test !allergic_to(0, "peanuts") + @test allergic_to(2, "peanuts") + @test allergic_to(7, "peanuts") + @test !allergic_to(5, "peanuts") + @test allergic_to(255, "peanuts") + end - @testset "testing for shellfish allergy" begin - @test !allergic_to(0, "shellfish") - @test allergic_to(4, "shellfish") - @test allergic_to(14, "shellfish") - @test !allergic_to(10, "shellfish") - @test allergic_to(255, "shellfish") - end + @testset "testing for shellfish allergy" begin + @test !allergic_to(0, "shellfish") + @test allergic_to(4, "shellfish") + @test allergic_to(14, "shellfish") + @test !allergic_to(10, "shellfish") + @test allergic_to(255, "shellfish") + end - @testset "testing for strawberries allergy" begin - @test !allergic_to(0, "strawberries") - @test allergic_to(8, "strawberries") - @test allergic_to(28, "strawberries") - @test !allergic_to(20, "strawberries") - @test allergic_to(255, "strawberries") - end + @testset "testing for strawberries allergy" begin + @test !allergic_to(0, "strawberries") + @test allergic_to(8, "strawberries") + @test allergic_to(28, "strawberries") + @test !allergic_to(20, "strawberries") + @test allergic_to(255, "strawberries") + end - @testset "testing for tomatoes allergy" begin - @test !allergic_to(0, "tomatoes") - @test allergic_to(16, "tomatoes") - @test allergic_to(56, "tomatoes") - @test !allergic_to(40, "tomatoes") - @test allergic_to(255, "tomatoes") - end + @testset "testing for tomatoes allergy" begin + @test !allergic_to(0, "tomatoes") + @test allergic_to(16, "tomatoes") + @test allergic_to(56, "tomatoes") + @test !allergic_to(40, "tomatoes") + @test allergic_to(255, "tomatoes") + end - @testset "testing for chocolate allergy" begin - @test !allergic_to(0, "chocolate") - @test allergic_to(32, "chocolate") - @test allergic_to(112, "chocolate") - @test !allergic_to(80, "chocolate") - @test allergic_to(255, "chocolate") - end + @testset "testing for chocolate allergy" begin + @test !allergic_to(0, "chocolate") + @test allergic_to(32, "chocolate") + @test allergic_to(112, "chocolate") + @test !allergic_to(80, "chocolate") + @test allergic_to(255, "chocolate") + end - @testset "testing for pollen allergy" begin - @test !allergic_to(0, "pollen") - @test allergic_to(64, "pollen") - @test allergic_to(224, "pollen") - @test !allergic_to(160, "pollen") - @test allergic_to(255, "pollen") - end + @testset "testing for pollen allergy" begin + @test !allergic_to(0, "pollen") + @test allergic_to(64, "pollen") + @test allergic_to(224, "pollen") + @test !allergic_to(160, "pollen") + @test allergic_to(255, "pollen") + end - @testset "testing for cats allergy" begin - @test !allergic_to(0, "cats") - @test allergic_to(128, "cats") - @test allergic_to(192, "cats") - @test !allergic_to(64, "cats") - @test allergic_to(255, "cats") + @testset "testing for cats allergy" begin + @test !allergic_to(0, "cats") + @test allergic_to(128, "cats") + @test allergic_to(192, "cats") + @test !allergic_to(64, "cats") + @test allergic_to(255, "cats") + end end -end -@testset "testing the allergy_list" begin - @testset "testing single allergies" begin - @test allergy_list(0) == Set([]) - @test allergy_list(1) == Set(["eggs"]) - @test allergy_list(2) == Set(["peanuts"]) - @test allergy_list(8) == Set(["strawberries"]) - end + @testset "testing the allergy_list" begin + @testset "testing single allergies" begin + @test allergy_list(0) == Set([]) + @test allergy_list(1) == Set(["eggs"]) + @test allergy_list(2) == Set(["peanuts"]) + @test allergy_list(8) == Set(["strawberries"]) + end - @testset "testing for more allergies" begin - @test allergy_list(3) == Set(["eggs", "peanuts"]) - @test allergy_list(5) == Set(["eggs", "shellfish"]) - @test allergy_list(248) == Set(["strawberries", "tomatoes", "chocolate", "pollen", "cats"]) - @test allergy_list(255) == Set(["eggs", "peanuts", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"]) - @test allergy_list(509) == Set(["eggs", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"]) + @testset "testing for more allergies" begin + @test allergy_list(3) == Set(["eggs", "peanuts"]) + @test allergy_list(5) == Set(["eggs", "shellfish"]) + @test allergy_list(248) == Set(["strawberries", "tomatoes", "chocolate", "pollen", "cats"]) + @test allergy_list(255) == Set(["eggs", "peanuts", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"]) + @test allergy_list(509) == Set(["eggs", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"]) + end end end diff --git a/exercises/practice/alphametics/.docs/instructions.append.md b/exercises/practice/alphametics/.docs/instructions.append.md new file mode 100644 index 00000000..79fb3427 --- /dev/null +++ b/exercises/practice/alphametics/.docs/instructions.append.md @@ -0,0 +1,4 @@ +# Instructions append + +You may (or may not!) want to call the function `permutations(a, t)` from [Combinatorics.jl](https://github.com/JuliaMath/Combinatorics.jl) in your solution. +If you would like to use it, you can include the **read-only** file `permutations.jl` with `include("permutations.jl")`. diff --git a/exercises/practice/alphametics/.docs/instructions.md b/exercises/practice/alphametics/.docs/instructions.md index ea0d42af..649576ec 100644 --- a/exercises/practice/alphametics/.docs/instructions.md +++ b/exercises/practice/alphametics/.docs/instructions.md @@ -2,7 +2,7 @@ Write a function to solve alphametics puzzles. -[Alphametics](https://en.wikipedia.org/wiki/Alphametics) is a puzzle where letters in words are replaced with numbers. +[Alphametics][alphametics] is a puzzle where letters in words are replaced with numbers. For example `SEND + MORE = MONEY`: @@ -28,5 +28,4 @@ Each letter must represent a different digit, and the leading digit of a multi-d Write a function to solve alphametics puzzles. -You may (or may not!) want to call the function `permutations(a, t)` from [Combinatorics.jl](https://github.com/JuliaMath/Combinatorics.jl) in your solution. -If you would like to use it, you can include the **read-only** file `permutations.jl` with `include("permutations.jl")`. +[alphametics]: https://en.wikipedia.org/wiki/Alphametics diff --git a/exercises/practice/alphametics/runtests.jl b/exercises/practice/alphametics/runtests.jl index c699523d..3ac49c42 100644 --- a/exercises/practice/alphametics/runtests.jl +++ b/exercises/practice/alphametics/runtests.jl @@ -2,101 +2,103 @@ using Test include("alphametics.jl") -@testset "puzzle with three letters" begin - @test solve("I + BB == ILL") == Dict( - 'I' => 1, - 'B' => 9, - 'L' => 0 - ) -end +@testset verbose = true "tests" begin + @testset "puzzle with three letters" begin + @test solve("I + BB == ILL") == Dict( + 'I' => 1, + 'B' => 9, + 'L' => 0 + ) + end -@testset "solution must have unique value for each letter" begin - @test solve("A == B") === nothing -end + @testset "solution must have unique value for each letter" begin + @test solve("A == B") === nothing + end -@testset "leading zero solution is invalid" begin - @test solve("ACA + DD == BD") === nothing -end + @testset "leading zero solution is invalid" begin + @test solve("ACA + DD == BD") === nothing + end -@testset "puzzle with two digits final carry" begin - @test solve("A + A + A + A + A + A + A + A + A + A + A + B == BCC") == Dict( - 'A' => 9, - 'B' => 1, - 'C' => 0 - ) -end + @testset "puzzle with two digits final carry" begin + @test solve("A + A + A + A + A + A + A + A + A + A + A + B == BCC") == Dict( + 'A' => 9, + 'B' => 1, + 'C' => 0 + ) + end -@testset "puzzle with four letters" begin - @test solve("AS + A == MOM") == Dict( - 'A' => 9, - 'S' => 2, - 'M' => 1, - 'O' => 0 - ) -end + @testset "puzzle with four letters" begin + @test solve("AS + A == MOM") == Dict( + 'A' => 9, + 'S' => 2, + 'M' => 1, + 'O' => 0 + ) + end -@testset "puzzle with six letters" begin - @test solve("NO + NO + TOO == LATE") == Dict( - 'N' => 7, - 'O' => 4, - 'T' => 9, - 'L' => 1, - 'A' => 0, - 'E' => 2 - ) -end + @testset "puzzle with six letters" begin + @test solve("NO + NO + TOO == LATE") == Dict( + 'N' => 7, + 'O' => 4, + 'T' => 9, + 'L' => 1, + 'A' => 0, + 'E' => 2 + ) + end -@testset "puzzle with seven letters" begin - @test solve("HE + SEES + THE == LIGHT") == Dict( - 'E' => 4, - 'G' => 2, - 'H' => 5, - 'I' => 0, - 'L' => 1, - 'S' => 9, - 'T' => 7 - ) -end + @testset "puzzle with seven letters" begin + @test solve("HE + SEES + THE == LIGHT") == Dict( + 'E' => 4, + 'G' => 2, + 'H' => 5, + 'I' => 0, + 'L' => 1, + 'S' => 9, + 'T' => 7 + ) + end -@testset "puzzle with eight letters" begin - @test solve("SEND + MORE == MONEY") == Dict( - 'S' => 9, - 'E' => 5, - 'N' => 6, - 'D' => 7, - 'M' => 1, - 'O' => 0, - 'R' => 8, - 'Y' => 2 - ) -end + @testset "puzzle with eight letters" begin + @test solve("SEND + MORE == MONEY") == Dict( + 'S' => 9, + 'E' => 5, + 'N' => 6, + 'D' => 7, + 'M' => 1, + 'O' => 0, + 'R' => 8, + 'Y' => 2 + ) + end -@testset "puzzle with ten letters" begin - @test solve("AND + A + STRONG + OFFENSE + AS + A + GOOD == DEFENSE") == Dict( - 'A' => 5, - 'D' => 3, - 'E' => 4, - 'F' => 7, - 'G' => 8, - 'N' => 0, - 'O' => 2, - 'R' => 1, - 'S' => 6, - 'T' => 9 - ) -end + @testset "puzzle with ten letters" begin + @test solve("AND + A + STRONG + OFFENSE + AS + A + GOOD == DEFENSE") == Dict( + 'A' => 5, + 'D' => 3, + 'E' => 4, + 'F' => 7, + 'G' => 8, + 'N' => 0, + 'O' => 2, + 'R' => 1, + 'S' => 6, + 'T' => 9 + ) + end -@testset "puzzle with ten letters and 199 addends" begin - @test solve("THIS + A + FIRE + THEREFORE + FOR + ALL + HISTORIES + I + TELL + A + TALE + THAT + FALSIFIES + ITS + TITLE + TIS + A + LIE + THE + TALE + OF + THE + LAST + FIRE + HORSES + LATE + AFTER + THE + FIRST + FATHERS + FORESEE + THE + HORRORS + THE + LAST + FREE + TROLL + TERRIFIES + THE + HORSES + OF + FIRE + THE + TROLL + RESTS + AT + THE + HOLE + OF + LOSSES + IT + IS + THERE + THAT + SHE + STORES + ROLES + OF + LEATHERS + AFTER + SHE + SATISFIES + HER + HATE + OFF + THOSE + FEARS + A + TASTE + RISES + AS + SHE + HEARS + THE + LEAST + FAR + HORSE + THOSE + FAST + HORSES + THAT + FIRST + HEAR + THE + TROLL + FLEE + OFF + TO + THE + FOREST + THE + HORSES + THAT + ALERTS + RAISE + THE + STARES + OF + THE + OTHERS + AS + THE + TROLL + ASSAILS + AT + THE + TOTAL + SHIFT + HER + TEETH + TEAR + HOOF + OFF + TORSO + AS + THE + LAST + HORSE + FORFEITS + ITS + LIFE + THE + FIRST + FATHERS + HEAR + OF + THE + HORRORS + THEIR + FEARS + THAT + THE + FIRES + FOR + THEIR + FEASTS + ARREST + AS + THE + FIRST + FATHERS + RESETTLE + THE + LAST + OF + THE + FIRE + HORSES + THE + LAST + TROLL + HARASSES + THE + FOREST + HEART + FREE + AT + LAST + OF + THE + LAST + TROLL + ALL + OFFER + THEIR + FIRE + HEAT + TO + THE + ASSISTERS + FAR + OFF + THE + TROLL + FASTS + ITS + LIFE + SHORTER + AS + STARS + RISE + THE + HORSES + REST + SAFE + AFTER + ALL + SHARE + HOT + FISH + AS + THEIR + AFFILIATES + TAILOR + A + ROOFS + FOR + THEIR + SAFE == FORTRESSES") == Dict( - 'A' => 1, - 'E' => 0, - 'F' => 5, - 'H' => 8, - 'I' => 7, - 'L' => 2, - 'O' => 6, - 'R' => 3, - 'S' => 4, - 'T' => 9 - ) + @testset "puzzle with ten letters and 199 addends" begin + @test solve("THIS + A + FIRE + THEREFORE + FOR + ALL + HISTORIES + I + TELL + A + TALE + THAT + FALSIFIES + ITS + TITLE + TIS + A + LIE + THE + TALE + OF + THE + LAST + FIRE + HORSES + LATE + AFTER + THE + FIRST + FATHERS + FORESEE + THE + HORRORS + THE + LAST + FREE + TROLL + TERRIFIES + THE + HORSES + OF + FIRE + THE + TROLL + RESTS + AT + THE + HOLE + OF + LOSSES + IT + IS + THERE + THAT + SHE + STORES + ROLES + OF + LEATHERS + AFTER + SHE + SATISFIES + HER + HATE + OFF + THOSE + FEARS + A + TASTE + RISES + AS + SHE + HEARS + THE + LEAST + FAR + HORSE + THOSE + FAST + HORSES + THAT + FIRST + HEAR + THE + TROLL + FLEE + OFF + TO + THE + FOREST + THE + HORSES + THAT + ALERTS + RAISE + THE + STARES + OF + THE + OTHERS + AS + THE + TROLL + ASSAILS + AT + THE + TOTAL + SHIFT + HER + TEETH + TEAR + HOOF + OFF + TORSO + AS + THE + LAST + HORSE + FORFEITS + ITS + LIFE + THE + FIRST + FATHERS + HEAR + OF + THE + HORRORS + THEIR + FEARS + THAT + THE + FIRES + FOR + THEIR + FEASTS + ARREST + AS + THE + FIRST + FATHERS + RESETTLE + THE + LAST + OF + THE + FIRE + HORSES + THE + LAST + TROLL + HARASSES + THE + FOREST + HEART + FREE + AT + LAST + OF + THE + LAST + TROLL + ALL + OFFER + THEIR + FIRE + HEAT + TO + THE + ASSISTERS + FAR + OFF + THE + TROLL + FASTS + ITS + LIFE + SHORTER + AS + STARS + RISE + THE + HORSES + REST + SAFE + AFTER + ALL + SHARE + HOT + FISH + AS + THEIR + AFFILIATES + TAILOR + A + ROOFS + FOR + THEIR + SAFE == FORTRESSES") == Dict( + 'A' => 1, + 'E' => 0, + 'F' => 5, + 'H' => 8, + 'I' => 7, + 'L' => 2, + 'O' => 6, + 'R' => 3, + 'S' => 4, + 'T' => 9 + ) + end end diff --git a/exercises/practice/anagram/.docs/instructions.md b/exercises/practice/anagram/.docs/instructions.md index 2675b583..a7298485 100644 --- a/exercises/practice/anagram/.docs/instructions.md +++ b/exercises/practice/anagram/.docs/instructions.md @@ -1,8 +1,13 @@ # Instructions -An anagram is a rearrangement of letters to form a new word. -Given a word and a list of candidates, select the sublist of anagrams of the given word. +Your task is to, given a target word and a set of candidate words, to find the subset of the candidates that are anagrams of the target. -Given `"listen"` and a list of candidates like `"enlists" "google" -"inlets" "banana"` the program should return a list containing -`"inlets"`. +An anagram is a rearrangement of letters to form a new word: for example `"owns"` is an anagram of `"snow"`. +A word is _not_ its own anagram: for example, `"stop"` is not an anagram of `"stop"`. + +The target and candidates are words of one or more ASCII alphabetic characters (`A`-`Z` and `a`-`z`). +Lowercase and uppercase characters are equivalent: for example, `"PoTS"` is an anagram of `"sTOp"`, but `StoP` is not an anagram of `sTOp`. +The anagram set is the subset of the candidate set that are anagrams of the target (in any order). +Words in the anagram set should have the same letter case as in the candidate set. + +Given the target `"stone"` and candidates `"stone"`, `"tones"`, `"banana"`, `"tons"`, `"notes"`, `"Seton"`, the anagram set is `"tones"`, `"notes"`, `"Seton"`. diff --git a/exercises/practice/anagram/.docs/introduction.md b/exercises/practice/anagram/.docs/introduction.md new file mode 100644 index 00000000..1acbdf00 --- /dev/null +++ b/exercises/practice/anagram/.docs/introduction.md @@ -0,0 +1,12 @@ +# Introduction + +At a garage sale, you find a lovely vintage typewriter at a bargain price! +Excitedly, you rush home, insert a sheet of paper, and start typing away. +However, your excitement wanes when you examine the output: all words are garbled! +For example, it prints "stop" instead of "post" and "least" instead of "stale." +Carefully, you try again, but now it prints "spot" and "slate." +After some experimentation, you find there is a random delay before each letter is printed, which messes up the order. +You now understand why they sold it for so little money! + +You realize this quirk allows you to generate anagrams, which are words formed by rearranging the letters of another word. +Pleased with your finding, you spend the rest of the day generating hundreds of anagrams. diff --git a/exercises/practice/anagram/runtests.jl b/exercises/practice/anagram/runtests.jl index dd94be17..59552ee7 100644 --- a/exercises/practice/anagram/runtests.jl +++ b/exercises/practice/anagram/runtests.jl @@ -2,84 +2,86 @@ using Test include("anagram.jl") -@testset verbose = true "Anagram" begin - @testset "no matches" begin - @test detect_anagrams("diaper", ["hello", "world", "zombies", "pants"]) == String[] - end - - @testset "detects simple anagram" begin - @test detect_anagrams("ant", ["tan", "stand", "at"]) == ["tan"] - end - - @testset "does not detect false positives" begin - @test detect_anagrams("galea", ["eagle"]) == String[] - end - - @testset "detects two anagrams" begin - @test detect_anagrams("master", ["stream", "pigeon", "maters"]) == ["stream", "maters"] - end - - @testset "does not detect anagram subsets" begin - @test detect_anagrams("good", ["dog", "goody"]) == String[] - end - - @testset "detects anagram" begin - @test detect_anagrams("listen", ["enlists", "google", "inlets", "banana"]) == ["inlets"] - end - - @testset "detects three anagrams" begin - @test detect_anagrams("allergy", ["gallery", "ballerina", "regally", "clergy", "largely", "leading"]) == ["gallery", "regally", "largely"] - end - - @testset "detects multiple anagrams with different case" begin - @test detect_anagrams("nose", ["Eons", "ONES"]) == ["Eons", "ONES"] - end - - @testset "does not detect identical words" begin - @test detect_anagrams("corn", ["corn", "dark", "Corn", "rank", "CORN", "cron", "park"]) == ["cron"] - end - - @testset "does not detect non-anagrams with identical checksum" begin - @test detect_anagrams("mass", ["last"]) == String[] - end - - @testset "detects anagrams case-insensitively" begin - @test detect_anagrams("Orchestra", ["cashregister", "Carthorse", "radishes"]) == ["Carthorse"] - end - - @testset "detects anagrams using case-insensitive subject" begin - @test detect_anagrams("Orchestra", ["cashregister", "carthorse", "radishes"]) == ["carthorse"] - end - - @testset "detects anagrams using case-insensitive possible matches" begin - @test detect_anagrams("orchestra", ["cashregister", "Carthorse", "radishes"]) == ["Carthorse"] - end - - @testset "does not detect an anagram if the original word is repeated" begin - @test detect_anagrams("go", ["go Go GO"]) == String[] - end - - @testset "does not detect a word as its own anagram" begin - @test detect_anagrams("banana", ["Banana"]) == String[] - end - - @testset "does not detect a anagram if the original word is repeated" begin - @test detect_anagrams("go", ["go Go GO"]) == String[] - end - - @testset "anagrams must use all letters exactly once" begin - @test detect_anagrams("tapper", ["patter"]) == String[] - end - - @testset "words are not anagrams of themselves (case-insensitive)" begin - @test detect_anagrams("BANANA", ["BANANA", "Banana", "banana"]) == String[] - end - - @testset "words other than themselves can be anagrams" begin - @test detect_anagrams("LISTEN", ["Listen", "Silent", "LISTEN"]) == ["Silent"] - end - - @testset "capital word is not own anagram" begin - @test detect_anagrams("BANANA", ["Banana"]) == String[] +@testset verbose = true "tests" begin + @testset verbose = true "Anagram" begin + @testset "no matches" begin + @test detect_anagrams("diaper", ["hello", "world", "zombies", "pants"]) == String[] + end + + @testset "detects simple anagram" begin + @test detect_anagrams("ant", ["tan", "stand", "at"]) == ["tan"] + end + + @testset "does not detect false positives" begin + @test detect_anagrams("galea", ["eagle"]) == String[] + end + + @testset "detects two anagrams" begin + @test detect_anagrams("master", ["stream", "pigeon", "maters"]) == ["stream", "maters"] + end + + @testset "does not detect anagram subsets" begin + @test detect_anagrams("good", ["dog", "goody"]) == String[] + end + + @testset "detects anagram" begin + @test detect_anagrams("listen", ["enlists", "google", "inlets", "banana"]) == ["inlets"] + end + + @testset "detects three anagrams" begin + @test detect_anagrams("allergy", ["gallery", "ballerina", "regally", "clergy", "largely", "leading"]) == ["gallery", "regally", "largely"] + end + + @testset "detects multiple anagrams with different case" begin + @test detect_anagrams("nose", ["Eons", "ONES"]) == ["Eons", "ONES"] + end + + @testset "does not detect identical words" begin + @test detect_anagrams("corn", ["corn", "dark", "Corn", "rank", "CORN", "cron", "park"]) == ["cron"] + end + + @testset "does not detect non-anagrams with identical checksum" begin + @test detect_anagrams("mass", ["last"]) == String[] + end + + @testset "detects anagrams case-insensitively" begin + @test detect_anagrams("Orchestra", ["cashregister", "Carthorse", "radishes"]) == ["Carthorse"] + end + + @testset "detects anagrams using case-insensitive subject" begin + @test detect_anagrams("Orchestra", ["cashregister", "carthorse", "radishes"]) == ["carthorse"] + end + + @testset "detects anagrams using case-insensitive possible matches" begin + @test detect_anagrams("orchestra", ["cashregister", "Carthorse", "radishes"]) == ["Carthorse"] + end + + @testset "does not detect an anagram if the original word is repeated" begin + @test detect_anagrams("go", ["go Go GO"]) == String[] + end + + @testset "does not detect a word as its own anagram" begin + @test detect_anagrams("banana", ["Banana"]) == String[] + end + + @testset "does not detect a anagram if the original word is repeated" begin + @test detect_anagrams("go", ["go Go GO"]) == String[] + end + + @testset "anagrams must use all letters exactly once" begin + @test detect_anagrams("tapper", ["patter"]) == String[] + end + + @testset "words are not anagrams of themselves (case-insensitive)" begin + @test detect_anagrams("BANANA", ["BANANA", "Banana", "banana"]) == String[] + end + + @testset "words other than themselves can be anagrams" begin + @test detect_anagrams("LISTEN", ["Listen", "Silent", "LISTEN"]) == ["Silent"] + end + + @testset "capital word is not own anagram" begin + @test detect_anagrams("BANANA", ["Banana"]) == String[] + end end end diff --git a/exercises/practice/armstrong-numbers/.docs/instructions.md b/exercises/practice/armstrong-numbers/.docs/instructions.md index 452a996f..5e56bbe4 100644 --- a/exercises/practice/armstrong-numbers/.docs/instructions.md +++ b/exercises/practice/armstrong-numbers/.docs/instructions.md @@ -1,12 +1,14 @@ # Instructions -An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that is the sum of its own digits each raised to the power of the number of digits. +An [Armstrong number][armstrong-number] is a number that is the sum of its own digits each raised to the power of the number of digits. For example: - 9 is an Armstrong number, because `9 = 9^1 = 9` -- 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1` +- 10 is _not_ an Armstrong number, because `10 != 1^2 + 0^2 = 1` - 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153` -- 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190` +- 154 is _not_ an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190` Write some code to determine whether a number is an Armstrong number. + +[armstrong-number]: https://en.wikipedia.org/wiki/Narcissistic_number diff --git a/exercises/practice/armstrong-numbers/.meta/config.json b/exercises/practice/armstrong-numbers/.meta/config.json index 3d0cf578..9df7c69d 100644 --- a/exercises/practice/armstrong-numbers/.meta/config.json +++ b/exercises/practice/armstrong-numbers/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Determine if a number is an Armstrong number", + "blurb": "Determine if a number is an Armstrong number.", "authors": [ "SaschaMann" ], diff --git a/exercises/practice/armstrong-numbers/runtests.jl b/exercises/practice/armstrong-numbers/runtests.jl index e8a48cae..299b7df2 100644 --- a/exercises/practice/armstrong-numbers/runtests.jl +++ b/exercises/practice/armstrong-numbers/runtests.jl @@ -2,14 +2,16 @@ using Test include("armstrong-numbers.jl") -@testset "armstrong numbers" begin - @test isarmstrong(0) - @test isarmstrong(5) - @test !isarmstrong(10) - @test !isarmstrong(100) - @test isarmstrong(153) - @test isarmstrong(9474) - @test !isarmstrong(9475) - @test isarmstrong(9926315) - @test !isarmstrong(9926314) +@testset verbose = true "tests" begin + @testset "armstrong numbers" begin + @test isarmstrong(0) + @test isarmstrong(5) + @test !isarmstrong(10) + @test !isarmstrong(100) + @test isarmstrong(153) + @test isarmstrong(9474) + @test !isarmstrong(9475) + @test isarmstrong(9926315) + @test !isarmstrong(9926314) + end end diff --git a/exercises/practice/atbash-cipher/.docs/instructions.md b/exercises/practice/atbash-cipher/.docs/instructions.md index 2f712b15..21ca2ce0 100644 --- a/exercises/practice/atbash-cipher/.docs/instructions.md +++ b/exercises/practice/atbash-cipher/.docs/instructions.md @@ -2,10 +2,8 @@ Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East. -The Atbash cipher is a simple substitution cipher that relies on -transposing all the letters in the alphabet such that the resulting -alphabet is backwards. The first letter is replaced with the last -letter, the second with the second-last, and so on. +The Atbash cipher is a simple substitution cipher that relies on transposing all the letters in the alphabet such that the resulting alphabet is backwards. +The first letter is replaced with the last letter, the second with the second-last, and so on. An Atbash cipher for the Latin alphabet would be as follows: @@ -14,16 +12,16 @@ Plain: abcdefghijklmnopqrstuvwxyz Cipher: zyxwvutsrqponmlkjihgfedcba ``` -It is a very weak cipher because it only has one possible key, and it is -a simple monoalphabetic substitution cipher. However, this may not have -been an issue in the cipher's time. +It is a very weak cipher because it only has one possible key, and it is a simple mono-alphabetic substitution cipher. +However, this may not have been an issue in the cipher's time. -Ciphertext is written out in groups of fixed length, the traditional group size -being 5 letters, and punctuation is excluded. This is to make it harder to guess -things based on word boundaries. +Ciphertext is written out in groups of fixed length, the traditional group size being 5 letters, leaving numbers unchanged, and punctuation is excluded. +This is to make it harder to guess things based on word boundaries. +All text will be encoded as lowercase letters. ## Examples - Encoding `test` gives `gvhg` +- Encoding `x123 yes` gives `c123b vh` - Decoding `gvhg` gives `test` - Decoding `gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt` gives `thequickbrownfoxjumpsoverthelazydog` diff --git a/exercises/practice/atbash-cipher/.meta/config.json b/exercises/practice/atbash-cipher/.meta/config.json index 299245e4..ae8a1fd0 100644 --- a/exercises/practice/atbash-cipher/.meta/config.json +++ b/exercises/practice/atbash-cipher/.meta/config.json @@ -20,5 +20,5 @@ ] }, "source": "Wikipedia", - "source_url": "http://en.wikipedia.org/wiki/Atbash" + "source_url": "https://en.wikipedia.org/wiki/Atbash" } diff --git a/exercises/practice/atbash-cipher/runtests.jl b/exercises/practice/atbash-cipher/runtests.jl index ed939f1a..dfcc821e 100644 --- a/exercises/practice/atbash-cipher/runtests.jl +++ b/exercises/practice/atbash-cipher/runtests.jl @@ -2,23 +2,24 @@ using Test include("atbash-cipher.jl") -@testset "encoding from English to atbash" begin - @test encode("yes") == "bvh" - @test encode("no") == "ml" - @test encode("OMG") == "lnt" - @test encode("O M G") == "lnt" - @test encode("mindblowingly") == "nrmwy oldrm tob" - @test encode("Testing,1 2 3, testing.") == "gvhgr mt123 gvhgr mt" - @test encode("Truth is fiction.") == "gifgs rhurx grlm" - @test encode("The quick brown fox jumps over the lazy dog.") == "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt" -end +@testset verbose = true "tests" begin + @testset "encoding from English to atbash" begin + @test encode("yes") == "bvh" + @test encode("no") == "ml" + @test encode("OMG") == "lnt" + @test encode("O M G") == "lnt" + @test encode("mindblowingly") == "nrmwy oldrm tob" + @test encode("Testing,1 2 3, testing.") == "gvhgr mt123 gvhgr mt" + @test encode("Truth is fiction.") == "gifgs rhurx grlm" + @test encode("The quick brown fox jumps over the lazy dog.") == "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt" + end -@testset "decoding from atbash to English" begin - @test decode("vcvix rhn") == "exercism" - @test decode("zmlyh gzxov rhlug vmzhg vkkrm thglm v") == "anobstacleisoftenasteppingstone" - @test decode("gvhgr mt123 gvhgr mt") == "testing123testing" - @test decode("gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt") == "thequickbrownfoxjumpsoverthelazydog" - @test decode("vc vix r hn") == "exercism" - @test decode("zmlyhgzxovrhlugvmzhgvkkrmthglmv") == "anobstacleisoftenasteppingstone" + @testset "decoding from atbash to English" begin + @test decode("vcvix rhn") == "exercism" + @test decode("zmlyh gzxov rhlug vmzhg vkkrm thglm v") == "anobstacleisoftenasteppingstone" + @test decode("gvhgr mt123 gvhgr mt") == "testing123testing" + @test decode("gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt") == "thequickbrownfoxjumpsoverthelazydog" + @test decode("vc vix r hn") == "exercism" + @test decode("zmlyhgzxovrhlugvmzhgvkkrmthglmv") == "anobstacleisoftenasteppingstone" + end end - diff --git a/exercises/practice/binary-search/.docs/instructions.md b/exercises/practice/binary-search/.docs/instructions.md index d7f1c899..12f4358e 100644 --- a/exercises/practice/binary-search/.docs/instructions.md +++ b/exercises/practice/binary-search/.docs/instructions.md @@ -11,7 +11,7 @@ Binary search only works when a list has been sorted. The algorithm looks like this: -- Find the middle element of a sorted list and compare it with the item we're looking for. +- Find the middle element of a _sorted_ list and compare it with the item we're looking for. - If the middle element is our item, then we're done! - If the middle element is greater than our item, we can eliminate that element and all the elements **after** it. - If the middle element is less than our item, we can eliminate that element and all the elements **before** it. diff --git a/exercises/practice/binary-search/.meta/config.json b/exercises/practice/binary-search/.meta/config.json index fc079e44..b6a2e6d7 100644 --- a/exercises/practice/binary-search/.meta/config.json +++ b/exercises/practice/binary-search/.meta/config.json @@ -18,5 +18,5 @@ ] }, "source": "Wikipedia", - "source_url": "http://en.wikipedia.org/wiki/Binary_search_algorithm" + "source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm" } diff --git a/exercises/practice/binary-search/runtests.jl b/exercises/practice/binary-search/runtests.jl index 0d4b1019..70493dfd 100644 --- a/exercises/practice/binary-search/runtests.jl +++ b/exercises/practice/binary-search/runtests.jl @@ -2,90 +2,92 @@ using Test include("binary-search.jl") -@testset "default binary search" begin - @testset "value in array" begin - @test binarysearch([6], 6) == 1:1 - @test binarysearch([1, 3, 4, 6, 8, 9, 11], 6) == 4:4 - @test binarysearch([1, 3, 4, 6, 8, 9, 11], 1) == 1:1 - @test binarysearch([1, 3, 4, 6, 8, 9, 11], 11) == 7:7 - @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634], 144) == 10:10 - @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377], 21) == 6:6 - end - @testset "value not in array" begin - @test binarysearch([1, 3, 4, 6, 8, 9, 11], 7) == 5:4 - @test binarysearch([1, 3, 4, 6, 8, 9, 11], 0) == 1:0 - @test binarysearch([1, 3, 4, 6, 8, 9, 11], 13) == 8:7 - @test binarysearch([], 1) == 1:0 - @test binarysearch([1, 2], 0) == 1:0 +@testset verbose = true "tests" begin + @testset "default binary search" begin + @testset "value in array" begin + @test binarysearch([6], 6) == 1:1 + @test binarysearch([1, 3, 4, 6, 8, 9, 11], 6) == 4:4 + @test binarysearch([1, 3, 4, 6, 8, 9, 11], 1) == 1:1 + @test binarysearch([1, 3, 4, 6, 8, 9, 11], 11) == 7:7 + @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634], 144) == 10:10 + @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377], 21) == 6:6 + end + @testset "value not in array" begin + @test binarysearch([1, 3, 4, 6, 8, 9, 11], 7) == 5:4 + @test binarysearch([1, 3, 4, 6, 8, 9, 11], 0) == 1:0 + @test binarysearch([1, 3, 4, 6, 8, 9, 11], 13) == 8:7 + @test binarysearch([], 1) == 1:0 + @test binarysearch([1, 2], 0) == 1:0 + end end -end -@isdefined(tested_bonus_tasks) && any(values(tested_bonus_tasks)) && @testset "bonus tasks" begin - if get(tested_bonus_tasks, :rev, false) - @testset "reverse search" begin - @testset "value in array" begin - @test binarysearch([6], 6, rev = true) == 1:1 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 6, rev = true) == 4:4 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 1, rev = true) == 7:7 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 11, rev = true) == 1:1 - @test binarysearch([634, 377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 144, rev = true,) == 4:4 - @test binarysearch([377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 21, rev = true,) == 7:7 - end - @testset "value not in array" begin - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 7, rev = true) == 4:3 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 0, rev = true) == 8:7 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 13, rev = true) == 1:0 - @test binarysearch([], 1, rev = true) == 1:0 + @isdefined(tested_bonus_tasks) && any(values(tested_bonus_tasks)) && @testset "bonus tasks" begin + if get(tested_bonus_tasks, :rev, false) + @testset "reverse search" begin + @testset "value in array" begin + @test binarysearch([6], 6, rev = true) == 1:1 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 6, rev = true) == 4:4 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 1, rev = true) == 7:7 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 11, rev = true) == 1:1 + @test binarysearch([634, 377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 144, rev = true,) == 4:4 + @test binarysearch([377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 21, rev = true,) == 7:7 + end + @testset "value not in array" begin + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 7, rev = true) == 4:3 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 0, rev = true) == 8:7 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 13, rev = true) == 1:0 + @test binarysearch([], 1, rev = true) == 1:0 + end end end - end - if get(tested_bonus_tasks, :by, false) - @testset "apply transformation" begin - @testset "value in array" begin - @test binarysearch([5.5], 6, by = round) == 1:1 - @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 6, by = round) == 4:4 - @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 1, by = round) == 1:1 - @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 11, by = round) == 7:7 - @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 11, by = abs2 ∘ round,) == 7:7 - @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634], 144.4, by = round,) == 10:10 - @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377], 20.6, by = round,) == 6:6 - end - @testset "value not in array" begin - @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 7, by = round) == 5:4 - @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 0, by = round) == 1:0 - @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 13, by = round) == 8:7 - @test binarysearch([], 1, by = round) == 1:0 + if get(tested_bonus_tasks, :by, false) + @testset "apply transformation" begin + @testset "value in array" begin + @test binarysearch([5.5], 6, by = round) == 1:1 + @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 6, by = round) == 4:4 + @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 1, by = round) == 1:1 + @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 11, by = round) == 7:7 + @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 11, by = abs2 ∘ round,) == 7:7 + @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634], 144.4, by = round,) == 10:10 + @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377], 20.6, by = round,) == 6:6 + end + @testset "value not in array" begin + @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 7, by = round) == 5:4 + @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 0, by = round) == 1:0 + @test binarysearch([1.1, 2.9, 4.4, 5.5, 8.1, 9.0, 10.8], 13, by = round) == 8:7 + @test binarysearch([], 1, by = round) == 1:0 + end end end - end - if get(tested_bonus_tasks, :lt, false) - @testset "compare with > instead of <" begin - # this is equivalent to searching in reverse order - @testset "value in array" begin - @test binarysearch([6], 6, lt = >) == 1:1 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 6, lt = >) == 4:4 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 1, lt = >) == 7:7 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 11, lt = >) == 1:1 - @test binarysearch([634, 377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 144, lt = >,) == 4:4 - @test binarysearch([377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 21, lt = >,) == 7:7 - end - @testset "value not in array" begin - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 7, lt = >) == 4:3 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 0, lt = >) == 8:7 - @test binarysearch([11, 9, 8, 6, 4, 3, 1], 13, lt = >) == 1:0 - @test binarysearch([], 1, lt = >) == 1:0 + if get(tested_bonus_tasks, :lt, false) + @testset "compare with > instead of <" begin + # this is equivalent to searching in reverse order + @testset "value in array" begin + @test binarysearch([6], 6, lt = >) == 1:1 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 6, lt = >) == 4:4 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 1, lt = >) == 7:7 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 11, lt = >) == 1:1 + @test binarysearch([634, 377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 144, lt = >,) == 4:4 + @test binarysearch([377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 1], 21, lt = >,) == 7:7 + end + @testset "value not in array" begin + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 7, lt = >) == 4:3 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 0, lt = >) == 8:7 + @test binarysearch([11, 9, 8, 6, 4, 3, 1], 13, lt = >) == 1:0 + @test binarysearch([], 1, lt = >) == 1:0 + end end end - end - if get(tested_bonus_tasks, :multiple_matches, false) - @testset "multiple matches" begin - @test binarysearch([1, 3, 4, 6, 6, 9, 11], 6) == 4:5 - @test binarysearch([1, 1, 4, 6, 8, 9, 11], 1) == 1:2 - @test binarysearch([1, 3, 4, 6, 8, 11, 11], 11) == 6:7 - @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 144, 144, 144, 377, 634],144,) == 9:11 - @test binarysearch([1, 3, 5, 21, 21, 21, 21, 21, 89, 144, 233, 377], 21) == 4:8 + if get(tested_bonus_tasks, :multiple_matches, false) + @testset "multiple matches" begin + @test binarysearch([1, 3, 4, 6, 6, 9, 11], 6) == 4:5 + @test binarysearch([1, 1, 4, 6, 8, 9, 11], 1) == 1:2 + @test binarysearch([1, 3, 4, 6, 8, 11, 11], 11) == 6:7 + @test binarysearch([1, 3, 5, 8, 13, 21, 34, 55, 144, 144, 144, 377, 634],144,) == 9:11 + @test binarysearch([1, 3, 5, 21, 21, 21, 21, 21, 89, 144, 233, 377], 21) == 4:8 + end end end end diff --git a/exercises/practice/bob/.docs/instructions.md b/exercises/practice/bob/.docs/instructions.md index edddb141..bb702f7b 100644 --- a/exercises/practice/bob/.docs/instructions.md +++ b/exercises/practice/bob/.docs/instructions.md @@ -1,16 +1,19 @@ # Instructions -Bob is a lackadaisical teenager. In conversation, his responses are very limited. +Your task is to determine what Bob will reply to someone when they say something to him or ask him a question. -Bob answers 'Sure.' if you ask him a question, such as "How are you?". +Bob only ever answers one of five things: -He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals). - -He answers 'Calm down, I know what I'm doing!' if you yell a question at him. - -He says 'Fine. Be that way!' if you address him without actually saying -anything. - -He answers 'Whatever.' to anything else. - -Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English. +- **"Sure."** + This is his response if you ask him a question, such as "How are you?" + The convention used for questions is that it ends with a question mark. +- **"Whoa, chill out!"** + This is his answer if you YELL AT HIM. + The convention used for yelling is ALL CAPITAL LETTERS. +- **"Calm down, I know what I'm doing!"** + This is what he says if you yell a question at him. +- **"Fine. Be that way!"** + This is how he responds to silence. + The convention used for silence is nothing, or various combinations of whitespace characters. +- **"Whatever."** + This is what he answers to anything else. diff --git a/exercises/practice/bob/.docs/introduction.md b/exercises/practice/bob/.docs/introduction.md new file mode 100644 index 00000000..ea4a8077 --- /dev/null +++ b/exercises/practice/bob/.docs/introduction.md @@ -0,0 +1,10 @@ +# Introduction + +Bob is a [lackadaisical][] teenager. +He likes to think that he's very cool. +And he definitely doesn't get excited about things. +That wouldn't be cool. + +When people talk to him, his responses are pretty limited. + +[lackadaisical]: https://www.collinsdictionary.com/dictionary/english/lackadaisical diff --git a/exercises/practice/bob/.meta/config.json b/exercises/practice/bob/.meta/config.json index 674d51be..807e260e 100644 --- a/exercises/practice/bob/.meta/config.json +++ b/exercises/practice/bob/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial.", - "source_url": "http://pine.fm/LearnToProgram/?Chapter=06" + "source_url": "https://pine.fm/LearnToProgram/?Chapter=06" } diff --git a/exercises/practice/bob/runtests.jl b/exercises/practice/bob/runtests.jl index 6226d588..1670720c 100644 --- a/exercises/practice/bob/runtests.jl +++ b/exercises/practice/bob/runtests.jl @@ -58,32 +58,34 @@ response = Dict( :forceful_question => "Calm down, I know what I'm doing!", ) -@testset "questions" begin - @testset "$question" for question in questions - @test bob(question) == response[:question] +@testset verbose = true "tests" begin + @testset "questions" begin + @testset "$question" for question in questions + @test bob(question) == response[:question] + end end -end -@testset "yelling" begin - @testset "$yell" for yell in yells - @test bob(yell) == response[:yelling] + @testset "yelling" begin + @testset "$yell" for yell in yells + @test bob(yell) == response[:yelling] + end end -end -@testset "silence" begin - @testset "$silence" for silence in silences - @test bob(silence) == response[:silence] + @testset "silence" begin + @testset "$silence" for silence in silences + @test bob(silence) == response[:silence] + end end -end -@testset "misc" begin - @testset "$misc" for misc in miscs - @test bob(misc) == response[:misc] + @testset "misc" begin + @testset "$misc" for misc in miscs + @test bob(misc) == response[:misc] + end end -end -@testset "forceful questions" begin - @testset "$question" for question in forceful_questions - @test bob(question) == response[:forceful_question] - end + @testset "forceful questions" begin + @testset "$question" for question in forceful_questions + @test bob(question) == response[:forceful_question] + end + end end diff --git a/exercises/practice/circular-buffer/.docs/instructions.md b/exercises/practice/circular-buffer/.docs/instructions.md index e9b00b91..2ba1fda2 100644 --- a/exercises/practice/circular-buffer/.docs/instructions.md +++ b/exercises/practice/circular-buffer/.docs/instructions.md @@ -1,51 +1,58 @@ # Instructions -A circular buffer, cyclic buffer or ring buffer is a data structure that -uses a single, fixed-size buffer as if it were connected end-to-end. - -A circular buffer first starts empty and of some predefined length. For -example, this is a 7-element buffer: - - [ ][ ][ ][ ][ ][ ][ ] - -Assume that a 1 is written into the middle of the buffer (exact starting -location does not matter in a circular buffer): - - [ ][ ][ ][1][ ][ ][ ] - -Then assume that two more elements are added — 2 & 3 — which get -appended after the 1: - - [ ][ ][ ][1][2][3][ ] - -If two elements are then removed from the buffer, the oldest values -inside the buffer are removed. The two elements removed, in this case, -are 1 & 2, leaving the buffer with just a 3: - - [ ][ ][ ][ ][ ][3][ ] +A circular buffer, cyclic buffer or ring buffer is a data structure that uses a single, fixed-size buffer as if it were connected end-to-end. + +A circular buffer first starts empty and of some predefined length. +For example, this is a 7-element buffer: + +```text +[ ][ ][ ][ ][ ][ ][ ] +``` + +Assume that a 1 is written into the middle of the buffer (exact starting location does not matter in a circular buffer): + +```text +[ ][ ][ ][1][ ][ ][ ] +``` + +Then assume that two more elements are added — 2 & 3 — which get appended after the 1: + +```text +[ ][ ][ ][1][2][3][ ] +``` + +If two elements are then removed from the buffer, the oldest values inside the buffer are removed. +The two elements removed, in this case, are 1 & 2, leaving the buffer with just a 3: + +```text +[ ][ ][ ][ ][ ][3][ ] +``` If the buffer has 7 elements then it is completely full: - - [5][6][7][8][9][3][4] - -When the buffer is full an error will be raised, alerting the client -that further writes are blocked until a slot becomes free. - -When the buffer is full, the client can opt to overwrite the oldest -data with a forced write. In this case, two more elements — A & B — -are added and they overwrite the 3 & 4: - - [5][6][7][8][9][A][B] - -3 & 4 have been replaced by A & B making 5 now the oldest data in the -buffer. Finally, if two elements are removed then what would be -returned is 5 & 6 yielding the buffer: - - [ ][ ][7][8][9][A][B] - -Because there is space available, if the client again uses overwrite -to store C & D then the space where 5 & 6 were stored previously will -be used not the location of 7 & 8. 7 is still the oldest element and -the buffer is once again full. - - [C][D][7][8][9][A][B] + +```text +[5][6][7][8][9][3][4] +``` + +When the buffer is full an error will be raised, alerting the client that further writes are blocked until a slot becomes free. + +When the buffer is full, the client can opt to overwrite the oldest data with a forced write. +In this case, two more elements — A & B — are added and they overwrite the 3 & 4: + +```text +[5][6][7][8][9][A][B] +``` + +3 & 4 have been replaced by A & B making 5 now the oldest data in the buffer. +Finally, if two elements are removed then what would be returned is 5 & 6 yielding the buffer: + +```text +[ ][ ][7][8][9][A][B] +``` + +Because there is space available, if the client again uses overwrite to store C & D then the space where 5 & 6 were stored previously will be used not the location of 7 & 8. +7 is still the oldest element and the buffer is once again full. + +```text +[C][D][7][8][9][A][B] +``` diff --git a/exercises/practice/circular-buffer/.meta/config.json b/exercises/practice/circular-buffer/.meta/config.json index bdcb98d1..f1b68602 100644 --- a/exercises/practice/circular-buffer/.meta/config.json +++ b/exercises/practice/circular-buffer/.meta/config.json @@ -18,5 +18,5 @@ ] }, "source": "Wikipedia", - "source_url": "http://en.wikipedia.org/wiki/Circular_buffer" + "source_url": "https://en.wikipedia.org/wiki/Circular_buffer" } diff --git a/exercises/practice/circular-buffer/.meta/example.jl b/exercises/practice/circular-buffer/.meta/example.jl index 1345dac1..8b4f2f50 100644 --- a/exercises/practice/circular-buffer/.meta/example.jl +++ b/exercises/practice/circular-buffer/.meta/example.jl @@ -2,8 +2,6 @@ # tasks. The lengthier CircularBuffer afterward completes the bonus tasks and is optimized # for performance. -module CircularDeques - """ CircularDeque{T}(n) @@ -42,18 +40,10 @@ function Base.popfirst!(cd::CircularDeque) return cd.data[i] end -end # module CircularDeques - -using .CircularDeques - - -module CircularBuffers using Base: @propagate_inbounds using Printf -export CircularBuffer, capacity, isfull - """ CircularBuffer{T}(n) <: AbstractVector{T} @@ -181,8 +171,4 @@ end return out end -end # module CircularBuffers - -using .CircularBuffers - enable_bonus_tests = true diff --git a/exercises/practice/circular-buffer/runtests.jl b/exercises/practice/circular-buffer/runtests.jl index e42916b8..a2447a0d 100644 --- a/exercises/practice/circular-buffer/runtests.jl +++ b/exercises/practice/circular-buffer/runtests.jl @@ -2,264 +2,265 @@ using Test include("circular-buffer.jl") -@testset "reading empty buffer should fail" begin - cb = CircularBuffer{Int}(1) - @test_throws BoundsError popfirst!(cb) -end - -@testset "can read an item just written" begin - cb = CircularBuffer{Int}(1) - @test push!(cb, 1) === cb - @test popfirst!(cb) == 1 -end +@testset verbose = true "tests" begin + @testset "reading empty buffer should fail" begin + cb = CircularBuffer{Int}(1) + @test_throws BoundsError popfirst!(cb) + end -@testset "each item may only be read once" begin - cb = CircularBuffer{Int}(1) - @test push!(cb, 1) === cb - @test popfirst!(cb) == 1 - @test_throws BoundsError popfirst!(cb) -end + @testset "can read an item just written" begin + cb = CircularBuffer{Int}(1) + @test push!(cb, 1) === cb + @test popfirst!(cb) == 1 + end -@testset "items are read in the order they are written" begin - cb = CircularBuffer{Int}(2) - @test push!(cb, 1) === cb - @test push!(cb, 2) === cb - @test popfirst!(cb) == 1 - @test popfirst!(cb) == 2 -end + @testset "each item may only be read once" begin + cb = CircularBuffer{Int}(1) + @test push!(cb, 1) === cb + @test popfirst!(cb) == 1 + @test_throws BoundsError popfirst!(cb) + end -@testset "full buffer can't be written to" begin - cb = CircularBuffer{Int}(1) - @test push!(cb, 1) === cb - @test_throws BoundsError push!(cb, 2) -end + @testset "items are read in the order they are written" begin + cb = CircularBuffer{Int}(2) + @test push!(cb, 1) === cb + @test push!(cb, 2) === cb + @test popfirst!(cb) == 1 + @test popfirst!(cb) == 2 + end -@testset "a read frees up capacity for another write" begin - cb = CircularBuffer{Int}(1) - @test push!(cb, 1) === cb - @test popfirst!(cb) == 1 - @test push!(cb, 2) === cb - @test popfirst!(cb) == 2 -end + @testset "full buffer can't be written to" begin + cb = CircularBuffer{Int}(1) + @test push!(cb, 1) === cb + @test_throws BoundsError push!(cb, 2) + end -@testset "read position is maintained even across multiple writes" begin - cb = CircularBuffer{Int}(3) - @test push!(cb, 1) === cb - @test push!(cb, 2) === cb - @test popfirst!(cb) == 1 - @test push!(cb, 3) === cb - @test popfirst!(cb) == 2 - @test popfirst!(cb) == 3 -end + @testset "a read frees up capacity for another write" begin + cb = CircularBuffer{Int}(1) + @test push!(cb, 1) === cb + @test popfirst!(cb) == 1 + @test push!(cb, 2) === cb + @test popfirst!(cb) == 2 + end -@testset "items cleared out of buffer can't be read" begin - cb = CircularBuffer{Int}(1) - @test push!(cb, 1) === cb - @test empty!(cb) === cb - @test_throws BoundsError popfirst!(cb) -end + @testset "read position is maintained even across multiple writes" begin + cb = CircularBuffer{Int}(3) + @test push!(cb, 1) === cb + @test push!(cb, 2) === cb + @test popfirst!(cb) == 1 + @test push!(cb, 3) === cb + @test popfirst!(cb) == 2 + @test popfirst!(cb) == 3 + end -@testset "clear frees up capacity for another write" begin - cb = CircularBuffer{Int}(1) - @test push!(cb, 1) === cb - @test empty!(cb) === cb - @test push!(cb, 2) === cb - @test popfirst!(cb) == 2 -end + @testset "items cleared out of buffer can't be read" begin + cb = CircularBuffer{Int}(1) + @test push!(cb, 1) === cb + @test empty!(cb) === cb + @test_throws BoundsError popfirst!(cb) + end -@testset "clear does nothing on empty buffer" begin - cb = CircularBuffer{Int}(1) - @test empty!(cb) === cb - @test push!(cb, 1) === cb - @test popfirst!(cb) == 1 -end + @testset "clear frees up capacity for another write" begin + cb = CircularBuffer{Int}(1) + @test push!(cb, 1) === cb + @test empty!(cb) === cb + @test push!(cb, 2) === cb + @test popfirst!(cb) == 2 + end -@testset "overwrite acts like write on non-full buffer" begin - cb = CircularBuffer{Int}(2) - @test push!(cb, 1) === cb - @test push!(cb, 2; overwrite=true) === cb - @test popfirst!(cb) == 1 - @test popfirst!(cb) == 2 -end + @testset "clear does nothing on empty buffer" begin + cb = CircularBuffer{Int}(1) + @test empty!(cb) === cb + @test push!(cb, 1) === cb + @test popfirst!(cb) == 1 + end -@testset "overwrite replaces the oldest item on full buffer" begin - cb = CircularBuffer{Int}(2) - @test push!(cb, 1) === cb - @test push!(cb, 2) === cb - @test push!(cb, 3; overwrite=true) === cb - @test popfirst!(cb) == 2 - @test popfirst!(cb) == 3 -end + @testset "overwrite acts like write on non-full buffer" begin + cb = CircularBuffer{Int}(2) + @test push!(cb, 1) === cb + @test push!(cb, 2; overwrite=true) === cb + @test popfirst!(cb) == 1 + @test popfirst!(cb) == 2 + end -@testset "overwrite replaces the oldest item remaining in buffer following a read" begin - cb = CircularBuffer{Int}(3) - @test push!(cb, 1) === cb - @test push!(cb, 2) === cb - @test push!(cb, 3) === cb - @test popfirst!(cb) == 1 - @test push!(cb, 4) === cb - @test push!(cb, 5; overwrite=true) === cb - @test popfirst!(cb) == 3 - @test popfirst!(cb) == 4 - @test popfirst!(cb) == 5 -end + @testset "overwrite replaces the oldest item on full buffer" begin + cb = CircularBuffer{Int}(2) + @test push!(cb, 1) === cb + @test push!(cb, 2) === cb + @test push!(cb, 3; overwrite=true) === cb + @test popfirst!(cb) == 2 + @test popfirst!(cb) == 3 + end -@testset "initial clear does not affect wrapping around" begin - cb = CircularBuffer{Int}(2) - @test empty!(cb) === cb - @test push!(cb, 1) === cb - @test push!(cb, 2) === cb - @test push!(cb, 3; overwrite=true) === cb - @test push!(cb, 4; overwrite=true) === cb - @test popfirst!(cb) == 3 - @test popfirst!(cb) == 4 - @test_throws BoundsError popfirst!(cb) -end + @testset "overwrite replaces the oldest item remaining in buffer following a read" begin + cb = CircularBuffer{Int}(3) + @test push!(cb, 1) === cb + @test push!(cb, 2) === cb + @test push!(cb, 3) === cb + @test popfirst!(cb) == 1 + @test push!(cb, 4) === cb + @test push!(cb, 5; overwrite=true) === cb + @test popfirst!(cb) == 3 + @test popfirst!(cb) == 4 + @test popfirst!(cb) == 5 + end -@testset "overwrite=true and overwrite=false" begin - cb = CircularBuffer{Int}(2) - @test empty!(cb) === cb - @test push!(cb, 1; overwrite=true) === cb - @test push!(cb, 2; overwrite=true) === cb - @test_throws BoundsError push!(cb, 3; overwrite=false) - @test push!(cb, 4; overwrite=true) === cb - @test popfirst!(cb) == 2 - @test popfirst!(cb) == 4 - @test_throws BoundsError popfirst!(cb) -end + @testset "initial clear does not affect wrapping around" begin + cb = CircularBuffer{Int}(2) + @test empty!(cb) === cb + @test push!(cb, 1) === cb + @test push!(cb, 2) === cb + @test push!(cb, 3; overwrite=true) === cb + @test push!(cb, 4; overwrite=true) === cb + @test popfirst!(cb) == 3 + @test popfirst!(cb) == 4 + @test_throws BoundsError popfirst!(cb) + end -@testset "type parameter" begin - cb = CircularBuffer{Int}(1) - @test_throws Exception push!(cb, "0") - cb = CircularBuffer{String}(1) - @test_throws Exception push!(cb, 0) - @test push!(cb, "0") === cb - @test popfirst!(cb) == "0" -end + @testset "overwrite=true and overwrite=false" begin + cb = CircularBuffer{Int}(2) + @test empty!(cb) === cb + @test push!(cb, 1; overwrite=true) === cb + @test push!(cb, 2; overwrite=true) === cb + @test_throws BoundsError push!(cb, 3; overwrite=false) + @test push!(cb, 4; overwrite=true) === cb + @test popfirst!(cb) == 2 + @test popfirst!(cb) == 4 + @test_throws BoundsError popfirst!(cb) + end -# Uncomment the following line to enable bonus tests. -# enable_bonus_tests = true + @testset "type parameter" begin + cb = CircularBuffer{Int}(1) + @test_throws Exception push!(cb, "0") + cb = CircularBuffer{String}(1) + @test_throws Exception push!(cb, 0) + @test push!(cb, "0") === cb + @test popfirst!(cb) == "0" + end -if @isdefined(enable_bonus_tests) && enable_bonus_tests - println("\nBonus tests enabled.\n") + # Uncomment the following line to enable bonus tests. + # enable_bonus_tests = true - @testset "is subtype of AbstractVector" begin - @test CircularBuffer <: AbstractVector - end + if @isdefined(enable_bonus_tests) && enable_bonus_tests + println("\nBonus tests enabled.\n") - # Copied from DataStructures.jl and slightly modified. - @testset "Bonus test set taken from DataStructures.jl (CircularBuffer)" begin - @testset "Core Functionality" begin - cb = CircularBuffer{Int}(5) - @testset "When empty" begin - @test length(cb) == 0 - @test capacity(cb) == 5 - @test_throws BoundsError first(cb) - @test_throws BoundsError last(cb) - @test isempty(cb) == true - @test isfull(cb) == false - @test eltype(cb) == Int - @test eltype(typeof(cb)) == Int - end + @testset "is subtype of AbstractVector" begin + @test CircularBuffer <: AbstractVector + end - @testset "With 1 element" begin - push!(cb, 1) - @test length(cb) == 1 - @test capacity(cb) == 5 - @test isfull(cb) == false - @test first(cb) == last(cb) + # Copied from DataStructures.jl and slightly modified. + @testset "Bonus test set taken from DataStructures.jl (CircularBuffer)" begin + @testset "Core Functionality" begin + cb = CircularBuffer{Int}(5) + @testset "When empty" begin + @test length(cb) == 0 + @test capacity(cb) == 5 + @test_throws BoundsError first(cb) + @test_throws BoundsError last(cb) + @test isempty(cb) == true + @test isfull(cb) == false + @test eltype(cb) == Int + @test eltype(typeof(cb)) == Int + end + + @testset "With 1 element" begin + push!(cb, 1) + @test length(cb) == 1 + @test capacity(cb) == 5 + @test isfull(cb) == false + @test first(cb) == last(cb) + end + + @testset "Appending many elements" begin + append!(cb, 2:8; overwrite=true) + @test length(cb) == capacity(cb) + @test size(cb) == (length(cb),) + @test isempty(cb) == false + @test isfull(cb) == true + @test convert(Array, cb) == Int[4,5,6,7,8] + end + + @testset "getindex" begin + @test cb[1] == 4 + @test cb[2] == 5 + @test cb[3] == 6 + @test cb[4] == 7 + @test cb[5] == 8 + @test_throws BoundsError cb[6] + @test_throws BoundsError cb[3:6] + @test cb[3:4] == Int[6,7] + @test cb[[1,5]] == Int[4,8] + @test first(cb) == 4 + @test last(cb) == 8 + end + + @testset "setindex" begin + cb[3] = 999 + @test convert(Array, cb) == Int[4,5,999,7,8] + end end - @testset "Appending many elements" begin - append!(cb, 2:8; overwrite=true) - @test length(cb) == capacity(cb) - @test size(cb) == (length(cb),) - @test isempty(cb) == false - @test isfull(cb) == true - @test convert(Array, cb) == Int[4,5,6,7,8] + @testset "pushfirst" begin + cb = CircularBuffer{Int}(5) # New, empty one for full test coverage + for i in -5:5 + pushfirst!(cb, i; overwrite=true) + end + arr = convert(Array, cb) + @test arr == Int[5, 4, 3, 2, 1] + for (idx, n) in enumerate(5:1) + @test arr[idx] == n + end end - @testset "getindex" begin - @test cb[1] == 4 - @test cb[2] == 5 - @test cb[3] == 6 - @test cb[4] == 7 - @test cb[5] == 8 - @test_throws BoundsError cb[6] - @test_throws BoundsError cb[3:6] - @test cb[3:4] == Int[6,7] - @test cb[[1,5]] == Int[4,8] - @test first(cb) == 4 - @test last(cb) == 8 + @testset "Issue 429" begin + cb = CircularBuffer{Int}(5) + map(x -> pushfirst!(cb, x; overwrite=true), 1:8) + pop!(cb) + pushfirst!(cb, 9) + arr = convert(Array, cb) + @test arr == Int[9, 8, 7, 6, 5] end - @testset "setindex" begin - cb[3] = 999 - @test convert(Array, cb) == Int[4,5,999,7,8] + @testset "Issue 379" begin + cb = CircularBuffer{Int}(5) + pushfirst!(cb, 1) + @test cb == [1] + pushfirst!(cb, 2) + @test cb == [2, 1] end - end - @testset "pushfirst" begin - cb = CircularBuffer{Int}(5) # New, empty one for full test coverage - for i in -5:5 - pushfirst!(cb, i; overwrite=true) - end - arr = convert(Array, cb) - @test arr == Int[5, 4, 3, 2, 1] - for (idx, n) in enumerate(5:1) - @test arr[idx] == n + @testset "empty!" begin + cb = CircularBuffer{Int}(5) + push!(cb, 13) + empty!(cb) + @test length(cb) == 0 end - end - - @testset "Issue 429" begin - cb = CircularBuffer{Int}(5) - map(x -> pushfirst!(cb, x; overwrite=true), 1:8) - pop!(cb) - pushfirst!(cb, 9) - arr = convert(Array, cb) - @test arr == Int[9, 8, 7, 6, 5] - end - - @testset "Issue 379" begin - cb = CircularBuffer{Int}(5) - pushfirst!(cb, 1) - @test cb == [1] - pushfirst!(cb, 2) - @test cb == [2, 1] - end - @testset "empty!" begin - cb = CircularBuffer{Int}(5) - push!(cb, 13) - empty!(cb) - @test length(cb) == 0 - end - - @testset "pop!" begin - cb = CircularBuffer{Int}(5) - for i in 0:5 # one extra to force wraparound - push!(cb, i; overwrite=true) - end - for j in 5:-1:1 - @test pop!(cb) == j - @test convert(Array, cb) == collect(1:j-1) + @testset "pop!" begin + cb = CircularBuffer{Int}(5) + for i in 0:5 # one extra to force wraparound + push!(cb, i; overwrite=true) + end + for j in 5:-1:1 + @test pop!(cb) == j + @test convert(Array, cb) == collect(1:j-1) + end + @test isempty(cb) + @test_throws BoundsError pop!(cb) end - @test isempty(cb) - @test_throws BoundsError pop!(cb) - end - @testset "popfirst!" begin - cb = CircularBuffer{Int}(5) - for i in 0:5 # one extra to force wraparound - push!(cb, i; overwrite=true) - end - for j in 1:5 - @test popfirst!(cb) == j - @test convert(Array, cb) == collect(j+1:5) + @testset "popfirst!" begin + cb = CircularBuffer{Int}(5) + for i in 0:5 # one extra to force wraparound + push!(cb, i; overwrite=true) + end + for j in 1:5 + @test popfirst!(cb) == j + @test convert(Array, cb) == collect(j+1:5) + end + @test isempty(cb) + @test_throws BoundsError popfirst!(cb) end - @test isempty(cb) - @test_throws BoundsError popfirst!(cb) end end end - diff --git a/exercises/practice/clock/.meta/config.json b/exercises/practice/clock/.meta/config.json index 96960cf5..047204c4 100644 --- a/exercises/practice/clock/.meta/config.json +++ b/exercises/practice/clock/.meta/config.json @@ -17,6 +17,5 @@ ".meta/example.jl" ] }, - "source": "Pairing session with Erin Drummond", - "source_url": "https://twitter.com/ebdrummond" + "source": "Pairing session with Erin Drummond" } diff --git a/exercises/practice/clock/runtests.jl b/exercises/practice/clock/runtests.jl index e5def1b4..db3395be 100644 --- a/exercises/practice/clock/runtests.jl +++ b/exercises/practice/clock/runtests.jl @@ -2,189 +2,191 @@ using Dates, Test include("clock.jl") -@testset "Create a new clock with an initial time" begin - # on the hour - @test Clock(8, 0) == Clock(8, 0) +@testset verbose = true "tests" begin + @testset "Create a new clock with an initial time" begin + # on the hour + @test Clock(8, 0) == Clock(8, 0) - # past the hour - @test Clock(11, 9) == Clock(11, 9) + # past the hour + @test Clock(11, 9) == Clock(11, 9) - # midnight is zero hours - @test Clock(24, 0) == Clock(0, 0) + # midnight is zero hours + @test Clock(24, 0) == Clock(0, 0) - # hour rolls over - @test Clock(25, 0) == Clock(1, 0) + # hour rolls over + @test Clock(25, 0) == Clock(1, 0) - # hour rolls over continuously - @test Clock(100, 0) == Clock(4, 0) + # hour rolls over continuously + @test Clock(100, 0) == Clock(4, 0) - # sixty minutes is next hour - @test Clock(1, 60) == Clock(2, 0) + # sixty minutes is next hour + @test Clock(1, 60) == Clock(2, 0) - # minutes roll over - @test Clock(0, 160) == Clock(2, 40) + # minutes roll over + @test Clock(0, 160) == Clock(2, 40) - # minutes roll over continuously - @test Clock(0, 1723) == Clock(4, 43) + # minutes roll over continuously + @test Clock(0, 1723) == Clock(4, 43) - # hour and minutes roll over - @test Clock(25, 160) == Clock(3, 40) + # hour and minutes roll over + @test Clock(25, 160) == Clock(3, 40) - # hour and minutes roll over continuously - @test Clock(201, 3001) == Clock(11, 1) + # hour and minutes roll over continuously + @test Clock(201, 3001) == Clock(11, 1) - # hour and minutes roll over to exactly midnight - @test Clock(72, 8640) == Clock(0, 0) + # hour and minutes roll over to exactly midnight + @test Clock(72, 8640) == Clock(0, 0) - # negative hour - @test Clock(-1, 15) == Clock(23, 15) + # negative hour + @test Clock(-1, 15) == Clock(23, 15) - # negative hour rolls over - @test Clock(-25, 0) == Clock(23, 0) + # negative hour rolls over + @test Clock(-25, 0) == Clock(23, 0) - # negative hour rolls over continuously - @test Clock(-91, 0) == Clock(5, 0) + # negative hour rolls over continuously + @test Clock(-91, 0) == Clock(5, 0) - # negative minutes - @test Clock(1, -40) == Clock(0, 20) + # negative minutes + @test Clock(1, -40) == Clock(0, 20) - # negative minutes roll over - @test Clock(1, -160) == Clock(22, 20) + # negative minutes roll over + @test Clock(1, -160) == Clock(22, 20) - # negative minutes roll over continuously - @test Clock(1, -4820) == Clock(16, 40) + # negative minutes roll over continuously + @test Clock(1, -4820) == Clock(16, 40) - # negative sixty minutes is previous hour - @test Clock(2, -60) == Clock(1, 0) + # negative sixty minutes is previous hour + @test Clock(2, -60) == Clock(1, 0) - # negative hour and minutes both roll over - @test Clock(-25, -160) == Clock(20, 20) + # negative hour and minutes both roll over + @test Clock(-25, -160) == Clock(20, 20) - # negative hour and minutes both roll over continuously - @test Clock(-121, -5810) == Clock(22, 10) -end + # negative hour and minutes both roll over continuously + @test Clock(-121, -5810) == Clock(22, 10) + end -@testset "Add minutes" begin - # add minutes - @test Clock(10, 0) + Dates.Minute(3) == Clock(10, 3) + @testset "Add minutes" begin + # add minutes + @test Clock(10, 0) + Dates.Minute(3) == Clock(10, 3) - # add no minutes - @test Clock(6, 41) + Dates.Minute(0) == Clock(6, 41) + # add no minutes + @test Clock(6, 41) + Dates.Minute(0) == Clock(6, 41) - # add to next hour - @test Clock(0, 45) + Dates.Minute(40) == Clock(1, 25) + # add to next hour + @test Clock(0, 45) + Dates.Minute(40) == Clock(1, 25) - # add more than one hour - @test Clock(10, 0) + Dates.Minute(61) == Clock(11, 1) + # add more than one hour + @test Clock(10, 0) + Dates.Minute(61) == Clock(11, 1) - # add more than two hours with carry - @test Clock(0, 45) + Dates.Minute(160) == Clock(3, 25) + # add more than two hours with carry + @test Clock(0, 45) + Dates.Minute(160) == Clock(3, 25) - # add across midnight - @test Clock(23, 59) + Dates.Minute(2) == Clock(0, 1) + # add across midnight + @test Clock(23, 59) + Dates.Minute(2) == Clock(0, 1) - # add more than one day (1500 min = 25 hrs) - @test Clock(5, 32) + Dates.Minute(1500) == Clock(6, 32) + # add more than one day (1500 min = 25 hrs) + @test Clock(5, 32) + Dates.Minute(1500) == Clock(6, 32) - # add more than two days - @test Clock(1, 1) + Dates.Minute(3500) == Clock(11, 21) -end + # add more than two days + @test Clock(1, 1) + Dates.Minute(3500) == Clock(11, 21) + end -@testset "Subtract minutes" begin - # subtract minutes - @test Clock(10, 3) - Dates.Minute(3) == Clock(10, 0) + @testset "Subtract minutes" begin + # subtract minutes + @test Clock(10, 3) - Dates.Minute(3) == Clock(10, 0) - # subtract to previous hour - @test Clock(10, 3) - Dates.Minute(30) == Clock(9, 33) + # subtract to previous hour + @test Clock(10, 3) - Dates.Minute(30) == Clock(9, 33) - # subtract more than an hour - @test Clock(10, 3) - Dates.Minute(70) == Clock(8, 53) + # subtract more than an hour + @test Clock(10, 3) - Dates.Minute(70) == Clock(8, 53) - # subtract across midnight - @test Clock(0, 3) - Dates.Minute(4) == Clock(23, 59) + # subtract across midnight + @test Clock(0, 3) - Dates.Minute(4) == Clock(23, 59) - # subtract more than two hours - @test Clock(0, 0) - Dates.Minute(160) == Clock(21, 20) + # subtract more than two hours + @test Clock(0, 0) - Dates.Minute(160) == Clock(21, 20) - # subtract more than two hours with borrow - @test Clock(6, 15) - Dates.Minute(160) == Clock(3, 35) + # subtract more than two hours with borrow + @test Clock(6, 15) - Dates.Minute(160) == Clock(3, 35) - # subtract more than one day (1500 min = 25 hrs) - @test Clock(5, 32) - Dates.Minute(1500) == Clock(4, 32) + # subtract more than one day (1500 min = 25 hrs) + @test Clock(5, 32) - Dates.Minute(1500) == Clock(4, 32) - # subtract more than two days - @test Clock(2, 20) - Dates.Minute(3000) == Clock(0, 20) -end + # subtract more than two days + @test Clock(2, 20) - Dates.Minute(3000) == Clock(0, 20) + end -@testset "Compare two clocks for equality" begin - # clocks with same time - @test Clock(15, 37) == Clock(15, 37) + @testset "Compare two clocks for equality" begin + # clocks with same time + @test Clock(15, 37) == Clock(15, 37) - # clocks a minute apart - @test Clock(15, 36) != Clock(15, 37) + # clocks a minute apart + @test Clock(15, 36) != Clock(15, 37) - # clocks an hour apart - @test Clock(14, 37) != Clock(15, 37) + # clocks an hour apart + @test Clock(14, 37) != Clock(15, 37) - # clocks with hour overflow - @test Clock(10, 37) == Clock(34, 37) + # clocks with hour overflow + @test Clock(10, 37) == Clock(34, 37) - # clocks with hour overflow by several days - @test Clock(3, 11) == Clock(99, 11) + # clocks with hour overflow by several days + @test Clock(3, 11) == Clock(99, 11) - # clocks with negative hour - @test Clock(22, 40) == Clock(-2, 40) + # clocks with negative hour + @test Clock(22, 40) == Clock(-2, 40) - # clocks with negative hour that wraps - @test Clock(17, 3) == Clock(-31, 3) + # clocks with negative hour that wraps + @test Clock(17, 3) == Clock(-31, 3) - # clocks with negative hour that wraps multiple times - @test Clock(13, 49) == Clock(-83, 49) + # clocks with negative hour that wraps multiple times + @test Clock(13, 49) == Clock(-83, 49) - # clocks with minute overflow - @test Clock(0, 1) == Clock(0, 1441) + # clocks with minute overflow + @test Clock(0, 1) == Clock(0, 1441) - # clocks with minute overflow by several days - @test Clock(2, 2) == Clock(2, 4322) + # clocks with minute overflow by several days + @test Clock(2, 2) == Clock(2, 4322) - # clocks with negative minute - @test Clock(2, 40) == Clock(3, -20) + # clocks with negative minute + @test Clock(2, 40) == Clock(3, -20) - # clocks with negative minute that wraps - @test Clock(4, 10) == Clock(5, -1490) + # clocks with negative minute that wraps + @test Clock(4, 10) == Clock(5, -1490) - # clocks with negative minute that wraps multiple times - @test Clock(6, 15) == Clock(6, -4305) + # clocks with negative minute that wraps multiple times + @test Clock(6, 15) == Clock(6, -4305) - # clocks with negative hours and minutes - @test Clock(7, 32) == Clock(-12, -268) + # clocks with negative hours and minutes + @test Clock(7, 32) == Clock(-12, -268) - # clocks with negative hours and minutes that wrap - @test Clock(18, 7) == Clock(-54, -11513) + # clocks with negative hours and minutes that wrap + @test Clock(18, 7) == Clock(-54, -11513) - # full clock and zeroed clock - @test Clock(24, 0) == Clock(0, 0) -end + # full clock and zeroed clock + @test Clock(24, 0) == Clock(0, 0) + end -@testset "displaying clocks" begin - @test sprint(show, Clock(8, 0)) == "\"08:00\"" - @test sprint(show, Clock(11, 9)) == "\"11:09\"" - @test sprint(show, Clock(24, 0)) == "\"00:00\"" - @test sprint(show, Clock(25, 0)) == "\"01:00\"" - @test sprint(show, Clock(100, 0)) == "\"04:00\"" - @test sprint(show, Clock(1, 60)) == "\"02:00\"" - @test sprint(show, Clock(0, 160)) == "\"02:40\"" - @test sprint(show, Clock(0, 1723)) == "\"04:43\"" - @test sprint(show, Clock(25, 160)) == "\"03:40\"" - @test sprint(show, Clock(201, 3001)) == "\"11:01\"" - @test sprint(show, Clock(72, 8640)) == "\"00:00\"" - @test sprint(show, Clock(-1, 15)) == "\"23:15\"" - @test sprint(show, Clock(-25, 0)) == "\"23:00\"" - @test sprint(show, Clock(-91, 0)) == "\"05:00\"" - @test sprint(show, Clock(1, -40)) == "\"00:20\"" - @test sprint(show, Clock(1, -160)) == "\"22:20\"" - @test sprint(show, Clock(1, -4820)) == "\"16:40\"" - @test sprint(show, Clock(2, -60)) == "\"01:00\"" - @test sprint(show, Clock(-25, -160)) == "\"20:20\"" - @test sprint(show, Clock(-121, -5810)) == "\"22:10\"" + @testset "displaying clocks" begin + @test sprint(show, Clock(8, 0)) == "\"08:00\"" + @test sprint(show, Clock(11, 9)) == "\"11:09\"" + @test sprint(show, Clock(24, 0)) == "\"00:00\"" + @test sprint(show, Clock(25, 0)) == "\"01:00\"" + @test sprint(show, Clock(100, 0)) == "\"04:00\"" + @test sprint(show, Clock(1, 60)) == "\"02:00\"" + @test sprint(show, Clock(0, 160)) == "\"02:40\"" + @test sprint(show, Clock(0, 1723)) == "\"04:43\"" + @test sprint(show, Clock(25, 160)) == "\"03:40\"" + @test sprint(show, Clock(201, 3001)) == "\"11:01\"" + @test sprint(show, Clock(72, 8640)) == "\"00:00\"" + @test sprint(show, Clock(-1, 15)) == "\"23:15\"" + @test sprint(show, Clock(-25, 0)) == "\"23:00\"" + @test sprint(show, Clock(-91, 0)) == "\"05:00\"" + @test sprint(show, Clock(1, -40)) == "\"00:20\"" + @test sprint(show, Clock(1, -160)) == "\"22:20\"" + @test sprint(show, Clock(1, -4820)) == "\"16:40\"" + @test sprint(show, Clock(2, -60)) == "\"01:00\"" + @test sprint(show, Clock(-25, -160)) == "\"20:20\"" + @test sprint(show, Clock(-121, -5810)) == "\"22:10\"" + end end diff --git a/exercises/practice/collatz-conjecture/.docs/instructions.md b/exercises/practice/collatz-conjecture/.docs/instructions.md index f8c76e7f..ba060483 100644 --- a/exercises/practice/collatz-conjecture/.docs/instructions.md +++ b/exercises/practice/collatz-conjecture/.docs/instructions.md @@ -2,10 +2,11 @@ The Collatz Conjecture or 3x+1 problem can be summarized as follows: -Take any positive integer n. If n is even, divide n by 2 to get n / 2. If n is -odd, multiply n by 3 and add 1 to get 3n + 1. Repeat the process indefinitely. -The conjecture states that no matter which number you start with, you will -always reach 1 eventually. +Take any positive integer n. +If n is even, divide n by 2 to get n / 2. +If n is odd, multiply n by 3 and add 1 to get 3n + 1. +Repeat the process indefinitely. +The conjecture states that no matter which number you start with, you will always reach 1 eventually. Given a number n, return the number of steps required to reach 1. @@ -24,4 +25,5 @@ Starting with n = 12, the steps would be as follows: 8. 2 9. 1 -Resulting in 9 steps. So for input n = 12, the return value would be 9. +Resulting in 9 steps. +So for input n = 12, the return value would be 9. diff --git a/exercises/practice/collatz-conjecture/.meta/config.json b/exercises/practice/collatz-conjecture/.meta/config.json index 927ac0e9..ae0dd042 100644 --- a/exercises/practice/collatz-conjecture/.meta/config.json +++ b/exercises/practice/collatz-conjecture/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Calculate the number of steps to reach 1 using the Collatz conjecture", + "blurb": "Calculate the number of steps to reach 1 using the Collatz conjecture.", "authors": [ "SaschaMann" ], diff --git a/exercises/practice/collatz-conjecture/runtests.jl b/exercises/practice/collatz-conjecture/runtests.jl index 90bd274d..c7b05f1a 100644 --- a/exercises/practice/collatz-conjecture/runtests.jl +++ b/exercises/practice/collatz-conjecture/runtests.jl @@ -2,7 +2,7 @@ using Test include("collatz-conjecture.jl") -@testset verbose = true "Collatz Conjecture" begin +@testset verbose = true "tests" begin # canonical data @testset "Canonical data" begin @test collatz_steps(1) == 0 diff --git a/exercises/practice/complex-numbers/.docs/instructions.md b/exercises/practice/complex-numbers/.docs/instructions.md index 267ff615..50b19aed 100644 --- a/exercises/practice/complex-numbers/.docs/instructions.md +++ b/exercises/practice/complex-numbers/.docs/instructions.md @@ -22,8 +22,8 @@ Dividing a complex number `a + i * b` by another `c + i * d` gives: Raising e to a complex exponent can be expressed as `e^(a + i * b) = e^a * e^(i * b)`, the last term of which is given by Euler's formula `e^(i * b) = cos(b) + i * sin(b)`. Implement the following operations: - - addition, subtraction, multiplication and division of two complex numbers, - - conjugate, absolute value, exponent of a given complex number. +- addition, subtraction, multiplication and division of two complex numbers, +- conjugate, absolute value, exponent of a given complex number. Assume the programming language you are using does not have an implementation of complex numbers. diff --git a/exercises/practice/complex-numbers/runtests.jl b/exercises/practice/complex-numbers/runtests.jl index 1179bbc8..c5d30aa9 100644 --- a/exercises/practice/complex-numbers/runtests.jl +++ b/exercises/practice/complex-numbers/runtests.jl @@ -2,7 +2,7 @@ using Test include("complex-numbers.jl") -@testset verbose = true "Complex Numbers" begin +@testset verbose = true "tests" begin @test ComplexNumber <: Number @test ComplexNumber(0, 1)^2 == ComplexNumber(-1, 0) diff --git a/exercises/practice/connect/.docs/instructions.md b/exercises/practice/connect/.docs/instructions.md new file mode 100644 index 00000000..7f34bfa8 --- /dev/null +++ b/exercises/practice/connect/.docs/instructions.md @@ -0,0 +1,27 @@ +# Instructions + +Compute the result for a game of Hex / Polygon. + +The abstract boardgame known as [Hex][hex] / Polygon / CON-TAC-TIX is quite simple in rules, though complex in practice. +Two players place stones on a parallelogram with hexagonal fields. +The player to connect his/her stones to the opposite side first wins. +The four sides of the parallelogram are divided between the two players (i.e. one player gets assigned a side and the side directly opposite it and the other player gets assigned the two other sides). + +Your goal is to build a program that given a simple representation of a board computes the winner (or lack thereof). +Note that all games need not be "fair". +(For example, players may have mismatched piece counts or the game's board might have a different width and height.) + +The boards look like this: + +```text +. O . X . + . X X O . + O O O X . + . X O X O + X O O O X +``` + +"Player `O`" plays from top to bottom, "Player `X`" plays from left to right. +In the above example `O` has made a connection from left to right but nobody has won since `O` didn't connect top and bottom. + +[hex]: https://en.wikipedia.org/wiki/Hex_%28board_game%29 diff --git a/exercises/practice/connect/.meta/config.json b/exercises/practice/connect/.meta/config.json new file mode 100644 index 00000000..8381b281 --- /dev/null +++ b/exercises/practice/connect/.meta/config.json @@ -0,0 +1,15 @@ +{ + "authors": [], + "files": { + "solution": [ + "connect.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Compute the result for a game of Hex / Polygon." +} diff --git a/exercises/practice/connect/.meta/example.jl b/exercises/practice/connect/.meta/example.jl new file mode 100644 index 00000000..d94c9470 --- /dev/null +++ b/exercises/practice/connect/.meta/example.jl @@ -0,0 +1,35 @@ +#= +The approach below is essentially an implementation of bfs/floodfill. + - connector does the bfs, using the six possible steps and tracking which have been seen, returns true/false + depending on if there is a path is found connecting two edges of the board. + - wins finds starting points for connector, and returns true if the provided points results in a win. + - connect processes the board to separate points into coordinates for wins to filter through and then returns the winner, + if there is one. The coordinates have been transposed for O, so that wins and connector can work with X or O equally. +=# +function connector(unseen, points, dim, nextpoints=Set()) + for point in points, step in ((1,0),(-1,0),(0,1),(0,-1),(1,-1),(-1,1)) + nextpoint = point .+ step + if nextpoint ∈ unseen + first(nextpoint) == dim && return true + push!(nextpoints, nextpoint) + delete!(unseen, nextpoint) + end + end + !isempty(nextpoints) && connector(unseen, nextpoints, dim) +end + +function wins(points, dim) + for point in filter(isone ∘ first, points) + (isone(dim) || connector(setdiff(points, Set([point])), Set([point]), dim)) && return true + end + false +end + +function connect(board) + newboard, Xs, Os = hcat(split.(strip.(board), " ")...), Set(), Set() + for i in axes(newboard,1), j in axes(newboard,2) + newboard[i,j] == "X" && push!(Xs, (i,j)) + newboard[i,j] == "O" && push!(Os, (j,i)) + end + wins(Xs, first(size(newboard))) ? "X" : wins(Os, last(size(newboard))) ? "O" : "" +end diff --git a/exercises/practice/connect/.meta/tests.toml b/exercises/practice/connect/.meta/tests.toml new file mode 100644 index 00000000..6ada8773 --- /dev/null +++ b/exercises/practice/connect/.meta/tests.toml @@ -0,0 +1,40 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[6eff0df4-3e92-478d-9b54-d3e8b354db56] +description = "an empty board has no winner" + +[298b94c0-b46d-45d8-b34b-0fa2ea71f0a4] +description = "X can win on a 1x1 board" + +[763bbae0-cb8f-4f28-bc21-5be16a5722dc] +description = "O can win on a 1x1 board" + +[819fde60-9ae2-485e-a024-cbb8ea68751b] +description = "only edges does not make a winner" + +[2c56a0d5-9528-41e5-b92b-499dfe08506c] +description = "illegal diagonal does not make a winner" + +[41cce3ef-43ca-4963-970a-c05d39aa1cc1] +description = "nobody wins crossing adjacent angles" + +[cd61c143-92f6-4a8d-84d9-cb2b359e226b] +description = "X wins crossing from left to right" + +[73d1eda6-16ab-4460-9904-b5f5dd401d0b] +description = "O wins crossing from top to bottom" + +[c3a2a550-944a-4637-8b3f-1e1bf1340a3d] +description = "X wins using a convoluted path" + +[17e76fa8-f731-4db7-92ad-ed2a285d31f3] +description = "X wins using a spiral path" diff --git a/exercises/practice/connect/connect.jl b/exercises/practice/connect/connect.jl new file mode 100644 index 00000000..020de71a --- /dev/null +++ b/exercises/practice/connect/connect.jl @@ -0,0 +1,3 @@ +function connect(board) + # Your code here +end diff --git a/exercises/practice/connect/runtests.jl b/exercises/practice/connect/runtests.jl new file mode 100644 index 00000000..e720c2dd --- /dev/null +++ b/exercises/practice/connect/runtests.jl @@ -0,0 +1,117 @@ +using Test + +include("connect.jl") + +@testset verbose = true "tests" begin + @testset "an empty board has no winner" begin + board = [ + ". . . . .", + " . . . . .", + " . . . . .", + " . . . . .", + " . . . . ." + ] + @test connect(board) == "" + end + + @testset "an empty 1x1 board has no winner" begin + board = [ + "." + ] + @test connect(board) == "" + end + + @testset "X can win on a 1x1 board" begin + board = [ + "X" + ] + @test connect(board) == "X" + end + + @testset "O can win on a 1x1 board" begin + board = [ + "O" + ] + @test connect(board) == "O" + end + + @testset "only edges does not make a winner" begin + board = [ + "O O O X", + " X . . X", + " X . . X", + " X O O O" + ] + @test connect(board) == "" + end + + @testset "illegal diagonal does not make a winner" begin + board = [ + "X O . .", + " O X X X", + " O X O .", + " . O X .", + " X X O O" + ] + @test connect(board) == "" + end + + @testset "nobody wins crossing adjacent angles" begin + board = [ + "X . . .", + " . X O .", + " O . X O", + " . O . X", + " . . O ." + ] + @test connect(board) == "" + end + + @testset "X wins crossing from left to right" begin + board = [ + ". O . .", + " O X X X", + " O X O .", + " X X O X", + " . O X ." + ] + @test connect(board) == "X" + end + + @testset "O wins crossing from top to bottom" begin + board = [ + ". O . .", + " O X X X", + " O O O .", + " X X O X", + " . O X ." + ] + @test connect(board) == "O" + end + + @testset "X wins using a convoluted path" begin + board = [ + ". X X . .", + " X . X . X", + " . X . X .", + " . X X . .", + " O O O O O" + ] + @test connect(board) == "X" + end + + @testset "X wins using a spiral path" begin + board = [ + "O X X X X X X X X", + " O X O O O O O O O", + " O X O X X X X X O", + " O X O X O O O X O", + " O X O X X X O X O", + " O X O O O X O X O", + " O X X X X X O X O", + " O O O O O O O X O", + " X X X X X X X X O" + ] + @test connect(board) == "X" + end +end diff --git a/exercises/practice/custom-set/.docs/instructions.md b/exercises/practice/custom-set/.docs/instructions.md index e4931b05..33b90e28 100644 --- a/exercises/practice/custom-set/.docs/instructions.md +++ b/exercises/practice/custom-set/.docs/instructions.md @@ -2,7 +2,6 @@ Create a custom set type. -Sometimes it is necessary to define a custom data structure of some -type, like a set. In this exercise you will define your own set. How it -works internally doesn't matter, as long as it behaves like a set of -unique elements. +Sometimes it is necessary to define a custom data structure of some type, like a set. +In this exercise you will define your own set. +How it works internally doesn't matter, as long as it behaves like a set of unique elements. diff --git a/exercises/practice/custom-set/runtests.jl b/exercises/practice/custom-set/runtests.jl index 5fd59fe9..d7467cbc 100644 --- a/exercises/practice/custom-set/runtests.jl +++ b/exercises/practice/custom-set/runtests.jl @@ -2,200 +2,202 @@ using Test include("custom-set.jl") -# canonical data -@testset "empty" begin - @test isempty(CustomSet([])) - @test !isempty(CustomSet([1])) -end - -@testset "in (contains)" begin - @test !(1 in CustomSet([])) - @test 1 in CustomSet([1, 2, 3]) - @test !(4 in CustomSet([1, 2, 3])) -end - -@testset "subset" begin - @test issubset(CustomSet([]), CustomSet([])) - @test issubset(CustomSet([]), CustomSet([1])) - @test !issubset(CustomSet([1]), CustomSet([])) - @test issubset(CustomSet([1, 2, 3]), CustomSet([1, 2, 3])) - @test issubset(CustomSet([1, 2, 3]), CustomSet([4, 1, 2, 3])) - @test !issubset(CustomSet([1, 2, 3]), CustomSet([4, 1, 3])) -end - -@testset "disjoint" begin - @test disjoint(CustomSet([]), CustomSet([])) - @test disjoint(CustomSet([]), CustomSet([1])) - @test disjoint(CustomSet([1]), CustomSet([])) - @test !disjoint(CustomSet([1, 2]), CustomSet([2, 3])) - @test disjoint(CustomSet([1, 2]), CustomSet([3, 4])) -end +@testset verbose = true "tests" begin + # canonical data + @testset "empty" begin + @test isempty(CustomSet([])) + @test !isempty(CustomSet([1])) + end -@testset "equal" begin - @test CustomSet([]) == CustomSet([]) - @test CustomSet([]) != CustomSet([1, 2, 3]) - @test CustomSet([1, 2, 3]) != CustomSet([]) - @test CustomSet([1, 2]) == CustomSet([2, 1]) - @test CustomSet([1, 2, 3]) != CustomSet([1, 2, 4]) - @test CustomSet([1, 2, 3]) != CustomSet([1, 2, 3, 4]) -end + @testset "in (contains)" begin + @test !(1 in CustomSet([])) + @test 1 in CustomSet([1, 2, 3]) + @test !(4 in CustomSet([1, 2, 3])) + end -@testset "add" begin - @test begin - custom_set = CustomSet([]) - push!(custom_set, 3) - custom_set == CustomSet([3]) + @testset "subset" begin + @test issubset(CustomSet([]), CustomSet([])) + @test issubset(CustomSet([]), CustomSet([1])) + @test !issubset(CustomSet([1]), CustomSet([])) + @test issubset(CustomSet([1, 2, 3]), CustomSet([1, 2, 3])) + @test issubset(CustomSet([1, 2, 3]), CustomSet([4, 1, 2, 3])) + @test !issubset(CustomSet([1, 2, 3]), CustomSet([4, 1, 3])) end - @test begin - custom_set = CustomSet([1, 2, 4]) - push!(custom_set, 3) - custom_set == CustomSet([1, 2, 3, 4]) + + @testset "disjoint" begin + @test disjoint(CustomSet([]), CustomSet([])) + @test disjoint(CustomSet([]), CustomSet([1])) + @test disjoint(CustomSet([1]), CustomSet([])) + @test !disjoint(CustomSet([1, 2]), CustomSet([2, 3])) + @test disjoint(CustomSet([1, 2]), CustomSet([3, 4])) end - @test begin - custom_set = CustomSet([1, 2, 3]) - push!(custom_set, 3) - custom_set == CustomSet([1, 2, 3]) + + @testset "equal" begin + @test CustomSet([]) == CustomSet([]) + @test CustomSet([]) != CustomSet([1, 2, 3]) + @test CustomSet([1, 2, 3]) != CustomSet([]) + @test CustomSet([1, 2]) == CustomSet([2, 1]) + @test CustomSet([1, 2, 3]) != CustomSet([1, 2, 4]) + @test CustomSet([1, 2, 3]) != CustomSet([1, 2, 3, 4]) end -end -@testset "intersection" begin - @testset "in-place" begin - @test begin - cs1 = CustomSet([]) - cs2 = CustomSet([]) - intersect!(cs1, cs2) - isempty(cs1) - end + @testset "add" begin @test begin - cs1 = CustomSet([]) - cs2 = CustomSet([3, 2, 5]) - intersect!(cs1, cs2) - isempty(cs1) + custom_set = CustomSet([]) + push!(custom_set, 3) + custom_set == CustomSet([3]) end @test begin - cs1 = CustomSet([1, 2, 3, 4]) - cs2 = CustomSet([]) - intersect!(cs1, cs2) - isempty(cs1) - end - @test begin - cs1 = CustomSet([1, 2, 3]) - cs2 = CustomSet([4, 5, 6]) - intersect!(cs1, cs2) - isempty(cs1) + custom_set = CustomSet([1, 2, 4]) + push!(custom_set, 3) + custom_set == CustomSet([1, 2, 3, 4]) end @test begin - cs1 = CustomSet([1, 2, 3, 4]) - cs2 = CustomSet([3, 2, 5]) - intersect!(cs1, cs2) - cs1 == CustomSet([2, 3]) + custom_set = CustomSet([1, 2, 3]) + push!(custom_set, 3) + custom_set == CustomSet([1, 2, 3]) end end - @testset "not in-place" begin - @test isempty(intersect(CustomSet([]), CustomSet([]))) - @test isempty(intersect(CustomSet([]), CustomSet([3, 2, 5]))) - @test isempty(intersect(CustomSet([1, 2, 3, 4]), CustomSet([]))) - @test isempty(intersect(CustomSet([1, 2, 3]), CustomSet([4, 5, 6]))) - @test intersect(CustomSet([1, 2, 3, 4]), CustomSet([3, 2, 5])) == CustomSet([2, 3]) - end -end -@testset "complement (difference)" begin - @testset "in-place" begin - @test begin - cs1 = CustomSet([]) - cs2 = CustomSet([]) - complement!(cs1, cs2) - isempty(cs1) - end - @test begin - cs1 = CustomSet([]) - cs2 = CustomSet([3, 2, 5]) - complement!(cs1, cs2) - isempty(cs1) + @testset "intersection" begin + @testset "in-place" begin + @test begin + cs1 = CustomSet([]) + cs2 = CustomSet([]) + intersect!(cs1, cs2) + isempty(cs1) + end + @test begin + cs1 = CustomSet([]) + cs2 = CustomSet([3, 2, 5]) + intersect!(cs1, cs2) + isempty(cs1) + end + @test begin + cs1 = CustomSet([1, 2, 3, 4]) + cs2 = CustomSet([]) + intersect!(cs1, cs2) + isempty(cs1) + end + @test begin + cs1 = CustomSet([1, 2, 3]) + cs2 = CustomSet([4, 5, 6]) + intersect!(cs1, cs2) + isempty(cs1) + end + @test begin + cs1 = CustomSet([1, 2, 3, 4]) + cs2 = CustomSet([3, 2, 5]) + intersect!(cs1, cs2) + cs1 == CustomSet([2, 3]) + end end - @test begin - cs1 = CustomSet([1, 2, 3, 4]) - cs2 = CustomSet([]) - complement!(cs1, cs2) - cs1 == CustomSet([1, 2, 3, 4]) + @testset "not in-place" begin + @test isempty(intersect(CustomSet([]), CustomSet([]))) + @test isempty(intersect(CustomSet([]), CustomSet([3, 2, 5]))) + @test isempty(intersect(CustomSet([1, 2, 3, 4]), CustomSet([]))) + @test isempty(intersect(CustomSet([1, 2, 3]), CustomSet([4, 5, 6]))) + @test intersect(CustomSet([1, 2, 3, 4]), CustomSet([3, 2, 5])) == CustomSet([2, 3]) end - @test begin - cs1 = CustomSet([3, 2, 1]) - cs2 = CustomSet([2, 4]) - complement!(cs1, cs2) - cs1 == CustomSet([1, 3]) - end - end - @testset "not in-place" begin - @test isempty(complement(CustomSet([]), CustomSet([]))) - @test isempty(complement(CustomSet([]), CustomSet([3, 2, 5]))) - @test complement(CustomSet([1, 2, 3, 4]), CustomSet([])) == CustomSet([1, 2, 3, 4]) - @test complement(CustomSet([3, 2, 1]), CustomSet([2, 4])) == CustomSet([1, 3]) end -end -@testset "union" begin - @testset "in-place" begin - @test begin - cs1 = CustomSet([]) - cs2 = CustomSet([]) - union!(cs1, cs2) - isempty(cs1) + @testset "complement (difference)" begin + @testset "in-place" begin + @test begin + cs1 = CustomSet([]) + cs2 = CustomSet([]) + complement!(cs1, cs2) + isempty(cs1) + end + @test begin + cs1 = CustomSet([]) + cs2 = CustomSet([3, 2, 5]) + complement!(cs1, cs2) + isempty(cs1) + end + @test begin + cs1 = CustomSet([1, 2, 3, 4]) + cs2 = CustomSet([]) + complement!(cs1, cs2) + cs1 == CustomSet([1, 2, 3, 4]) + end + @test begin + cs1 = CustomSet([3, 2, 1]) + cs2 = CustomSet([2, 4]) + complement!(cs1, cs2) + cs1 == CustomSet([1, 3]) + end end - @test begin - cs1 = CustomSet([]) - cs2 = CustomSet([2]) - union!(cs1, cs2) - cs1 == CustomSet([2]) + @testset "not in-place" begin + @test isempty(complement(CustomSet([]), CustomSet([]))) + @test isempty(complement(CustomSet([]), CustomSet([3, 2, 5]))) + @test complement(CustomSet([1, 2, 3, 4]), CustomSet([])) == CustomSet([1, 2, 3, 4]) + @test complement(CustomSet([3, 2, 1]), CustomSet([2, 4])) == CustomSet([1, 3]) end - @test begin - cs1 = CustomSet([1, 3]) - cs2 = CustomSet([]) - union!(cs1, cs2) - cs1 == CustomSet([1, 3]) + end + + @testset "union" begin + @testset "in-place" begin + @test begin + cs1 = CustomSet([]) + cs2 = CustomSet([]) + union!(cs1, cs2) + isempty(cs1) + end + @test begin + cs1 = CustomSet([]) + cs2 = CustomSet([2]) + union!(cs1, cs2) + cs1 == CustomSet([2]) + end + @test begin + cs1 = CustomSet([1, 3]) + cs2 = CustomSet([]) + union!(cs1, cs2) + cs1 == CustomSet([1, 3]) + end + @test begin + cs1 = CustomSet([1, 3]) + cs2 = CustomSet([2, 3]) + union!(cs1, cs2) + cs1 == CustomSet([3, 2, 1]) + end end - @test begin - cs1 = CustomSet([1, 3]) - cs2 = CustomSet([2, 3]) - union!(cs1, cs2) - cs1 == CustomSet([3, 2, 1]) + @testset "not in-place" begin + @test isempty(union(CustomSet([]), CustomSet([]))) + @test union(CustomSet([]), CustomSet([2])) == CustomSet([2]) + @test union(CustomSet([1, 3]), CustomSet([])) == CustomSet([1, 3]) + @test union(CustomSet([1, 3]), CustomSet([2, 3])) == CustomSet([3, 2, 1]) end end - @testset "not in-place" begin - @test isempty(union(CustomSet([]), CustomSet([]))) - @test union(CustomSet([]), CustomSet([2])) == CustomSet([2]) - @test union(CustomSet([1, 3]), CustomSet([])) == CustomSet([1, 3]) - @test union(CustomSet([1, 3]), CustomSet([2, 3])) == CustomSet([3, 2, 1]) - end -end -# language specific tests -@testset "implements correct abstract type" begin - @test CustomSet <: Base.AbstractSet -end + # language specific tests + @testset "implements correct abstract type" begin + @test CustomSet <: Base.AbstractSet + end -@testset "length" begin - @test length(CustomSet([])) == 0 - @test length(CustomSet([1, 2, 3])) == 3 -end + @testset "length" begin + @test length(CustomSet([])) == 0 + @test length(CustomSet([1, 2, 3])) == 3 + end -@testset "iterable" begin - @test begin - cs1 = CustomSet([1, 2, 3, 4]) - cs2 = CustomSet([]) - for element in cs1 - push!(cs2, element) + @testset "iterable" begin + @test begin + cs1 = CustomSet([1, 2, 3, 4]) + cs2 = CustomSet([]) + for element in cs1 + push!(cs2, element) + end + cs1 == cs2 end - cs1 == cs2 end -end -@testset "copy" begin - @test begin - cs1 = CustomSet([1, 2, 3]) - cs2 = copy(cs1) - push!(cs1, 4) - cs2 == CustomSet([1, 2, 3]) + @testset "copy" begin + @test begin + cs1 = CustomSet([1, 2, 3]) + cs2 = copy(cs1) + push!(cs1, 4) + cs2 == CustomSet([1, 2, 3]) + end end end diff --git a/exercises/practice/darts/.docs/instructions.md b/exercises/practice/darts/.docs/instructions.md index 6c8178ae..5e57a860 100644 --- a/exercises/practice/darts/.docs/instructions.md +++ b/exercises/practice/darts/.docs/instructions.md @@ -2,16 +2,30 @@ Write a function that returns the earned points in a single toss of a Darts game. -[Darts](https://en.wikipedia.org/wiki/Darts) is a game where players -throw darts at a [target](https://en.wikipedia.org/wiki/Darts#/media/File:Darts_in_a_dartboard.jpg). +[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: -* 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. +![Our dart scoreboard with values from a complete miss to a bullseye](https://assets.exercism.org/images/exercises/darts/darts-scoreboard.svg) -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](http://mathworld.wolfram.com/ConcentricCircles.html)) defined by the coordinates (0, 0). +- 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. -Write a function that given a point in the target (defined by its `real` Cartesian coordinates `x` and `y`), returns the correct amount earned by a dart landing at that point. +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). + +Write a function that given a point in the target (defined by its [Cartesian coordinates][cartesian-coordinates] `x` and `y`, where `x` and `y` are [real][real-numbers]), returns the correct amount 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 diff --git a/exercises/practice/darts/.meta/config.json b/exercises/practice/darts/.meta/config.json index d061ca9e..942eb1fa 100644 --- a/exercises/practice/darts/.meta/config.json +++ b/exercises/practice/darts/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Write a function that returns the earned points in a single toss of a Darts game", + "blurb": "Write a function that returns the earned points in a single toss of a Darts game.", "authors": [ "vyu" ], diff --git a/exercises/practice/darts/runtests.jl b/exercises/practice/darts/runtests.jl index d07f062d..6a745127 100644 --- a/exercises/practice/darts/runtests.jl +++ b/exercises/practice/darts/runtests.jl @@ -2,7 +2,7 @@ using Test include("darts.jl") -@testset verbose = true "Darts" begin +@testset verbose = true "tests" begin @testset "Missed target" begin @test score(-9, 9) == 0 end diff --git a/exercises/practice/difference-of-squares/.docs/instructions.md b/exercises/practice/difference-of-squares/.docs/instructions.md index c3999e86..39c38b50 100644 --- a/exercises/practice/difference-of-squares/.docs/instructions.md +++ b/exercises/practice/difference-of-squares/.docs/instructions.md @@ -8,10 +8,7 @@ The square of the sum of the first ten natural numbers is 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. +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. +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. diff --git a/exercises/practice/difference-of-squares/.meta/config.json b/exercises/practice/difference-of-squares/.meta/config.json index a6c0cc4c..d09b038a 100644 --- a/exercises/practice/difference-of-squares/.meta/config.json +++ b/exercises/practice/difference-of-squares/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "Problem 6 at Project Euler", - "source_url": "http://projecteuler.net/problem=6" + "source_url": "https://projecteuler.net/problem=6" } diff --git a/exercises/practice/difference-of-squares/runtests.jl b/exercises/practice/difference-of-squares/runtests.jl index 45c3061d..16d3e95a 100644 --- a/exercises/practice/difference-of-squares/runtests.jl +++ b/exercises/practice/difference-of-squares/runtests.jl @@ -2,7 +2,7 @@ using Test include("difference-of-squares.jl") -@testset verbose = true "Difference of Squares" begin +@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 diff --git a/exercises/practice/dnd-character/runtests.jl b/exercises/practice/dnd-character/runtests.jl index 827be3e5..58d283ed 100644 --- a/exercises/practice/dnd-character/runtests.jl +++ b/exercises/practice/dnd-character/runtests.jl @@ -12,40 +12,42 @@ function ischaracter(c) c.hitpoints == 10 + modifier(c.constitution) end -@testset "ability modifier" begin - @test modifier(3) == -4 - @test modifier(4) == -3 - @test modifier(5) == -3 - @test modifier(6) == -2 - @test modifier(7) == -2 - @test modifier(8) == -1 - @test modifier(9) == -1 - @test modifier(10) == 0 - @test modifier(11) == 0 - @test modifier(12) == 1 - @test modifier(13) == 1 - @test modifier(14) == 2 - @test modifier(15) == 2 - @test modifier(16) == 3 - @test modifier(17) == 3 - @test modifier(18) == 4 -end +@testset verbose = true "tests" begin + @testset "ability modifier" begin + @test modifier(3) == -4 + @test modifier(4) == -3 + @test modifier(5) == -3 + @test modifier(6) == -2 + @test modifier(7) == -2 + @test modifier(8) == -1 + @test modifier(9) == -1 + @test modifier(10) == 0 + @test modifier(11) == 0 + @test modifier(12) == 1 + @test modifier(13) == 1 + @test modifier(14) == 2 + @test modifier(15) == 2 + @test modifier(16) == 3 + @test modifier(17) == 3 + @test modifier(18) == 4 + end -@testset "random ability is within range" begin - abil = ability() - @test abil >= 3 && abil <= 18 -end + @testset "random ability is within range" begin + abil = ability() + @test abil >= 3 && abil <= 18 + end -@testset "random character is valid" begin - characters = DNDCharacter[] + @testset "random character is valid" begin + characters = DNDCharacter[] - for i=1:10 - c = DNDCharacter() - @testset "random character is valid and unique in history" begin - @test ischaracter(c) - @test !in(c, characters) - end + for i=1:10 + c = DNDCharacter() + @testset "random character is valid and unique in history" begin + @test ischaracter(c) + @test !in(c, characters) + end - push!(characters, c) + push!(characters, c) + end end end diff --git a/exercises/practice/etl/.meta/config.json b/exercises/practice/etl/.meta/config.json index 70b00c50..e034e91f 100644 --- a/exercises/practice/etl/.meta/config.json +++ b/exercises/practice/etl/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "We are going to do the `Transform` step of an Extract-Transform-Load.", + "blurb": "Change the data format for scoring a game to more easily add other languages.", "authors": [ "andrej-makarov-skrt" ], @@ -19,6 +19,6 @@ ".meta/example.jl" ] }, - "source": "The Jumpstart Lab team", - "source_url": "http://jumpstartlab.com" + "source": "Based on an exercise by the JumpstartLab team for students at The Turing School of Software and Design.", + "source_url": "https://turing.edu" } diff --git a/exercises/practice/etl/runtests.jl b/exercises/practice/etl/runtests.jl index e0624652..e618deb0 100644 --- a/exercises/practice/etl/runtests.jl +++ b/exercises/practice/etl/runtests.jl @@ -2,35 +2,36 @@ using Test include("etl.jl") -@testset "single letter" begin - input = Dict(1=>['A']) - output = Dict('a'=>1) - @test transform(input) == output -end +@testset verbose = true "tests" begin + @testset "single letter" begin + input = Dict(1=>['A']) + output = Dict('a'=>1) + @test transform(input) == output + end -@testset "single score with multiple letters" begin - input = Dict(1=>['A', 'E', 'I', 'O', 'U']) - output = Dict('a'=>1, 'e'=>1, 'i'=>1, 'o'=>1, 'u'=>1) - @test transform(input) == output -end + @testset "single score with multiple letters" begin + input = Dict(1=>['A', 'E', 'I', 'O', 'U']) + output = Dict('a'=>1, 'e'=>1, 'i'=>1, 'o'=>1, 'u'=>1) + @test transform(input) == output + end -@testset "multiple scores with multiple letters" begin - input = Dict(1=>['A', 'E'], 2=>['D', 'G']) - output = Dict('g'=>2, 'e'=>1, 'a'=>1, 'd'=>2) - @test transform(input) == output -end + @testset "multiple scores with multiple letters" begin + input = Dict(1=>['A', 'E'], 2=>['D', 'G']) + output = Dict('g'=>2, 'e'=>1, 'a'=>1, 'd'=>2) + @test transform(input) == output + end -@testset "multiple scores with differing numbers of letters" begin - input = Dict(1=>[ 'A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T' ], - 2=>[ 'D', 'G' ], 3=>[ 'B', 'C', 'M', 'P' ], - 4=>[ 'F', 'H', 'V', 'W', 'Y' ], 5=>[ 'K' ], - 8=>[ 'J', 'X' ], 10=>[ 'Q', 'Z' ]) - output = Dict('a'=>1, 'b'=>3, 'c'=>3, 'd'=>2, 'e'=>1, - 'f'=>4, 'g'=>2, 'h'=>4, 'i'=>1, 'j'=>8, - 'k'=>5, 'l'=>1, 'm'=>3, 'n'=>1, 'o'=>1, - 'p'=>3, 'q'=>10, 'r'=>1, 's'=>1, 't'=>1, - 'u'=>1, 'v'=>4, 'w'=>4, 'x'=>8, 'y'=>4, - 'z'=>10) - @test transform(input) == output + @testset "multiple scores with differing numbers of letters" begin + input = Dict(1=>[ 'A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T' ], + 2=>[ 'D', 'G' ], 3=>[ 'B', 'C', 'M', 'P' ], + 4=>[ 'F', 'H', 'V', 'W', 'Y' ], 5=>[ 'K' ], + 8=>[ 'J', 'X' ], 10=>[ 'Q', 'Z' ]) + output = Dict('a'=>1, 'b'=>3, 'c'=>3, 'd'=>2, 'e'=>1, + 'f'=>4, 'g'=>2, 'h'=>4, 'i'=>1, 'j'=>8, + 'k'=>5, 'l'=>1, 'm'=>3, 'n'=>1, 'o'=>1, + 'p'=>3, 'q'=>10, 'r'=>1, 's'=>1, 't'=>1, + 'u'=>1, 'v'=>4, 'w'=>4, 'x'=>8, 'y'=>4, + 'z'=>10) + @test transform(input) == output + end end - diff --git a/exercises/practice/gigasecond/.meta/config.json b/exercises/practice/gigasecond/.meta/config.json index 131c17e0..c00bf031 100644 --- a/exercises/practice/gigasecond/.meta/config.json +++ b/exercises/practice/gigasecond/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "Chapter 9 in Chris Pine's online Learn to Program tutorial.", - "source_url": "http://pine.fm/LearnToProgram/?Chapter=09" + "source_url": "https://pine.fm/LearnToProgram/?Chapter=09" } diff --git a/exercises/practice/gigasecond/runtests.jl b/exercises/practice/gigasecond/runtests.jl index 897d07ad..54f29be9 100644 --- a/exercises/practice/gigasecond/runtests.jl +++ b/exercises/practice/gigasecond/runtests.jl @@ -11,6 +11,8 @@ samples = Dict( DateTime("2015-01-24T23:59:59") => DateTime("2046-10-03T01:46:39") ) -@testset "add gigasecond to $sample[1]" for sample in samples - @test add_gigasecond(sample[1]) == sample[2] +@testset verbose = true "tests" begin + @testset "add gigasecond to $sample[1]" for sample in samples + @test add_gigasecond(sample[1]) == sample[2] + end end diff --git a/exercises/practice/grains/.docs/instructions.md b/exercises/practice/grains/.docs/instructions.md index 05ee9976..df479fc0 100644 --- a/exercises/practice/grains/.docs/instructions.md +++ b/exercises/practice/grains/.docs/instructions.md @@ -1,27 +1,15 @@ # Instructions -Calculate the number of grains of wheat on a chessboard given that the number -on each square doubles. +Calculate the number of grains of wheat on a chessboard given that the number on each square doubles. -There once was a wise servant who saved the life of a prince. The king -promised to pay whatever the servant could dream up. Knowing that the -king loved chess, the servant told the king he would like to have grains -of wheat. One grain on the first square of a chess board, with the number -of grains doubling on each successive square. +There once was a wise servant who saved the life of a prince. +The king promised to pay whatever the servant could dream up. +Knowing that the king loved chess, the servant told the king he would like to have grains of wheat. +One grain on the first square of a chess board, with the number of grains doubling on each successive square. There are 64 squares on a chessboard (where square 1 has one grain, square 2 has two grains, and so on). Write code that shows: + - how many grains were on a given square, and - the total number of grains on the chessboard - -## For bonus points - -Did you get the tests passing and the code clean? If you want to, these -are some additional things you could try: - -- Optimize for speed. -- Optimize for readability. - -Then please share your thoughts in a comment on the submission. Did this -experiment make the code better? Worse? Did you learn anything from it? diff --git a/exercises/practice/grains/.meta/config.json b/exercises/practice/grains/.meta/config.json index 143f92ee..a0ee58ef 100644 --- a/exercises/practice/grains/.meta/config.json +++ b/exercises/practice/grains/.meta/config.json @@ -18,6 +18,6 @@ ".meta/example.jl" ] }, - "source": "JavaRanch Cattle Drive, exercise 6", - "source_url": "http://www.javaranch.com/grains.jsp" + "source": "The CodeRanch Cattle Drive, Assignment 6", + "source_url": "https://coderanch.com/wiki/718824/Grains" } diff --git a/exercises/practice/grains/runtests.jl b/exercises/practice/grains/runtests.jl index b458fda3..b0e9134f 100644 --- a/exercises/practice/grains/runtests.jl +++ b/exercises/practice/grains/runtests.jl @@ -2,36 +2,38 @@ using Test include("grains.jl") -@testset "beginning squares" begin - @test on_square(1) == 1 - @test on_square(2) == 2 - @test on_square(3) == 4 - @test on_square(4) == 8 - @test on_square(16) == 32768 - @test on_square(32) == 2147483648 - @test total_after(1) == 1 - @test total_after(3) == on_square(1) + on_square(2) + on_square(3) -end - -@testset "ending squares" begin - @test total_after(32) < total_after(64) - @test on_square(64) == 9223372036854775808 - @test total_after(64) == 18446744073709551615 -end - -@testset "Invalid values" begin - @testset "Zero" begin - @test_throws DomainError on_square(0) - @test_throws DomainError total_after(0) +@testset verbose = true "tests" begin + @testset "beginning squares" begin + @test on_square(1) == 1 + @test on_square(2) == 2 + @test on_square(3) == 4 + @test on_square(4) == 8 + @test on_square(16) == 32768 + @test on_square(32) == 2147483648 + @test total_after(1) == 1 + @test total_after(3) == on_square(1) + on_square(2) + on_square(3) end - - @testset "Negative" begin - @test_throws DomainError on_square(-1) - @test_throws DomainError total_after(-1) + + @testset "ending squares" begin + @test total_after(32) < total_after(64) + @test on_square(64) == 9223372036854775808 + @test total_after(64) == 18446744073709551615 end - - @testset "Greater than 64" begin - @test_throws DomainError on_square(65) - @test_throws DomainError total_after(65) + + @testset "Invalid values" begin + @testset "Zero" begin + @test_throws DomainError on_square(0) + @test_throws DomainError total_after(0) + end + + @testset "Negative" begin + @test_throws DomainError on_square(-1) + @test_throws DomainError total_after(-1) + end + + @testset "Greater than 64" begin + @test_throws DomainError on_square(65) + @test_throws DomainError total_after(65) + end end end diff --git a/exercises/practice/hamming/.docs/instructions.md b/exercises/practice/hamming/.docs/instructions.md index 56c5696d..020fdd02 100644 --- a/exercises/practice/hamming/.docs/instructions.md +++ b/exercises/practice/hamming/.docs/instructions.md @@ -2,11 +2,17 @@ Calculate the Hamming Distance between two DNA strands. -Your body is made up of cells that contain DNA. Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells. In fact, the average human body experiences about 10 quadrillion cell divisions in a lifetime! +Your body is made up of cells that contain DNA. +Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells. +In fact, the average human body experiences about 10 quadrillion cell divisions in a lifetime! -When cells divide, their DNA replicates too. Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information. If we compare two strands of DNA and count the differences between them we can see how many mistakes occurred. This is known as the "Hamming Distance". +When cells divide, their DNA replicates too. +Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information. +If we compare two strands of DNA and count the differences between them we can see how many mistakes occurred. +This is known as the "Hamming Distance". -We read DNA using the letters C,A,G and T. Two strands might look like this: +We read DNA using the letters C,A,G and T. +Two strands might look like this: GAGCCTACTAACGGGAT CATCGTAATGACGGCCT @@ -16,9 +22,6 @@ They have 7 differences, and therefore the Hamming Distance is 7. The Hamming Distance is useful for lots of things in science, not just biology, so it's a nice phrase to be familiar with :) -# Implementation notes +## Implementation notes -The Hamming distance is only defined for sequences of equal length, so -an attempt to calculate it between sequences of different lengths should -not work. The general handling of this situation (e.g., raising an -exception vs returning a special value) may differ between languages. +The Hamming distance is only defined for sequences of equal length, so an attempt to calculate it between sequences of different lengths should not work. diff --git a/exercises/practice/hamming/.meta/config.json b/exercises/practice/hamming/.meta/config.json index cda8a9b1..dda330d3 100644 --- a/exercises/practice/hamming/.meta/config.json +++ b/exercises/practice/hamming/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "The Calculating Point Mutations problem at Rosalind", - "source_url": "http://rosalind.info/problems/hamm/" + "source_url": "https://rosalind.info/problems/hamm/" } diff --git a/exercises/practice/hamming/runtests.jl b/exercises/practice/hamming/runtests.jl index caaed8b9..4c6af8ab 100644 --- a/exercises/practice/hamming/runtests.jl +++ b/exercises/practice/hamming/runtests.jl @@ -2,7 +2,7 @@ using Test include("hamming.jl") -@testset verbose = true "Hamming" begin +@testset verbose = true "tests" begin @testset "identical strands" begin @test distance("A", "A") == 0 @test distance("GGACTGA", "GGACTGA") == 0 diff --git a/exercises/practice/hello-world/.docs/instructions.md b/exercises/practice/hello-world/.docs/instructions.md index 6e08ebba..c9570e48 100644 --- a/exercises/practice/hello-world/.docs/instructions.md +++ b/exercises/practice/hello-world/.docs/instructions.md @@ -1,15 +1,16 @@ # Instructions -The classical introductory exercise. Just say "Hello, World!". +The classical introductory exercise. +Just say "Hello, World!". -["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is -the traditional first program for beginning programming in a new language -or environment. +["Hello, World!"][hello-world] is the traditional first program for beginning programming in a new language or environment. The objectives are simple: -- Write a function that returns the string "Hello, World!". +- 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 diff --git a/exercises/practice/hello-world/.meta/config.json b/exercises/practice/hello-world/.meta/config.json index 5f69d87f..2281666b 100644 --- a/exercises/practice/hello-world/.meta/config.json +++ b/exercises/practice/hello-world/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "The classical introductory exercise. Just say \"Hello, World!\"", + "blurb": "Exercism's classic introductory exercise. Just say \"Hello, World!\".", "authors": [ "SaschaMann" ], @@ -16,5 +16,5 @@ ] }, "source": "This is an exercise to introduce users to using Exercism", - "source_url": "http://en.wikipedia.org/wiki/%22Hello,_world!%22_program" + "source_url": "https://en.wikipedia.org/wiki/%22Hello,_world!%22_program" } diff --git a/exercises/practice/hello-world/runtests.jl b/exercises/practice/hello-world/runtests.jl index 6abdee84..2b99ccc7 100644 --- a/exercises/practice/hello-world/runtests.jl +++ b/exercises/practice/hello-world/runtests.jl @@ -2,7 +2,7 @@ using Test include("hello-world.jl") -@testset verbose = true "Hello World" begin +@testset verbose = true "tests" begin @testset "Say Hi!" begin @test hello() == "Hello, World!" end diff --git a/exercises/practice/isbn-verifier/.docs/instructions.append.md b/exercises/practice/isbn-verifier/.docs/instructions.append.md new file mode 100644 index 00000000..8b4473e7 --- /dev/null +++ b/exercises/practice/isbn-verifier/.docs/instructions.append.md @@ -0,0 +1,14 @@ +# Instructions append + +## Bonus tasks + +If you attempt these tasks please write your own tests for them in your solution file! + +* Define a string macro so that `isbn"3-598-21507-X" == ISBN("3-598-21507-X")`. + +* Let the constructor accept ISBN-13s as well. The same ISBN should compare equal regardless of format: `ISBN("1-234-56789-X") == ISBN("978-1-234-56789-7")`. + +* Define a function or iterator to generate a valid ISBN, maybe even from a given starting ISBN. + + Can you store the ISBN as an integer rather than a string and would that ever be a good idea? + If you did, could you still print the ISBN (including check-digit) as a string? diff --git a/exercises/practice/isbn-verifier/.docs/instructions.md b/exercises/practice/isbn-verifier/.docs/instructions.md index 6ee1487d..4a0244e5 100644 --- a/exercises/practice/isbn-verifier/.docs/instructions.md +++ b/exercises/practice/isbn-verifier/.docs/instructions.md @@ -1,22 +1,26 @@ # Instructions -The [ISBN-10 verification process](https://en.wikipedia.org/wiki/International_Standard_Book_Number) is used to validate book identification -numbers. These normally contain dashes and look like: `3-598-21508-8` +The [ISBN-10 verification process][isbn-verification] is used to validate book identification numbers. +These normally contain dashes and look like: `3-598-21508-8` ## ISBN -The ISBN-10 format is 9 digits (0 to 9) plus one check character (either a digit or an X only). In the case the check character is an X, this represents the value '10'. These may be communicated with or without hyphens, and can be checked for their validity by the following formula: +The ISBN-10 format is 9 digits (0 to 9) plus one check character (either a digit or an X only). +In the case the check character is an X, this represents the value '10'. +These may be communicated with or without hyphens, and can be checked for their validity by the following formula: -``` -(x1 * 10 + x2 * 9 + x3 * 8 + x4 * 7 + x5 * 6 + x6 * 5 + x7 * 4 + x8 * 3 + x9 * 2 + x10 * 1) mod 11 == 0 +```text +(d₁ * 10 + d₂ * 9 + d₃ * 8 + d₄ * 7 + d₅ * 6 + d₆ * 5 + d₇ * 4 + d₈ * 3 + d₉ * 2 + d₁₀ * 1) mod 11 == 0 ``` If the result is 0, then it is a valid ISBN-10, otherwise it is invalid. ## Example -Let's take the ISBN-10 `3-598-21508-8`. We plug it in to the formula, and get: -``` +Let's take the ISBN-10 `3-598-21508-8`. +We plug it in to the formula, and get: + +```text (3 * 10 + 5 * 9 + 9 * 8 + 8 * 7 + 2 * 6 + 1 * 5 + 5 * 4 + 0 * 3 + 8 * 2 + 8 * 1) mod 11 == 0 ``` @@ -24,31 +28,15 @@ Since the result is 0, this proves that our ISBN is valid. ## Task -Define a new `ISBN` type and a constructor for it that accepts a string. -The constructor should throw a `DomainError` if the provided string does not look like a valid ISBN-10. +Given a string the program should check if the provided string is a valid ISBN-10. +Putting this into place requires some thinking about preprocessing/parsing of the string prior to calculating the check digit for the ISBN. -The constructor should accept strings with and without separating dashes. - -`ISBN` values should compare as equal if the ISBN-10s are the same and not otherwise, e.g. - -```jl -ISBN("1-234-56789-X") == ISBN("123456789X") == ISBN("1234-56789X") -ISBN("1-234-56789-X") != ISBN("3-598-21508-8") -``` +The program should be able to verify ISBN-10 both with and without separating dashes. ## Caveats Converting from strings to numbers can be tricky in certain languages. -Now, it's even trickier since the check digit of an ISBN-10 may be 'X' (representing '10'). For instance `3-598-21507-X` is a valid ISBN-10. - -## Bonus tasks - -If you attempt these tasks please write your own tests for them in your solution file! - -* Define a string macro so that `isbn"3-598-21507-X" == ISBN("3-598-21507-X")`. - -* Let the constructor accept ISBN-13s as well. The same ISBN should compare equal regardless of format: `ISBN("1-234-56789-X") == ISBN("978-1-234-56789-7")`. - -* Define a function or iterator to generate a valid ISBN, maybe even from a given starting ISBN. +Now, it's even trickier since the check digit of an ISBN-10 may be 'X' (representing '10'). +For instance `3-598-21507-X` is a valid ISBN-10. -* Can you store the ISBN as an integer rather than a string and would that ever be a good idea? If you did, could you still print the ISBN (including check-digit) as a string? +[isbn-verification]: https://en.wikipedia.org/wiki/International_Standard_Book_Number diff --git a/exercises/practice/isbn-verifier/runtests.jl b/exercises/practice/isbn-verifier/runtests.jl index 7ffb6d3a..88b4715d 100644 --- a/exercises/practice/isbn-verifier/runtests.jl +++ b/exercises/practice/isbn-verifier/runtests.jl @@ -15,50 +15,52 @@ macro test_nothrow(expr) :(@test ( $expr; true )) end -@testset "valid ISBNs don't throw" begin - # ISBN number - @test_nothrow ISBN("3-598-21508-8") - # ISBN number with a check digit of 10 - @test_nothrow ISBN("3-598-21507-X") - # ISBN without separating dashes - @test_nothrow ISBN("3598215088") - # ISBN without separating dashes and X as check digit - @test_nothrow ISBN("359821507X") -end +@testset verbose = true "tests" begin + @testset "valid ISBNs don't throw" begin + # ISBN number + @test_nothrow ISBN("3-598-21508-8") + # ISBN number with a check digit of 10 + @test_nothrow ISBN("3-598-21507-X") + # ISBN without separating dashes + @test_nothrow ISBN("3598215088") + # ISBN without separating dashes and X as check digit + @test_nothrow ISBN("359821507X") + end -@testset "invalid ISBNs throw DomainError" begin - # invalid ISBN check digit - @test_throws DomainError ISBN("3-598-21508-9") - # check digit is a character other than X - @test_throws DomainError ISBN("3-598-21507-A") - # invalid character in ISBN - @test_throws DomainError ISBN("3-598-2K507-0") - # X is only valid as a check isdigit - @test_throws DomainError ISBN("3-598-2X507-9") - # ISBN without check digit and dashes - @test_throws DomainError ISBN("359821507") - # too long ISBN and no dashes - @test_throws DomainError ISBN("3598215078X") - # ISBN without check digit - @test_throws DomainError ISBN("3-598-21507") - # too long ISBN - @test_throws DomainError ISBN("3-598-21507-XX") - # check digit of X should not be used for 0 - @test_throws DomainError ISBN("3-598-21515-X") - # empty ISBN - @test_throws DomainError ISBN("") - # invalid character in ISBN - @test_throws DomainError ISBN("3-598-P1581-X") - # too short ISBN - @test_throws DomainError ISBN("00") - # input is 9 characters - @test_throws DomainError ISBN("134456729") - # invalid characters are not ignored - @test_throws DomainError ISBN("3132P34035") - # input is too long but contains a valid ISBN - @test_throws DomainError ISBN("98245726788") -end + @testset "invalid ISBNs throw DomainError" begin + # invalid ISBN check digit + @test_throws DomainError ISBN("3-598-21508-9") + # check digit is a character other than X + @test_throws DomainError ISBN("3-598-21507-A") + # invalid character in ISBN + @test_throws DomainError ISBN("3-598-2K507-0") + # X is only valid as a check isdigit + @test_throws DomainError ISBN("3-598-2X507-9") + # ISBN without check digit and dashes + @test_throws DomainError ISBN("359821507") + # too long ISBN and no dashes + @test_throws DomainError ISBN("3598215078X") + # ISBN without check digit + @test_throws DomainError ISBN("3-598-21507") + # too long ISBN + @test_throws DomainError ISBN("3-598-21507-XX") + # check digit of X should not be used for 0 + @test_throws DomainError ISBN("3-598-21515-X") + # empty ISBN + @test_throws DomainError ISBN("") + # invalid character in ISBN + @test_throws DomainError ISBN("3-598-P1581-X") + # too short ISBN + @test_throws DomainError ISBN("00") + # input is 9 characters + @test_throws DomainError ISBN("134456729") + # invalid characters are not ignored + @test_throws DomainError ISBN("3132P34035") + # input is too long but contains a valid ISBN + @test_throws DomainError ISBN("98245726788") + end -@testset "ISBNs compare equal when they're the same number" begin - @test ISBN("3-598-21508-8") == ISBN("3598215088") != ISBN("3-598-21507-X") + @testset "ISBNs compare equal when they're the same number" begin + @test ISBN("3-598-21508-8") == ISBN("3598215088") != ISBN("3-598-21507-X") + end end diff --git a/exercises/practice/isogram/.docs/instructions.md b/exercises/practice/isogram/.docs/instructions.md index 9cc5350b..2e8df851 100644 --- a/exercises/practice/isogram/.docs/instructions.md +++ b/exercises/practice/isogram/.docs/instructions.md @@ -2,7 +2,7 @@ Determine if a word or phrase is an isogram. -An isogram (also known as a "nonpattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times. +An isogram (also known as a "non-pattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times. Examples of isograms: @@ -11,4 +11,4 @@ Examples of isograms: - downstream - six-year-old -The word *isograms*, however, is not an isogram, because the s repeats. +The word _isograms_, however, is not an isogram, because the s repeats. diff --git a/exercises/practice/isogram/runtests.jl b/exercises/practice/isogram/runtests.jl index d5d705d8..c2b94e25 100644 --- a/exercises/practice/isogram/runtests.jl +++ b/exercises/practice/isogram/runtests.jl @@ -2,7 +2,7 @@ using Test include("isogram.jl") -@testset verbose = true "Isogram" begin +@testset verbose = true "tests" begin @testset "empty string" begin @test isisogram("") end diff --git a/exercises/practice/killer-sudoku-helper/runtests.jl b/exercises/practice/killer-sudoku-helper/runtests.jl index 5be2ad02..7e0d02e4 100644 --- a/exercises/practice/killer-sudoku-helper/runtests.jl +++ b/exercises/practice/killer-sudoku-helper/runtests.jl @@ -2,7 +2,7 @@ using Test include("sudoku-util.jl") -@testset verbose = true "Killer Sudoku Helper" begin +@testset verbose = true "tests" begin @testset "Trivial 1-digit cages" begin for n in 1:9 @test combinations_in_cage(n, 1) == [[n]] diff --git a/exercises/practice/largest-series-product/runtests.jl b/exercises/practice/largest-series-product/runtests.jl index 1647c24c..4c524d95 100644 --- a/exercises/practice/largest-series-product/runtests.jl +++ b/exercises/practice/largest-series-product/runtests.jl @@ -2,56 +2,58 @@ using Test include("largest-series-product.jl") -@testset "finds the largest product if span equals length" begin - @test largest_product("29", 2) == 18 -end - -@testset "can find the largest product of 2 with numbers in order" begin - @test largest_product("0123456789", 2) == 72 -end - -@testset "can find the largest product of 2" begin - @test largest_product("576802143", 2) == 48 -end - -@testset "can find the largest product of 3 with numbers in order" begin - @test largest_product("0123456789", 3) == 504 -end +@testset verbose = true "tests" begin + @testset "finds the largest product if span equals length" begin + @test largest_product("29", 2) == 18 + end -@testset "can find the largest product of 3" begin - @test largest_product("1027839564", 3) == 270 -end + @testset "can find the largest product of 2 with numbers in order" begin + @test largest_product("0123456789", 2) == 72 + end -@testset "can find the largest product of 5 with numbers in order" begin - @test largest_product("0123456789", 5) == 15_120 -end + @testset "can find the largest product of 2" begin + @test largest_product("576802143", 2) == 48 + end -@testset "can get the largest product of a big number" begin - @test largest_product("73167176531330624919225119674426574742355349194934", 6) == 23_520 -end + @testset "can find the largest product of 3 with numbers in order" begin + @test largest_product("0123456789", 3) == 504 + end -@testset "reports zero if the only digits are zero" begin - @test largest_product("0000", 2) == 0 -end + @testset "can find the largest product of 3" begin + @test largest_product("1027839564", 3) == 270 + end -@testset "reports zero if all spans include zero" begin - @test largest_product("99099", 3) == 0 -end + @testset "can find the largest product of 5 with numbers in order" begin + @test largest_product("0123456789", 5) == 15_120 + end -@testset "error handling" begin - @testset "span longer than string length" begin - @test_throws ArgumentError largest_product("123", 4) + @testset "can get the largest product of a big number" begin + @test largest_product("73167176531330624919225119674426574742355349194934", 6) == 23_520 end - @testset "empty string and nonzero span" begin - @test_throws ArgumentError largest_product("", 1) + @testset "reports zero if the only digits are zero" begin + @test largest_product("0000", 2) == 0 end - @testset "invalid character in digits" begin - @test_throws ArgumentError largest_product("1234a5", 2) + @testset "reports zero if all spans include zero" begin + @test largest_product("99099", 3) == 0 end - @testset "negative span" begin - @test_throws ArgumentError largest_product("12345", -1) + @testset "error handling" begin + @testset "span longer than string length" begin + @test_throws ArgumentError largest_product("123", 4) + end + + @testset "empty string and nonzero span" begin + @test_throws ArgumentError largest_product("", 1) + end + + @testset "invalid character in digits" begin + @test_throws ArgumentError largest_product("1234a5", 2) + end + + @testset "negative span" begin + @test_throws ArgumentError largest_product("12345", -1) + end end end diff --git a/exercises/practice/leap/runtests.jl b/exercises/practice/leap/runtests.jl index 28aa95aa..756c5216 100644 --- a/exercises/practice/leap/runtests.jl +++ b/exercises/practice/leap/runtests.jl @@ -2,7 +2,7 @@ using Test include("leap.jl") -@testset verbose = true "Leap" begin +@testset verbose = true "tests" begin @testset "Year not divisible by 4: common year" begin @test !is_leap_year(2015) end diff --git a/exercises/practice/luhn/.docs/instructions.md b/exercises/practice/luhn/.docs/instructions.md index c7c7d3e0..8cbe791f 100644 --- a/exercises/practice/luhn/.docs/instructions.md +++ b/exercises/practice/luhn/.docs/instructions.md @@ -2,35 +2,31 @@ Given a number determine whether or not it is valid per the Luhn formula. -The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is -a simple checksum formula used to validate a variety of identification -numbers, such as credit card numbers and Canadian Social Insurance -Numbers. +The [Luhn algorithm][luhn] is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers and Canadian Social Insurance Numbers. The task is to check if a given string is valid. -Validating a Number ------- +## Validating a Number -Strings of length 1 or less are not valid. Spaces are allowed in the input, -but they should be stripped before checking. All other non-digit characters -are disallowed. +Strings of length 1 or less are not valid. +Spaces are allowed in the input, but they should be stripped before checking. +All other non-digit characters are disallowed. -## Example 1: valid credit card number +### Example 1: valid credit card number ```text 4539 3195 0343 6467 ``` -The first step of the Luhn algorithm is to double every second digit, -starting from the right. We will be doubling +The first step of the Luhn algorithm is to double every second digit, starting from the right. +We will be doubling ```text 4_3_ 3_9_ 0_4_ 6_6_ ``` -If doubling the number results in a number greater than 9 then subtract 9 -from the product. The results of our doubling: +If doubling the number results in a number greater than 9 then subtract 9 from the product. +The results of our doubling: ```text 8569 6195 0383 3437 @@ -42,9 +38,10 @@ Then sum all of the digits: 8+5+6+9+6+1+9+5+0+3+8+3+3+4+3+7 = 80 ``` -If the sum is evenly divisible by 10, then the number is valid. This number is valid! +If the sum is evenly divisible by 10, then the number is valid. +This number is valid! -## Example 2: invalid credit card number +### Example 2: invalid credit card number ```text 8273 1232 7352 0569 @@ -63,3 +60,5 @@ Sum the digits ``` 57 is not evenly divisible by 10, so this number is not valid. + +[luhn]: https://en.wikipedia.org/wiki/Luhn_algorithm diff --git a/exercises/practice/luhn/.meta/config.json b/exercises/practice/luhn/.meta/config.json index a9705e9d..b14f77d7 100644 --- a/exercises/practice/luhn/.meta/config.json +++ b/exercises/practice/luhn/.meta/config.json @@ -18,5 +18,5 @@ ] }, "source": "The Luhn Algorithm on Wikipedia", - "source_url": "http://en.wikipedia.org/wiki/Luhn_algorithm" + "source_url": "https://en.wikipedia.org/wiki/Luhn_algorithm" } diff --git a/exercises/practice/luhn/runtests.jl b/exercises/practice/luhn/runtests.jl index ac7cdf90..18cbb202 100644 --- a/exercises/practice/luhn/runtests.jl +++ b/exercises/practice/luhn/runtests.jl @@ -2,82 +2,84 @@ using Test include("luhn.jl") -@testset "invalid" begin - @testset "single digit strings can not be valid" begin - @test !luhn("1") - end +@testset verbose = true "tests" begin + @testset "invalid" begin + @testset "single digit strings can not be valid" begin + @test !luhn("1") + end - @testset "A single zero is invalid" begin - @test !luhn("0") - end + @testset "A single zero is invalid" begin + @test !luhn("0") + end - @testset "invalid Canadian SIN" begin - @test !luhn("055 444 286") - end + @testset "invalid Canadian SIN" begin + @test !luhn("055 444 286") + end - @testset "invalid credit card" begin - @test !luhn("8273 1232 7352 0569") - end + @testset "invalid credit card" begin + @test !luhn("8273 1232 7352 0569") + end - @testset "valid strings with a non-digit added become invalid" begin - @test !luhn("046a 454 286") - end + @testset "valid strings with a non-digit added become invalid" begin + @test !luhn("046a 454 286") + end - @testset "invalid long number with an even remainder" begin - @test !luhn("1 2345 6789 1234 5678 9012") - end + @testset "invalid long number with an even remainder" begin + @test !luhn("1 2345 6789 1234 5678 9012") + end - @testset "valid strings with a non-digit added at the end become invalid" begin - @test !luhn("059a") - end + @testset "valid strings with a non-digit added at the end become invalid" begin + @test !luhn("059a") + end - @testset "valid strings with punctuation included become invalid" begin - @test !luhn("055-444-285") - end + @testset "valid strings with punctuation included become invalid" begin + @test !luhn("055-444-285") + end - @testset "valid strings with symbols included become invalid" begin - @test !luhn("055# 444\$ 285") - end + @testset "valid strings with symbols included become invalid" begin + @test !luhn("055# 444\$ 285") + end - @testset "single zero with space is invalid" begin - @test !luhn(" 0") - end + @testset "single zero with space is invalid" begin + @test !luhn(" 0") + end - @testset "using ascii value for non-doubled non-digit isn't allowed" begin - @test !luhn("055b 444 285") - end + @testset "using ascii value for non-doubled non-digit isn't allowed" begin + @test !luhn("055b 444 285") + end - @testset "using ascii value for doubled non-digit isn't allowed" begin - @test !luhn(":9") + @testset "using ascii value for doubled non-digit isn't allowed" begin + @test !luhn(":9") + end end -end -@testset "valid" begin - @testset "valid Canadian SIN" begin - @test luhn("055 444 285") - end + @testset "valid" begin + @testset "valid Canadian SIN" begin + @test luhn("055 444 285") + end - @testset "a simple valid SIN that remains valid if reversed" begin - @test luhn("059") - end + @testset "a simple valid SIN that remains valid if reversed" begin + @test luhn("059") + end - @testset "a simple valid SIN that becomes invalid if reversed" begin - @test luhn("59") - end + @testset "a simple valid SIN that becomes invalid if reversed" begin + @test luhn("59") + end - @testset "valid number with an even number of digits" begin - @test luhn("095 245 88") - end + @testset "valid number with an even number of digits" begin + @test luhn("095 245 88") + end - @testset "valid number with an odd number of spaces" begin - @test luhn("234 567 891 234") - end + @testset "valid number with an odd number of spaces" begin + @test luhn("234 567 891 234") + end - @testset "more than a single zero is valid" begin - @test luhn("0000 0") - end + @testset "more than a single zero is valid" begin + @test luhn("0000 0") + end - @testset "input digit 9 is correctly converted to output digit 9" begin - @test luhn("091") + @testset "input digit 9 is correctly converted to output digit 9" begin + @test luhn("091") + end end end diff --git a/exercises/practice/matching-brackets/.docs/instructions.md b/exercises/practice/matching-brackets/.docs/instructions.md index 364ecad2..544daa96 100644 --- a/exercises/practice/matching-brackets/.docs/instructions.md +++ b/exercises/practice/matching-brackets/.docs/instructions.md @@ -1,5 +1,4 @@ # Instructions -Given a string containing brackets `[]`, braces `{}`, parentheses `()`, -or any combination thereof, verify that any and all pairs are matched -and nested correctly. +Given a string containing brackets `[]`, braces `{}`, parentheses `()`, or any combination thereof, verify that any and all pairs are matched and nested correctly. +The string may also contain other characters, which for the purposes of this exercise should be ignored. diff --git a/exercises/practice/matching-brackets/runtests.jl b/exercises/practice/matching-brackets/runtests.jl index dace8d8e..431165bc 100644 --- a/exercises/practice/matching-brackets/runtests.jl +++ b/exercises/practice/matching-brackets/runtests.jl @@ -2,30 +2,32 @@ using Test include("matching-brackets.jl") -@testset "Determine if a pair of brackets are correctly matched" begin - @test matching_brackets("[]") - @test !matching_brackets("[[") - @test !matching_brackets("}{") - @test !matching_brackets("{]") - @test matching_brackets("{ }") -end +@testset verbose = true "tests" begin + @testset "Determine if a pair of brackets are correctly matched" begin + @test matching_brackets("[]") + @test !matching_brackets("[[") + @test !matching_brackets("}{") + @test !matching_brackets("{]") + @test matching_brackets("{ }") + end -@testset "Determine if 3 or more brackets are correctly matched" begin - @test !matching_brackets("[]]") - @test !matching_brackets("{}[") - @test matching_brackets("{}[]") - @test !matching_brackets("{[])") - @test matching_brackets("{[]}") - @test matching_brackets("([{}({}[])])") - @test !matching_brackets("{[)][]}") - @test !matching_brackets("([{])") - @test !matching_brackets("[({]})") - @test !matching_brackets(")()") - @test !matching_brackets("{)()") -end - -@testset "Determine if expressions with non-brackets are correctly matched" begin - @test matching_brackets("") - @test matching_brackets("(((185 + 223.85) * 15) - 543)/2") - @test matching_brackets("\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)") + @testset "Determine if 3 or more brackets are correctly matched" begin + @test !matching_brackets("[]]") + @test !matching_brackets("{}[") + @test matching_brackets("{}[]") + @test !matching_brackets("{[])") + @test matching_brackets("{[]}") + @test matching_brackets("([{}({}[])])") + @test !matching_brackets("{[)][]}") + @test !matching_brackets("([{])") + @test !matching_brackets("[({]})") + @test !matching_brackets(")()") + @test !matching_brackets("{)()") + end + + @testset "Determine if expressions with non-brackets are correctly matched" begin + @test matching_brackets("") + @test matching_brackets("(((185 + 223.85) * 15) - 543)/2") + @test matching_brackets("\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)") + end end diff --git a/exercises/practice/minesweeper/.docs/instructions.md b/exercises/practice/minesweeper/.docs/instructions.md index 1114cc95..7c1df2e4 100644 --- a/exercises/practice/minesweeper/.docs/instructions.md +++ b/exercises/practice/minesweeper/.docs/instructions.md @@ -1,35 +1,24 @@ # Instructions -Add the mine counts to a completed Minesweeper board. +Your task is to add the mine counts to empty squares in a completed Minesweeper board. +The board itself is a rectangle composed of squares that are either empty (`' '`) or a mine (`'*'`). -Minesweeper is a popular game where the user has to find the mines using -numeric hints that indicate how many mines are directly adjacent -(horizontally, vertically, diagonally) to a square. +For each empty square, count the number of mines adjacent to it (horizontally, vertically, diagonally). +If the empty square has no adjacent mines, leave it empty. +Otherwise replace it with the adjacent mines count. -In this exercise you have to create some code that counts the number of -mines adjacent to a given empty square and replaces that square with the -count. +For example, you may receive a 5 x 4 board like this (empty spaces are represented here with the '·' character for display on screen): -The board is a rectangle composed of blank space (' ') characters. A mine -is represented by an asterisk ('\*') character. - -If a given space has no adjacent mines at all, leave that square blank. - -## Examples - -For example you may receive a 5 x 4 board like this (empty spaces are -represented here with the '·' character for display on screen): - -``` +```text ·*·*· ··*·· ··*·· ····· ``` -And your code will transform it into this: +Which your code should transform into this: -``` +```text 1*3*1 13*31 ·2*2· diff --git a/exercises/practice/minesweeper/.docs/introduction.md b/exercises/practice/minesweeper/.docs/introduction.md new file mode 100644 index 00000000..5f74a742 --- /dev/null +++ b/exercises/practice/minesweeper/.docs/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +[Minesweeper][wikipedia] is a popular game where the user has to find the mines using numeric hints that indicate how many mines are directly adjacent (horizontally, vertically, diagonally) to a square. + +[wikipedia]: https://en.wikipedia.org/wiki/Minesweeper_(video_game) diff --git a/exercises/practice/minesweeper/.meta/config.json b/exercises/practice/minesweeper/.meta/config.json index b7400aab..65f69520 100644 --- a/exercises/practice/minesweeper/.meta/config.json +++ b/exercises/practice/minesweeper/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Add the numbers to a minesweeper board", + "blurb": "Add the numbers to a minesweeper board.", "authors": [ "abhishalya" ], diff --git a/exercises/practice/minesweeper/runtests.jl b/exercises/practice/minesweeper/runtests.jl index eba79caa..7d744b5a 100644 --- a/exercises/practice/minesweeper/runtests.jl +++ b/exercises/practice/minesweeper/runtests.jl @@ -2,120 +2,122 @@ using Test include("minesweeper.jl") -@testset "no rows" begin - @test annotate([]) == [] -end +@testset verbose = true "tests" begin + @testset "no rows" begin + @test annotate([]) == [] + end -@testset "no columns" begin - @test annotate([""]) == [""] -end + @testset "no columns" begin + @test annotate([""]) == [""] + end -@testset "no mines" begin - minefield = [" ", - " ", - " "] - out = [" ", - " ", - " "] - @test annotate(minefield) == out -end + @testset "no mines" begin + minefield = [" ", + " ", + " "] + out = [" ", + " ", + " "] + @test annotate(minefield) == out + end -@testset "minefield only mines" begin - minefield = ["***", - "***", - "***"] - out = ["***", - "***", - "***"] - @test annotate(minefield) == out -end + @testset "minefield only mines" begin + minefield = ["***", + "***", + "***"] + out = ["***", + "***", + "***"] + @test annotate(minefield) == out + end -@testset "mine surrounded by spaces" begin - minefield = [" ", - " * ", - " "] - out = ["111", - "1*1", - "111"] - @test annotate(minefield) == out -end + @testset "mine surrounded by spaces" begin + minefield = [" ", + " * ", + " "] + out = ["111", + "1*1", + "111"] + @test annotate(minefield) == out + end -@testset "space surrounded by mines" begin - minefield = ["***", - "* *", - "***"] - out = ["***", - "*8*", - "***"] - @test annotate(minefield) == out -end + @testset "space surrounded by mines" begin + minefield = ["***", + "* *", + "***"] + out = ["***", + "*8*", + "***"] + @test annotate(minefield) == out + end -@testset "horizontal line" begin - minefield = [" * * "] - out = ["1*2*1"] - @test annotate(minefield) == out -end + @testset "horizontal line" begin + minefield = [" * * "] + out = ["1*2*1"] + @test annotate(minefield) == out + end -@testset "horizontal line mines at edges" begin - minefield = ["* *"] - out = ["*1 1*"] - @test annotate(minefield) == out -end + @testset "horizontal line mines at edges" begin + minefield = ["* *"] + out = ["*1 1*"] + @test annotate(minefield) == out + end -@testset "vertical line" begin - minefield = [" ", - "*", - " ", - "*", - " "] - out = ["1", - "*", - "2", - "*", - "1"] - @test annotate(minefield) == out -end + @testset "vertical line" begin + minefield = [" ", + "*", + " ", + "*", + " "] + out = ["1", + "*", + "2", + "*", + "1"] + @test annotate(minefield) == out + end -@testset "vertical line mines at edges" begin - minefield = ["*", - " ", - " ", - " ", - "*"] - out = ["*", - "1", - " ", - "1", - "*"] - @test annotate(minefield) == out -end + @testset "vertical line mines at edges" begin + minefield = ["*", + " ", + " ", + " ", + "*"] + out = ["*", + "1", + " ", + "1", + "*"] + @test annotate(minefield) == out + end -@testset "cross" begin - minefield = [" * ", - " * ", - "*****", - " * ", - " * "] - out = [" 2*2 ", - "25*52", - "*****", - "25*52", - " 2*2 "] - @test annotate(minefield) == out -end + @testset "cross" begin + minefield = [" * ", + " * ", + "*****", + " * ", + " * "] + out = [" 2*2 ", + "25*52", + "*****", + "25*52", + " 2*2 "] + @test annotate(minefield) == out + end -@testset "large minefield" begin - minefield = [" * * ", - " * ", - " * ", - " * *", - " * * ", - " "] - out = ["1*22*1", - "12*322", - " 123*2", - "112*4*", - "1*22*2", - "111111"] - @test annotate(minefield) == out + @testset "large minefield" begin + minefield = [" * * ", + " * ", + " * ", + " * *", + " * * ", + " "] + out = ["1*22*1", + "12*322", + " 123*2", + "112*4*", + "1*22*2", + "111111"] + @test annotate(minefield) == out + end end diff --git a/exercises/practice/nucleotide-count/.docs/instructions.md b/exercises/practice/nucleotide-count/.docs/instructions.md index cd087589..548d9ba5 100644 --- a/exercises/practice/nucleotide-count/.docs/instructions.md +++ b/exercises/practice/nucleotide-count/.docs/instructions.md @@ -1,10 +1,12 @@ # Instructions -Each of us inherits from our biological parents a set of chemical instructions known as DNA that influence how our bodies are constructed. All known life depends on DNA! +Each of us inherits from our biological parents a set of chemical instructions known as DNA that influence how our bodies are constructed. +All known life depends on DNA! > Note: You do not need to understand anything about nucleotides or DNA to complete this exercise. -DNA is a long chain of other chemicals and the most important are the four nucleotides, adenine, cytosine, guanine and thymine. A single DNA chain can contain billions of these four nucleotides and the order in which they occur is important! +DNA is a long chain of other chemicals and the most important are the four nucleotides, adenine, cytosine, guanine and thymine. +A single DNA chain can contain billions of these four nucleotides and the order in which they occur is important! We call the order of these nucleotides in a bit of DNA a "DNA sequence". We represent a DNA sequence as an ordered collection of these four nucleotides and a common way to do that is with a string of characters such as "ATTACG" for a DNA sequence of 6 nucleotides. @@ -15,7 +17,7 @@ If the string contains characters that aren't A, C, G, or T then it is invalid a For example: -``` +```text "GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2 "INVALID" -> error ``` diff --git a/exercises/practice/nucleotide-count/.meta/config.json b/exercises/practice/nucleotide-count/.meta/config.json index 17fab528..6aba7dc2 100644 --- a/exercises/practice/nucleotide-count/.meta/config.json +++ b/exercises/practice/nucleotide-count/.meta/config.json @@ -21,5 +21,5 @@ ] }, "source": "The Calculating DNA Nucleotides_problem at Rosalind", - "source_url": "http://rosalind.info/problems/dna/" + "source_url": "https://rosalind.info/problems/dna/" } diff --git a/exercises/practice/nucleotide-count/runtests.jl b/exercises/practice/nucleotide-count/runtests.jl index 168fe914..c77a08bd 100644 --- a/exercises/practice/nucleotide-count/runtests.jl +++ b/exercises/practice/nucleotide-count/runtests.jl @@ -2,7 +2,7 @@ using Test include("nucleotide-count.jl") -@testset verbose = true "Nucleotide Count" begin +@testset verbose = true "tests" begin @testset "empty strand" begin @test count_nucleotides("") == Dict('A' => 0, 'C' => 0, 'G' => 0, 'T' => 0) end diff --git a/exercises/practice/pangram/runtests.jl b/exercises/practice/pangram/runtests.jl index 31c96f4e..794e43b6 100644 --- a/exercises/practice/pangram/runtests.jl +++ b/exercises/practice/pangram/runtests.jl @@ -2,7 +2,7 @@ using Test include("pangram.jl") -@testset verbose = true "Pangram" begin +@testset verbose = true "tests" begin @testset "empty sentence" begin @test !ispangram("") end diff --git a/exercises/practice/pascals-triangle/.docs/instructions.md b/exercises/practice/pascals-triangle/.docs/instructions.md index 7109334f..f5567859 100644 --- a/exercises/practice/pascals-triangle/.docs/instructions.md +++ b/exercises/practice/pascals-triangle/.docs/instructions.md @@ -2,8 +2,7 @@ Compute Pascal's triangle up to a given number of rows. -In Pascal's Triangle each number is computed by adding the numbers to -the right and left of the current position in the previous row. +In Pascal's Triangle each number is computed by adding the numbers to the right and left of the current position in the previous row. ```text 1 diff --git a/exercises/practice/pascals-triangle/.meta/config.json b/exercises/practice/pascals-triangle/.meta/config.json index 19ed28f8..afac7dfc 100644 --- a/exercises/practice/pascals-triangle/.meta/config.json +++ b/exercises/practice/pascals-triangle/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "Pascal's Triangle at Wolfram Math World", - "source_url": "http://mathworld.wolfram.com/PascalsTriangle.html" + "source_url": "https://www.wolframalpha.com/input/?i=Pascal%27s+triangle" } diff --git a/exercises/practice/pascals-triangle/runtests.jl b/exercises/practice/pascals-triangle/runtests.jl index e1bd53ce..d0448ba5 100644 --- a/exercises/practice/pascals-triangle/runtests.jl +++ b/exercises/practice/pascals-triangle/runtests.jl @@ -4,11 +4,13 @@ include("pascals-triangle.jl") const rows = [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1], [1, 6, 15, 20, 15, 6, 1], [1, 7, 21, 35, 35, 21, 7, 1], [1, 8, 28, 56, 70, 56, 28, 8, 1], [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]] -@testset "$i row(s)" for i in eachindex(rows) - @test triangle(i) == @view rows[1:i] -end +@testset verbose = true "tests" begin + @testset "$i row(s)" for i in eachindex(rows) + @test triangle(i) == @view rows[1:i] + end -@testset "special cases" begin - @test_throws DomainError triangle(-1) - @test isempty(triangle(0)) + @testset "special cases" begin + @test_throws DomainError triangle(-1) + @test isempty(triangle(0)) + end end diff --git a/exercises/practice/perfect-numbers/.docs/instructions.md b/exercises/practice/perfect-numbers/.docs/instructions.md index 144c9133..b2bc82ca 100644 --- a/exercises/practice/perfect-numbers/.docs/instructions.md +++ b/exercises/practice/perfect-numbers/.docs/instructions.md @@ -1,18 +1,39 @@ # 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](https://en.wikipedia.org/wiki/Nicomachus) devised a classification scheme for positive integers, identifying each as belonging uniquely to the categories of **perfect**, **abundant**, or **deficient** based on their [aliquot sum](https://en.wikipedia.org/wiki/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**: aliquot sum = number - - 6 is a perfect number because (1 + 2 + 3) = 6 - - 28 is a perfect number because (1 + 2 + 4 + 7 + 14) = 28 -- **Abundant**: aliquot sum > number - - 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**: aliquot sum < number - - 8 is a deficient number because (1 + 2 + 4) = 7 - - Prime numbers are deficient - -Implement a way to determine whether a given number is **perfect**. Depending on your language track, you may also need to implement a way to determine whether a given number is **abundant** or **deficient**. +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 diff --git a/exercises/practice/perfect-numbers/.meta/config.json b/exercises/practice/perfect-numbers/.meta/config.json index 0f13baa4..71149256 100644 --- a/exercises/practice/perfect-numbers/.meta/config.json +++ b/exercises/practice/perfect-numbers/.meta/config.json @@ -21,5 +21,5 @@ ] }, "source": "Taken from Chapter 2 of Functional Thinking by Neal Ford.", - "source_url": "http://shop.oreilly.com/product/0636920029687.do" + "source_url": "https://www.oreilly.com/library/view/functional-thinking/9781449365509/" } diff --git a/exercises/practice/perfect-numbers/runtests.jl b/exercises/practice/perfect-numbers/runtests.jl index 982d35a1..ffa44f8c 100644 --- a/exercises/practice/perfect-numbers/runtests.jl +++ b/exercises/practice/perfect-numbers/runtests.jl @@ -2,70 +2,87 @@ using Test include("perfect-numbers.jl") -@testset "Perfect numbers" begin - - @testset "Smallest perfect number is classified correctly" begin - @test isperfect(6) +@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 "Medium perfect number is classified correctly" begin - @test isperfect(28) - end + @testset "Abundant numbers" begin - @testset "Large perfect number is classified correctly" begin - @test isperfect(33550336) - end -end + @testset "Smallest abundant number is classified correctly" begin + @test isabundant(12) + end -@testset "Abundant numbers" begin + @testset "Medium abundant number is classified correctly" begin + @test isabundant(30) + end - @testset "Smallest abundant number is classified correctly" begin - @test isabundant(12) - end + @testset "Large abundant number is classified correctly" begin + @test isabundant(33550335) + end - @testset "Medium abundant number is classified correctly" begin - @test isabundant(30) + @testset "Correctly handles non-abundant numbers" begin + @test !isabundant(6) + @test !isabundant(32) + end end - @testset "Large abundant number is classified correctly" begin - @test isabundant(33550335) - end -end + @testset "Deficient numbers" begin -@testset "Deficient numbers" begin + @testset "Smallest prime deficient number is classified correctly" begin + @test isdeficient(2) + end - @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 "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 "Medium deficient number is classified correctly" begin - @test isdeficient(32) - end + @testset "Large deficient number is classified correctly" begin + @test isdeficient(33550337) + 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 "Edge case (no factors other than itself) is classified correctly" begin - @test isdeficient(1) + @testset "Correctly handles non-deficient numbers" begin + @test !isdeficient(28) + @test !isdeficient(30) + end end -end -@testset "Invalid inputs" begin + @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 "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) + @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/exercises/practice/phone-number/.docs/instructions.append.md b/exercises/practice/phone-number/.docs/instructions.append.md new file mode 100644 index 00000000..ff7e8927 --- /dev/null +++ b/exercises/practice/phone-number/.docs/instructions.append.md @@ -0,0 +1,8 @@ +# Instructions append + +When an input is invalid your function must throw an `ArgumentError`. +Invalid inputs include: +- `apple` +- `100` +- `2 555 555 1234` +- `100 200 3000` diff --git a/exercises/practice/phone-number/.docs/instructions.md b/exercises/practice/phone-number/.docs/instructions.md index 932be570..62ba48e9 100644 --- a/exercises/practice/phone-number/.docs/instructions.md +++ b/exercises/practice/phone-number/.docs/instructions.md @@ -2,21 +2,26 @@ Clean up user-entered phone numbers so that they can be sent SMS messages. -The **North American Numbering Plan (NANP)** is a telephone numbering system used by many countries in North America like the United States, Canada or Bermuda. All NANP-countries share the same international country code: `1`. +The **North American Numbering Plan (NANP)** is a telephone numbering system used by many countries in North America like the United States, Canada or Bermuda. +All NANP-countries share the same international country code: `1`. -NANP numbers are ten-digit numbers consisting of a three-digit Numbering Plan Area code, commonly known as *area code*, followed by a seven-digit local number. The first three digits of the local number represent the *exchange code*, followed by the unique four-digit number which is the *subscriber number*. +NANP numbers are ten-digit numbers consisting of a three-digit Numbering Plan Area code, commonly known as _area code_, followed by a seven-digit local number. +The first three digits of the local number represent the _exchange code_, followed by the unique four-digit number which is the _subscriber number_. The format is usually represented as ```text -(NXX)-NXX-XXXX +NXX NXX-XXXX ``` where `N` is any digit from 2 through 9 and `X` is any digit from 0 through 9. -Your task is to clean up differently formatted telephone numbers by removing punctuation and the country code (1) if present. +Sometimes they also have the country code (represented as `1` or `+1`) prefixed. + +Your task is to clean up differently formatted telephone numbers by removing punctuation and the country code if present. For example, the inputs + - `+1 (613)-995-0253` - `613-995-0253` - `1 613 995 0253` @@ -27,10 +32,3 @@ should all produce the output `6139950253` **Note:** As this exercise only deals with telephone numbers used in NANP-countries, only 1 is considered a valid country code. - -When an input is invalid your function must throw an `ArgumentError`. -Invalid inputs include: -- `apple` -- `100` -- `2 555 555 1234` -- `100 200 3000` diff --git a/exercises/practice/phone-number/.meta/config.json b/exercises/practice/phone-number/.meta/config.json index 12c2dc0c..4f66211f 100644 --- a/exercises/practice/phone-number/.meta/config.json +++ b/exercises/practice/phone-number/.meta/config.json @@ -19,6 +19,6 @@ ".meta/example.jl" ] }, - "source": "Event Manager by JumpstartLab", - "source_url": "http://tutorials.jumpstartlab.com/projects/eventmanager.html" + "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", + "source_url": "https://turing.edu" } diff --git a/exercises/practice/phone-number/runtests.jl b/exercises/practice/phone-number/runtests.jl index 80e91447..9374d5fa 100644 --- a/exercises/practice/phone-number/runtests.jl +++ b/exercises/practice/phone-number/runtests.jl @@ -34,20 +34,22 @@ const invalid_num = ( "1 (223) 156-7890", ) -@testset "clean 10-digit number" begin - @testset "$number" for number in valid_10digit_num - @test clean(number) == expected_number +@testset verbose = true "tests" begin + @testset "clean 10-digit number" begin + @testset "$number" for number in valid_10digit_num + @test clean(number) == expected_number + end end -end -@testset "clean 11-digit number starting with 1" begin - @testset "$number" for number in valid_11digit_num - @test clean(number) == expected_number + @testset "clean 11-digit number starting with 1" begin + @testset "$number" for number in valid_11digit_num + @test clean(number) == expected_number + end end -end -@testset "detect invalid number" begin - @testset "$number" for number in invalid_num - @test_throws ArgumentError clean(number) + @testset "detect invalid number" begin + @testset "$number" for number in invalid_num + @test_throws ArgumentError clean(number) + end end end diff --git a/exercises/practice/prime-factors/.docs/instructions.md b/exercises/practice/prime-factors/.docs/instructions.md index 494d3dfc..252cc8ee 100644 --- a/exercises/practice/prime-factors/.docs/instructions.md +++ b/exercises/practice/prime-factors/.docs/instructions.md @@ -10,21 +10,27 @@ Note that 1 is not a prime number. What are the prime factors of 60? -- Our first divisor is 2. 2 goes into 60, leaving 30. +- Our first divisor is 2. + 2 goes into 60, leaving 30. - 2 goes into 30, leaving 15. - - 2 doesn't go cleanly into 15. So let's move on to our next divisor, 3. + - 2 doesn't go cleanly into 15. + So let's move on to our next divisor, 3. - 3 goes cleanly into 15, leaving 5. - - 3 does not go cleanly into 5. The next possible factor is 4. - - 4 does not go cleanly into 5. The next possible factor is 5. + - 3 does not go cleanly into 5. + The next possible factor is 4. + - 4 does not go cleanly into 5. + The next possible factor is 5. - 5 does go cleanly into 5. - We're left only with 1, so now, we're done. -Our successful divisors in that computation represent the list of prime -factors of 60: 2, 2, 3, and 5. +Our successful divisors in that computation represent the list of prime factors of 60: 2, 2, 3, and 5. You can check this yourself: -- 2 \* 2 \* 3 * 5 -- = 4 * 15 -- = 60 -- Success! +```text +2 * 2 * 3 * 5 += 4 * 15 += 60 +``` + +Success! diff --git a/exercises/practice/prime-factors/.meta/config.json b/exercises/practice/prime-factors/.meta/config.json index 1e2dd5db..e98435ef 100644 --- a/exercises/practice/prime-factors/.meta/config.json +++ b/exercises/practice/prime-factors/.meta/config.json @@ -18,5 +18,5 @@ ] }, "source": "The Prime Factors Kata by Uncle Bob", - "source_url": "http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata" + "source_url": "https://web.archive.org/web/20221026171801/http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata" } diff --git a/exercises/practice/prime-factors/runtests.jl b/exercises/practice/prime-factors/runtests.jl index cf5cc7b5..3432fa84 100644 --- a/exercises/practice/prime-factors/runtests.jl +++ b/exercises/practice/prime-factors/runtests.jl @@ -1,50 +1,53 @@ -include("prime-factors.jl") using Test -@testset "no factors" begin - @test prime_factors(1) == [] -end +include("prime-factors.jl") -@testset "prime number" begin - @test prime_factors(2) == [2] -end +@testset verbose = true "tests" begin + @testset "no factors" begin + @test prime_factors(1) == [] + end -@testset "another prime number" begin - @test prime_factors(3) == [3] -end + @testset "prime number" begin + @test prime_factors(2) == [2] + end -@testset "product of first prime" begin - @test prime_factors(4) == [2, 2] -end + @testset "another prime number" begin + @test prime_factors(3) == [3] + end -@testset "square of a prime" begin - @test prime_factors(9) == [3, 3] -end + @testset "product of first prime" begin + @test prime_factors(4) == [2, 2] + end -@testset "product of first and second prime" begin - @test prime_factors(6) == [2, 3] -end + @testset "square of a prime" begin + @test prime_factors(9) == [3, 3] + end -@testset "cube of a prime" begin - @test prime_factors(8) == [2, 2, 2] -end + @testset "product of first and second prime" begin + @test prime_factors(6) == [2, 3] + end -@testset "product of second prime" begin - @test prime_factors(27) == [3, 3, 3] -end + @testset "cube of a prime" begin + @test prime_factors(8) == [2, 2, 2] + end -@testset "product of primes and non-primes" begin - @test prime_factors(12) == [2, 2, 3] -end + @testset "product of second prime" begin + @test prime_factors(27) == [3, 3, 3] + end -@testset "product of third prime" begin - @test prime_factors(625) == [5, 5, 5, 5] -end + @testset "product of primes and non-primes" begin + @test prime_factors(12) == [2, 2, 3] + end -@testset "product of primes" begin - @test prime_factors(901255) == [5, 17, 23, 461] -end + @testset "product of third prime" begin + @test prime_factors(625) == [5, 5, 5, 5] + end + + @testset "product of primes" begin + @test prime_factors(901255) == [5, 17, 23, 461] + end -@testset "factors include a large prime" begin - @test prime_factors(93819012551) == [11, 9539, 894119] + @testset "factors include a large prime" begin + @test prime_factors(93819012551) == [11, 9539, 894119] + end end diff --git a/exercises/practice/pythagorean-triplet/.docs/instructions.md b/exercises/practice/pythagorean-triplet/.docs/instructions.md index c38e2ef5..1c1a8aea 100644 --- a/exercises/practice/pythagorean-triplet/.docs/instructions.md +++ b/exercises/practice/pythagorean-triplet/.docs/instructions.md @@ -1,12 +1,23 @@ # Instructions -`(3, 4, 5)` and `(5, 12, 13)` are both Pythogorean triplets. -A Pythagorean triplet is three natural numbers `(a, b, c)` such that: `a^2 + b^2 = c^2` and `a < b < c`. +A Pythagorean triplet is a set of three natural numbers, {a, b, c}, for which, -In this exercise you must find all Pythagorean triplets that sum to a target value `N` and return them in ascending order. +```text +a² + b² = c² +``` -## Examples +and such that, -For `N = 24`, there is one triplet that sums to 24: `(6, 8, 10)`. +```text +a < b < c +``` -For `N = 60`, there are two triplets that sum to 60: `(10, 24, 26)` and `(15, 20 , 25)`. You should return them in that order. +For example, + +```text +3² + 4² = 5². +``` + +Given an input integer N, find all Pythagorean triplets for which `a + b + c = N`. + +For example, with N = 1000, there is exactly one Pythagorean triplet for which `a + b + c = 1000`: `{200, 375, 425}`. diff --git a/exercises/practice/pythagorean-triplet/.meta/config.json b/exercises/practice/pythagorean-triplet/.meta/config.json index 935810c1..6a1ed465 100644 --- a/exercises/practice/pythagorean-triplet/.meta/config.json +++ b/exercises/practice/pythagorean-triplet/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product a * b * c.", + "blurb": "There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the triplet.", "authors": [ "TheComputerM" ], @@ -19,5 +19,5 @@ ] }, "source": "Problem 9 at Project Euler", - "source_url": "http://projecteuler.net/problem=9" + "source_url": "https://projecteuler.net/problem=9" } diff --git a/exercises/practice/pythagorean-triplet/runtests.jl b/exercises/practice/pythagorean-triplet/runtests.jl index e747147c..6fb444bd 100644 --- a/exercises/practice/pythagorean-triplet/runtests.jl +++ b/exercises/practice/pythagorean-triplet/runtests.jl @@ -1,7 +1,7 @@ using Test include("pythagorean-triplet.jl") -@testset verbose = true "Pythagorean Triplet" begin +@testset verbose = true "tests" begin @testset "triplets whose sum is 12" begin @test pythagorean_triplets(12) == [(3, 4, 5)] end diff --git a/exercises/practice/raindrops/.docs/instructions.md b/exercises/practice/raindrops/.docs/instructions.md index a78585df..df644107 100644 --- a/exercises/practice/raindrops/.docs/instructions.md +++ b/exercises/practice/raindrops/.docs/instructions.md @@ -1,16 +1,24 @@ # Instructions -Your task is to convert a number into a string that contains raindrop sounds corresponding to certain potential factors. A factor is a number that evenly divides into another number, leaving no remainder. The simplest way to test if a one number is a factor of another is to use the [modulo operation](https://en.wikipedia.org/wiki/Modulo_operation). +Your task is to convert a number into its corresponding raindrop sounds. -The rules of `raindrops` are that if a given number: +If a given number: -- has 3 as a factor, add 'Pling' to the result. -- has 5 as a factor, add 'Plang' to the result. -- has 7 as a factor, add 'Plong' to the result. -- _does not_ have any of 3, 5, or 7 as a factor, the result should be the digits of the 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 has 7 as a factor, but not 3 or 5, so the result would be "Plong". -- 30 has both 3 and 5 as factors, but not 7, so the result would be "PlingPlang". -- 34 is not factored by 3, 5, or 7, so the result would be "34". +- 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 +~~~~ diff --git a/exercises/practice/raindrops/.docs/introduction.md b/exercises/practice/raindrops/.docs/introduction.md new file mode 100644 index 00000000..ba12100f --- /dev/null +++ b/exercises/practice/raindrops/.docs/introduction.md @@ -0,0 +1,3 @@ +# Introduction + +Raindrops is a slightly more complex version of the FizzBuzz challenge, a classic interview question. diff --git a/exercises/practice/raindrops/.meta/config.json b/exercises/practice/raindrops/.meta/config.json index e5cc206d..76c19393 100644 --- a/exercises/practice/raindrops/.meta/config.json +++ b/exercises/practice/raindrops/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Convert a number to a string, the content of which depends on the number's factors.", + "blurb": "Convert a number into its corresponding raindrop sounds - Pling, Plang and Plong.", "authors": [ "andrej-makarov-skrt" ], diff --git a/exercises/practice/raindrops/runtests.jl b/exercises/practice/raindrops/runtests.jl index 2292e2a2..c423f340 100644 --- a/exercises/practice/raindrops/runtests.jl +++ b/exercises/practice/raindrops/runtests.jl @@ -2,7 +2,7 @@ using Test include("raindrops.jl") -@testset verbose = true "Raindrops" begin +@testset verbose = true "tests" begin @testset "detect numbers" begin @testset "the sound for 1 is 1" begin @test raindrops(1) == "1" diff --git a/exercises/practice/rational-numbers/runtests.jl b/exercises/practice/rational-numbers/runtests.jl index c3afc02e..c23b14c6 100644 --- a/exercises/practice/rational-numbers/runtests.jl +++ b/exercises/practice/rational-numbers/runtests.jl @@ -2,148 +2,150 @@ using Test include("rational-numbers.jl") -@test RationalNumber <: Real -@test_throws ArgumentError RationalNumber(0, 0) - -@testset "Conversion and promotion" begin - # To pass these tests you should define a promote_rule method and a - # constructor, you don't need to define methods such as - # `==(a::RationalNumber{Int}, b::Int)`, `promote_type`, `convert`, etc. - # - # Read the manual for how to do this and why: - # https://docs.julialang.org/en/v1/manual/conversion-and-promotion/ - @test RationalNumber{Int}(10) == 10 - @test promote_type(Int, RationalNumber{Int}) == RationalNumber{Int} - @test convert(RationalNumber{Int8}, 2) isa RationalNumber{Int8} -end - -@testset "One- & Zero-elements" begin - @test zero(RationalNumber{Int}) == RationalNumber(0, 1) - @test one(RationalNumber{Int}) == RationalNumber(1, 1) -end - -@testset "Arithmetic" begin - @testset "Addition" begin - @test RationalNumber( 1, 2) + RationalNumber( 2, 3) == RationalNumber( 7, 6) - @test RationalNumber( 1, 2) + RationalNumber(-2, 3) == RationalNumber(-1, 6) - @test RationalNumber(-1, 2) + RationalNumber(-2, 3) == RationalNumber(-7, 6) - @test RationalNumber( 1, 2) + RationalNumber(-1, 2) == RationalNumber( 0, 1) - @test RationalNumber(1, 2) + 4 == RationalNumber(9, 2) - @test 4 + RationalNumber(1, 2) == RationalNumber(9, 2) +@testset verbose = true "tests" begin + @test RationalNumber <: Real + @test_throws ArgumentError RationalNumber(0, 0) + + @testset "Conversion and promotion" begin + # To pass these tests you should define a promote_rule method and a + # constructor, you don't need to define methods such as + # `==(a::RationalNumber{Int}, b::Int)`, `promote_type`, `convert`, etc. + # + # Read the manual for how to do this and why: + # https://docs.julialang.org/en/v1/manual/conversion-and-promotion/ + @test RationalNumber{Int}(10) == 10 + @test promote_type(Int, RationalNumber{Int}) == RationalNumber{Int} + @test convert(RationalNumber{Int8}, 2) isa RationalNumber{Int8} end - @testset "Subtraction" begin - @test RationalNumber( 1, 2) - RationalNumber( 2, 3) == RationalNumber(-1, 6) - @test RationalNumber( 1, 2) - RationalNumber(-2, 3) == RationalNumber( 7, 6) - @test RationalNumber(-1, 2) - RationalNumber(-2, 3) == RationalNumber( 1, 6) - @test RationalNumber( 1, 2) - RationalNumber( 1, 2) == RationalNumber( 0, 1) + @testset "One- & Zero-elements" begin + @test zero(RationalNumber{Int}) == RationalNumber(0, 1) + @test one(RationalNumber{Int}) == RationalNumber(1, 1) end - @testset "Multiplication" begin - @test RationalNumber( 1, 2) * RationalNumber( 2, 3) == RationalNumber( 1, 3) - @test RationalNumber(-1, 2) * RationalNumber( 2, 3) == RationalNumber(-1, 3) - @test RationalNumber(-1, 2) * RationalNumber(-2, 3) == RationalNumber( 1, 3) - @test RationalNumber( 1, 2) * RationalNumber( 2, 1) == RationalNumber( 1, 1) - @test RationalNumber( 1, 2) * RationalNumber( 1, 1) == RationalNumber( 1, 2) - @test RationalNumber( 1, 2) * RationalNumber( 0, 1) == RationalNumber( 0, 1) - end + @testset "Arithmetic" begin + @testset "Addition" begin + @test RationalNumber( 1, 2) + RationalNumber( 2, 3) == RationalNumber( 7, 6) + @test RationalNumber( 1, 2) + RationalNumber(-2, 3) == RationalNumber(-1, 6) + @test RationalNumber(-1, 2) + RationalNumber(-2, 3) == RationalNumber(-7, 6) + @test RationalNumber( 1, 2) + RationalNumber(-1, 2) == RationalNumber( 0, 1) + @test RationalNumber(1, 2) + 4 == RationalNumber(9, 2) + @test 4 + RationalNumber(1, 2) == RationalNumber(9, 2) + end - @testset "Exponentiation" begin - @testset "Exponentiation of a rational number" begin - @test RationalNumber( 1, 2)^3 == RationalNumber( 1, 8) - @test RationalNumber(-1, 2)^3 == RationalNumber( -1, 8) - @test RationalNumber( 0, 1)^5 == RationalNumber( 0, 1) - @test RationalNumber( 1, 1)^4 == RationalNumber( 1, 1) - @test RationalNumber( 1, 2)^0 == RationalNumber( 1, 1) - @test RationalNumber(-1, 2)^0 == RationalNumber( 1, 1) - @test RationalNumber( 3, 5)^-2 == RationalNumber( 25, 9) - @test RationalNumber(-3, 5)^-3 == RationalNumber(-125, 27) + @testset "Subtraction" begin + @test RationalNumber( 1, 2) - RationalNumber( 2, 3) == RationalNumber(-1, 6) + @test RationalNumber( 1, 2) - RationalNumber(-2, 3) == RationalNumber( 7, 6) + @test RationalNumber(-1, 2) - RationalNumber(-2, 3) == RationalNumber( 1, 6) + @test RationalNumber( 1, 2) - RationalNumber( 1, 2) == RationalNumber( 0, 1) end - @testset "Exponentiation of a real number to a rational number" begin - @test 8^RationalNumber( 4, 3) ≈ 15.999999999999998 - @test 9^RationalNumber(-1, 2) ≈ 0.3333333333333333 - @test 2^RationalNumber( 0, 1) ≈ 1.0 + @testset "Multiplication" begin + @test RationalNumber( 1, 2) * RationalNumber( 2, 3) == RationalNumber( 1, 3) + @test RationalNumber(-1, 2) * RationalNumber( 2, 3) == RationalNumber(-1, 3) + @test RationalNumber(-1, 2) * RationalNumber(-2, 3) == RationalNumber( 1, 3) + @test RationalNumber( 1, 2) * RationalNumber( 2, 1) == RationalNumber( 1, 1) + @test RationalNumber( 1, 2) * RationalNumber( 1, 1) == RationalNumber( 1, 2) + @test RationalNumber( 1, 2) * RationalNumber( 0, 1) == RationalNumber( 0, 1) + end + + @testset "Exponentiation" begin + @testset "Exponentiation of a rational number" begin + @test RationalNumber( 1, 2)^3 == RationalNumber( 1, 8) + @test RationalNumber(-1, 2)^3 == RationalNumber( -1, 8) + @test RationalNumber( 0, 1)^5 == RationalNumber( 0, 1) + @test RationalNumber( 1, 1)^4 == RationalNumber( 1, 1) + @test RationalNumber( 1, 2)^0 == RationalNumber( 1, 1) + @test RationalNumber(-1, 2)^0 == RationalNumber( 1, 1) + @test RationalNumber( 3, 5)^-2 == RationalNumber( 25, 9) + @test RationalNumber(-3, 5)^-3 == RationalNumber(-125, 27) + end + + @testset "Exponentiation of a real number to a rational number" begin + @test 8^RationalNumber( 4, 3) ≈ 15.999999999999998 + @test 9^RationalNumber(-1, 2) ≈ 0.3333333333333333 + @test 2^RationalNumber( 0, 1) ≈ 1.0 + end + end + + @testset "Division" begin + @test RationalNumber( 1, 2) / RationalNumber( 2, 3) == RationalNumber( 3, 4) + @test RationalNumber( 1, 2) / RationalNumber(-2, 3) == RationalNumber(-3, 4) + @test RationalNumber(-1, 2) / RationalNumber(-2, 3) == RationalNumber( 3, 4) + @test RationalNumber( 1, 2) / RationalNumber( 1, 1) == RationalNumber( 1, 2) end end - @testset "Division" begin - @test RationalNumber( 1, 2) / RationalNumber( 2, 3) == RationalNumber( 3, 4) - @test RationalNumber( 1, 2) / RationalNumber(-2, 3) == RationalNumber(-3, 4) - @test RationalNumber(-1, 2) / RationalNumber(-2, 3) == RationalNumber( 3, 4) - @test RationalNumber( 1, 2) / RationalNumber( 1, 1) == RationalNumber( 1, 2) + @testset "Absolute value" begin + @test abs(RationalNumber( 1, 2)) == RationalNumber(1, 2) + @test abs(RationalNumber(-1, 2)) == RationalNumber(1, 2) + @test abs(RationalNumber( 0, 1)) == RationalNumber(0, 1) + @test abs(RationalNumber( 1, -2)) == RationalNumber(1, 2) + @test abs(RationalNumber( 2, 4)) == RationalNumber(1, 2) end -end -@testset "Absolute value" begin - @test abs(RationalNumber( 1, 2)) == RationalNumber(1, 2) - @test abs(RationalNumber(-1, 2)) == RationalNumber(1, 2) - @test abs(RationalNumber( 0, 1)) == RationalNumber(0, 1) - @test abs(RationalNumber( 1, -2)) == RationalNumber(1, 2) - @test abs(RationalNumber( 2, 4)) == RationalNumber(1, 2) -end + @testset "Reduction to lowest terms" begin + r = RationalNumber(2, 4) + @test numerator(r) == 1 + @test denominator(r) == 2 + + r = RationalNumber(-4, 6) + @test numerator(r) == -2 + @test denominator(r) == 3 + + r = RationalNumber(3, -9) + @test numerator(r) == -1 + @test denominator(r) == 3 + + r = RationalNumber(0, 6) + @test numerator(r) == 0 + @test denominator(r) == 1 + + r = RationalNumber(-14, 7) + @test numerator(r) == -2 + @test denominator(r) == 1 + + r = RationalNumber(13, 13) + @test numerator(r) == 1 + @test denominator(r) == 1 + + r = RationalNumber(1, -1) + @test numerator(r) == -1 + @test denominator(r) == 1 -@testset "Reduction to lowest terms" begin - r = RationalNumber(2, 4) - @test numerator(r) == 1 - @test denominator(r) == 2 - - r = RationalNumber(-4, 6) - @test numerator(r) == -2 - @test denominator(r) == 3 - - r = RationalNumber(3, -9) - @test numerator(r) == -1 - @test denominator(r) == 3 - - r = RationalNumber(0, 6) - @test numerator(r) == 0 - @test denominator(r) == 1 - - r = RationalNumber(-14, 7) - @test numerator(r) == -2 - @test denominator(r) == 1 - - r = RationalNumber(13, 13) - @test numerator(r) == 1 - @test denominator(r) == 1 - - r = RationalNumber(1, -1) - @test numerator(r) == -1 - @test denominator(r) == 1 - - r = RationalNumber(3, -4) - @test numerator(r) == -3 - @test denominator(r) == 4 -end + r = RationalNumber(3, -4) + @test numerator(r) == -3 + @test denominator(r) == 4 + end -# The following testset is based on the tests for rational numbers in Julia Base (MIT license) -# https://github.com/JuliaLang/julia/blob/52bafeb981bac548afd2264edb518d8d86944dca/test/rational.jl -# https://github.com/JuliaLang/julia/blob/52bafeb981bac548afd2264edb518d8d86944dca/LICENSE.md -@testset "Ordering" begin - for a in -5:5, b in -5:5, c in -5:5 - b == 0 && continue - - r = RationalNumber(a, b) - - @test (r == c) == (a / b == c) - @test (r != c) == (a / b != c) - @test (r <= c) == (a / b <= c) - @test (r < c) == (a / b < c) - @test (r >= c) == (a / b >= c) - @test (r > c) == (a / b > c) - - for d in -5:5 - d == 0 && continue - - s = RationalNumber(c, d) - - @test (r == s) == (a / b == c / d) - @test (r != s) == (a / b != c / d) - @test (r <= s) == (a / b <= c / d) - @test (r < s) == (a / b < c / d) - @test (r >= s) == (a / b >= c / d) - @test (r > s) == (a / b > c / d) + # The following testset is based on the tests for rational numbers in Julia Base (MIT license) + # https://github.com/JuliaLang/julia/blob/52bafeb981bac548afd2264edb518d8d86944dca/test/rational.jl + # https://github.com/JuliaLang/julia/blob/52bafeb981bac548afd2264edb518d8d86944dca/LICENSE.md + @testset "Ordering" begin + for a in -5:5, b in -5:5, c in -5:5 + b == 0 && continue + + r = RationalNumber(a, b) + + @test (r == c) == (a / b == c) + @test (r != c) == (a / b != c) + @test (r <= c) == (a / b <= c) + @test (r < c) == (a / b < c) + @test (r >= c) == (a / b >= c) + @test (r > c) == (a / b > c) + + for d in -5:5 + d == 0 && continue + + s = RationalNumber(c, d) + + @test (r == s) == (a / b == c / d) + @test (r != s) == (a / b != c / d) + @test (r <= s) == (a / b <= c / d) + @test (r < s) == (a / b < c / d) + @test (r >= s) == (a / b >= c / d) + @test (r > s) == (a / b > c / d) + end end end end diff --git a/exercises/practice/resistor-color-trio/.docs/instructions.md b/exercises/practice/resistor-color-trio/.docs/instructions.md index 4ad2aede..59d22783 100644 --- a/exercises/practice/resistor-color-trio/.docs/instructions.md +++ b/exercises/practice/resistor-color-trio/.docs/instructions.md @@ -23,7 +23,7 @@ For this exercise, you need to know only three things about them: - Grey: 8 - White: 9 -In `resistor-color duo` you decoded the first two colors. +In Resistor Color Duo you decoded the first two colors. For instance: orange-orange got the main value `33`. The third color stands for how many zeros need to be added to the main value. The main value plus the zeros gives us a value in ohms. diff --git a/exercises/practice/resistor-color-trio/runtests.jl b/exercises/practice/resistor-color-trio/runtests.jl index 48399612..9d88269c 100644 --- a/exercises/practice/resistor-color-trio/runtests.jl +++ b/exercises/practice/resistor-color-trio/runtests.jl @@ -2,42 +2,44 @@ using Test include("resistor-color-trio.jl") -@testset "Orange and orange and black" begin - @test label(["orange", "orange", "black"]) == "33 ohms" -end - -@testset "Blue and grey and brown" begin - @test label(["blue", "grey", "brown"]) == "680 ohms" -end - -@testset "Red and black and red" begin - @test label(["red", "black", "red"]) == "2 kiloohms" -end - -@testset "Green and brown and orange" begin - @test label(["green", "brown", "orange"]) == "51 kiloohms" -end - -@testset "Yellow and violet and yellow" begin - @test label(["yellow", "violet", "yellow"]) == "470 kiloohms" -end - -@testset "Orange and orange and red" begin - @test label(["orange", "orange", "red"]) == "3.3 kiloohms" -end - -@testset "Orange and orange and green" begin - @test label(["orange", "orange", "green"]) == "3.3 megaohms" -end - -@testset "White and white and violet" begin - @test label(["white", "white", "violet"]) == "990 megaohms" -end - -@testset "White and white and grey" begin - @test label(["white", "white", "grey"]) == "9.9 gigaohms" -end - -@testset "White and black and white" begin - @test label(["white", "black", "white"]) == "90 gigaohms" +@testset verbose = true "tests" begin + @testset "Orange and orange and black" begin + @test label(["orange", "orange", "black"]) == "33 ohms" + end + + @testset "Blue and grey and brown" begin + @test label(["blue", "grey", "brown"]) == "680 ohms" + end + + @testset "Red and black and red" begin + @test label(["red", "black", "red"]) == "2 kiloohms" + end + + @testset "Green and brown and orange" begin + @test label(["green", "brown", "orange"]) == "51 kiloohms" + end + + @testset "Yellow and violet and yellow" begin + @test label(["yellow", "violet", "yellow"]) == "470 kiloohms" + end + + @testset "Orange and orange and red" begin + @test label(["orange", "orange", "red"]) == "3.3 kiloohms" + end + + @testset "Orange and orange and green" begin + @test label(["orange", "orange", "green"]) == "3.3 megaohms" + end + + @testset "White and white and violet" begin + @test label(["white", "white", "violet"]) == "990 megaohms" + end + + @testset "White and white and grey" begin + @test label(["white", "white", "grey"]) == "9.9 gigaohms" + end + + @testset "White and black and white" begin + @test label(["white", "black", "white"]) == "90 gigaohms" + end end diff --git a/exercises/practice/resistor-color/.docs/instructions.md b/exercises/practice/resistor-color/.docs/instructions.md new file mode 100644 index 00000000..646c1439 --- /dev/null +++ b/exercises/practice/resistor-color/.docs/instructions.md @@ -0,0 +1,39 @@ +# Instructions + +If you want to build something using a Raspberry Pi, you'll probably use _resistors_. +For this exercise, you need to know two things about them: + +- Each resistor has a resistance value. +- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. + +To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. +Each band has a position and a numeric value. + +The first 2 bands of a resistor have a simple encoding scheme: each color maps to a single number. + +In this exercise you are going to create a helpful program so that you don't have to remember the values of the bands. + +These colors are encoded as follows: + +- Black: 0 +- Brown: 1 +- Red: 2 +- Orange: 3 +- Yellow: 4 +- Green: 5 +- Blue: 6 +- Violet: 7 +- Grey: 8 +- White: 9 + +The goal of this exercise is to create a way: + +- to look up the numerical value associated with a particular color band +- to list the different band colors + +Mnemonics map the colors to the numbers, that, when stored as an array, happen to map to their index in the array: +Better Be Right Or Your Great Big Values Go Wrong. + +More information on the color encoding of resistors can be found in the [Electronic color code Wikipedia article][e-color-code]. + +[e-color-code]: https://en.wikipedia.org/wiki/Electronic_color_code diff --git a/exercises/practice/resistor-color/.meta/config.json b/exercises/practice/resistor-color/.meta/config.json new file mode 100644 index 00000000..c62ab5c6 --- /dev/null +++ b/exercises/practice/resistor-color/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "resistor-color.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Convert a resistor band's color to its numeric representation.", + "source": "Maud de Vries, Erik Schierboom", + "source_url": "https://github.com/exercism/problem-specifications/issues/1458" +} diff --git a/exercises/practice/resistor-color/.meta/example.jl b/exercises/practice/resistor-color/.meta/example.jl new file mode 100644 index 00000000..059adeff --- /dev/null +++ b/exercises/practice/resistor-color/.meta/example.jl @@ -0,0 +1,20 @@ +const COLORS = ( + "black", + "brown", + "red", + "orange", + "yellow", + "green", + "blue", + "violet", + "grey", + "white" +) + +function colorcode(color) + findfirst(==(color), COLORS) - 1 +end + +function colors() + COLORS +end diff --git a/exercises/practice/resistor-color/.meta/tests.toml b/exercises/practice/resistor-color/.meta/tests.toml new file mode 100644 index 00000000..9d4ee973 --- /dev/null +++ b/exercises/practice/resistor-color/.meta/tests.toml @@ -0,0 +1,22 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[49eb31c5-10a8-4180-9f7f-fea632ab87ef] +description = "Color codes -> Black" + +[0a4df94b-92da-4579-a907-65040ce0b3fc] +description = "Color codes -> White" + +[5f81608d-f36f-4190-8084-f45116b6f380] +description = "Color codes -> Orange" + +[581d68fa-f968-4be2-9f9d-880f2fb73cf7] +description = "Colors" diff --git a/exercises/practice/resistor-color/resistor-color.jl b/exercises/practice/resistor-color/resistor-color.jl new file mode 100644 index 00000000..6c0dbe74 --- /dev/null +++ b/exercises/practice/resistor-color/resistor-color.jl @@ -0,0 +1,7 @@ +function colorcode(color) + +end + +function colors() + +end \ No newline at end of file diff --git a/exercises/practice/resistor-color/runtests.jl b/exercises/practice/resistor-color/runtests.jl new file mode 100644 index 00000000..90196dc9 --- /dev/null +++ b/exercises/practice/resistor-color/runtests.jl @@ -0,0 +1,33 @@ +using Test + +include("resistor-color.jl") + +@testset verbose = true "tests" begin + @testset "Black" begin + @test colorcode("black") == 0 + end + + @testset "White" begin + @test colorcode("white") == 9 + end + + @testset "Orange" begin + @test colorcode("orange") == 3 + end + + @testset "Colors" begin + expected_colors = [ + "black", + "brown", + "red", + "orange", + "yellow", + "green", + "blue", + "violet", + "grey", + "white" + ] + @test all(colors() .== expected_colors) + end +end diff --git a/exercises/practice/reverse-string/runtests.jl b/exercises/practice/reverse-string/runtests.jl index 7f9fd3a8..a5bf18e3 100644 --- a/exercises/practice/reverse-string/runtests.jl +++ b/exercises/practice/reverse-string/runtests.jl @@ -2,7 +2,7 @@ using Test include("reverse-string.jl") -@testset verbose = true "Reverse String" begin +@testset verbose = true "tests" begin @testset "an empty string" begin @test myreverse("") == "" end diff --git a/exercises/practice/rna-transcription/.meta/config.json b/exercises/practice/rna-transcription/.meta/config.json index ed41f221..489829e5 100644 --- a/exercises/practice/rna-transcription/.meta/config.json +++ b/exercises/practice/rna-transcription/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "Hyperphysics", - "source_url": "http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html" + "source_url": "https://web.archive.org/web/20220408112140/http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html" } diff --git a/exercises/practice/rna-transcription/runtests.jl b/exercises/practice/rna-transcription/runtests.jl index 676c641a..c58b381a 100644 --- a/exercises/practice/rna-transcription/runtests.jl +++ b/exercises/practice/rna-transcription/runtests.jl @@ -2,7 +2,7 @@ using Test include("rna-transcription.jl") -@testset verbose = true "RNA Transcription" begin +@testset verbose = true "tests" begin @testset "basic transformations" begin @testset "empty rna sequence" begin @test to_rna("") == "" diff --git a/exercises/practice/robot-name/.docs/instructions.md b/exercises/practice/robot-name/.docs/instructions.md index a0079a34..fca3a41a 100644 --- a/exercises/practice/robot-name/.docs/instructions.md +++ b/exercises/practice/robot-name/.docs/instructions.md @@ -4,13 +4,11 @@ Manage robot factory settings. When a robot comes off the factory floor, it has no name. -The first time you turn on a robot, a random name is generated in the format -of two uppercase letters followed by three digits, such as RX837 or BC811. +The first time you turn on a robot, a random name is generated in the format of two uppercase letters followed by three digits, such as RX837 or BC811. -Every once in a while we need to reset a robot to its factory settings, -which means that its name gets wiped. The next time you ask, that robot will -respond with a new random name. +Every once in a while we need to reset a robot to its factory settings, which means that its name gets wiped. +The next time you ask, that robot will respond with a new random name. The names must be random: they should not follow a predictable sequence. -Using random names means a risk of collisions. Your solution must ensure that -every existing robot has a unique name. +Using random names means a risk of collisions. +Your solution must ensure that every existing robot has a unique name. diff --git a/exercises/practice/robot-name/runtests.jl b/exercises/practice/robot-name/runtests.jl index 2f190298..9b95961b 100644 --- a/exercises/practice/robot-name/runtests.jl +++ b/exercises/practice/robot-name/runtests.jl @@ -9,72 +9,74 @@ const history = Set{String}() isname(x) = occursin(r"^[A-Z]{2}[0-9]{3}$", x) -@testset "one robot" begin - global r1 = Robot() - push!(history, name(r1)) +@testset verbose = true "tests" begin + @testset "one robot" begin + global r1 = Robot() + push!(history, name(r1)) - @testset "name of robot is valid" begin - @test isname(name(r1)) - end - - @testset "names of robot instance are valid and unique in history" begin - # @testset sets the same seed every time for reproducibility, but we're - # undoing that deliberately with Random.seed!() to increase the chance - # of seeing collisions. - Random.seed!() - for i in 1:100 - reset!(r1) + @testset "name of robot is valid" begin @test isname(name(r1)) - @test !in(name(r1), history) - push!(history, name(r1)) + end + + @testset "names of robot instance are valid and unique in history" begin + # @testset sets the same seed every time for reproducibility, but we're + # undoing that deliberately with Random.seed!() to increase the chance + # of seeing collisions. + Random.seed!() + for i in 1:100 + reset!(r1) + @test isname(name(r1)) + @test !in(name(r1), history) + push!(history, name(r1)) + end end end -end -@testset "two robots" begin - global r2 = Robot() - global r3 = Robot() + @testset "two robots" begin + global r2 = Robot() + global r3 = Robot() - @testset "names of robots are valid" begin - @test isname(name(r2)) - @test isname(name(r3)) - end - - @testset "names of robots are not equal" begin - @test name(r2) != name(r3) - end + @testset "names of robots are valid" begin + @test isname(name(r2)) + @test isname(name(r3)) + end + + @testset "names of robots are not equal" begin + @test name(r2) != name(r3) + end + + @testset "names of both robots are unique in history" begin + @test !in(name(r2), history) + @test !in(name(r3), history) + end - @testset "names of both robots are unique in history" begin - @test !in(name(r2), history) - @test !in(name(r3), history) + push!(history, name(r2)) + push!(history, name(r3)) end - push!(history, name(r2)) - push!(history, name(r3)) -end + @testset "many robots" begin + Random.seed!() + robots = Robot[] -@testset "many robots" begin - Random.seed!() - robots = Robot[] + for i in 1:100 + push!(robots, Robot()) - for i in 1:100 - push!(robots, Robot()) + @testset "name of robot is valid and unique in history" begin + @test isname(name(robots[i])) + @test !in(name(robots[i]), history) + end - @testset "name of robot is valid and unique in history" begin - @test isname(name(robots[i])) - @test !in(name(robots[i]), history) + push!(history, name(robots[i])) end - push!(history, name(robots[i])) - end - - @testset "fresh names of reset robots are valid and unique in history" begin - Random.seed!() - for r in robots - reset!(r) - @test isname(name(r)) - @test !in(name(r), history) - push!(history, name(r)) + @testset "fresh names of reset robots are valid and unique in history" begin + Random.seed!() + for r in robots + reset!(r) + @test isname(name(r)) + @test !in(name(r), history) + push!(history, name(r)) + end end end end diff --git a/exercises/practice/robot-simulator/.docs/instructions.md b/exercises/practice/robot-simulator/.docs/instructions.md index 83be50cc..0ac96ce0 100644 --- a/exercises/practice/robot-simulator/.docs/instructions.md +++ b/exercises/practice/robot-simulator/.docs/instructions.md @@ -10,13 +10,10 @@ The robots have three possible movements: - turn left - advance -Robots are placed on a hypothetical infinite grid, facing a particular -direction (north, east, south, or west) at a set of {x,y} coordinates, +Robots are placed on a hypothetical infinite grid, facing a particular direction (north, east, south, or west) at a set of {x,y} coordinates, e.g., {3,8}, with coordinates increasing to the north and east. -The robot then receives a number of instructions, at which point the -testing facility verifies the robot's new position, and in which -direction it is pointing. +The robot then receives a number of instructions, at which point the testing facility verifies the robot's new position, and in which direction it is pointing. - The letter-string "RAALAL" means: - Turn right @@ -24,5 +21,5 @@ direction it is pointing. - Turn left - Advance once - Turn left yet again -- Say a robot starts at {7, 3} facing north. Then running this stream - of instructions should leave it at {9, 4} facing west. +- Say a robot starts at {7, 3} facing north. + Then running this stream of instructions should leave it at {9, 4} facing west. diff --git a/exercises/practice/robot-simulator/runtests.jl b/exercises/practice/robot-simulator/runtests.jl index 4a6897c4..33fb8281 100644 --- a/exercises/practice/robot-simulator/runtests.jl +++ b/exercises/practice/robot-simulator/runtests.jl @@ -2,87 +2,89 @@ using Test include("robot-simulator.jl") -@testset "constructor" begin - r = Robot((0, 0), NORTH) - @test position(r) == Point(0, 0) - @test heading(r) == NORTH - - r = Robot((-1, -1), SOUTH) - @test position(r) == Point(-1, -1) - @test heading(r) == SOUTH -end - -@testset "mutating functions should return robot" begin - r = Robot((0, 0), NORTH) - @test r == turn_right!(r) - @test r == turn_left!(r) - @test r == advance!(r) - @test r == move!(r, "A") -end - -@testset "rotate +π/2" begin - r = Robot((0, 0), NORTH) - turn_right!(r) - @test position(r) == Point(0, 0) - @test heading(r) == EAST - turn_right!(r) - @test heading(r) == SOUTH - turn_right!(r) - @test heading(r) == WEST - turn_right!(r) - @test heading(r) == NORTH -end - -@testset "rotate -π/2" begin - r = Robot((0, 0), NORTH) - turn_left!(r) - @test position(r) == Point(0, 0) - @test heading(r) == WEST - turn_left!(r) - @test heading(r) == SOUTH - turn_left!(r) - @test heading(r) == EAST - turn_left!(r) - @test heading(r) == NORTH -end - -@testset "advance" begin - r = Robot((0, 0), NORTH) - advance!(r) - @test heading(r) == NORTH - @test position(r) == Point(0, 1) +@testset verbose = true "tests" begin + @testset "constructor" begin + r = Robot((0, 0), NORTH) + @test position(r) == Point(0, 0) + @test heading(r) == NORTH - @test position(advance!(Robot((0, 0), SOUTH))) == Point(0, -1) - @test position(advance!(Robot((0, 0), EAST))) == Point(1, 0) - @test position(advance!(Robot((0, 0), WEST))) == Point(-1, 0) -end + r = Robot((-1, -1), SOUTH) + @test position(r) == Point(-1, -1) + @test heading(r) == SOUTH + end -@testset "instructions" begin - @testset "moving east and north from README" begin - r = Robot((7, 3), NORTH) - move!(r, "RAALAL") - @test position(r) == Point(9, 4) - @test heading(r) == WEST + @testset "mutating functions should return robot" begin + r = Robot((0, 0), NORTH) + @test r == turn_right!(r) + @test r == turn_left!(r) + @test r == advance!(r) + @test r == move!(r, "A") end - @testset "move west and north" begin + @testset "rotate +π/2" begin r = Robot((0, 0), NORTH) - move!(r, "LAAARALA") - @test position(r) == Point(-4, 1) + turn_right!(r) + @test position(r) == Point(0, 0) + @test heading(r) == EAST + turn_right!(r) + @test heading(r) == SOUTH + turn_right!(r) @test heading(r) == WEST + turn_right!(r) + @test heading(r) == NORTH end - @testset "move west and south" begin - r = Robot((2, -7), EAST) - move!(r, "RRAAAAALA") - @test position(r) == Point(-3, -8) + @testset "rotate -π/2" begin + r = Robot((0, 0), NORTH) + turn_left!(r) + @test position(r) == Point(0, 0) + @test heading(r) == WEST + turn_left!(r) @test heading(r) == SOUTH + turn_left!(r) + @test heading(r) == EAST + turn_left!(r) + @test heading(r) == NORTH end - @testset "move east and north" begin - r = Robot((8, 4), SOUTH) - move!(r, "LAAARRRALLLL") - @test position(r) == Point(11, 5) + @testset "advance" begin + r = Robot((0, 0), NORTH) + advance!(r) @test heading(r) == NORTH + @test position(r) == Point(0, 1) + + @test position(advance!(Robot((0, 0), SOUTH))) == Point(0, -1) + @test position(advance!(Robot((0, 0), EAST))) == Point(1, 0) + @test position(advance!(Robot((0, 0), WEST))) == Point(-1, 0) + end + + @testset "instructions" begin + @testset "moving east and north from README" begin + r = Robot((7, 3), NORTH) + move!(r, "RAALAL") + @test position(r) == Point(9, 4) + @test heading(r) == WEST + end + + @testset "move west and north" begin + r = Robot((0, 0), NORTH) + move!(r, "LAAARALA") + @test position(r) == Point(-4, 1) + @test heading(r) == WEST + end + + @testset "move west and south" begin + r = Robot((2, -7), EAST) + move!(r, "RRAAAAALA") + @test position(r) == Point(-3, -8) + @test heading(r) == SOUTH + end + + @testset "move east and north" begin + r = Robot((8, 4), SOUTH) + move!(r, "LAAARRRALLLL") + @test position(r) == Point(11, 5) + @test heading(r) == NORTH + end end end diff --git a/exercises/practice/roman-numerals/.docs/instructions.md b/exercises/practice/roman-numerals/.docs/instructions.md index dd4ed09f..50e2f5bf 100644 --- a/exercises/practice/roman-numerals/.docs/instructions.md +++ b/exercises/practice/roman-numerals/.docs/instructions.md @@ -1,45 +1,12 @@ -# Instructions +# Introduction -Write a function to convert from normal numbers to Roman Numerals. +Your task is to convert a number from Arabic numerals to Roman numerals. -The Romans were a clever bunch. They conquered most of Europe and ruled -it for hundreds of years. They invented concrete and straight roads and -even bikinis. One thing they never discovered though was the number -zero. This made writing and dating extensive histories of their exploits -slightly more challenging, but the system of numbers they came up with -is still in use today. For example the BBC uses Roman numerals to date -their programs. +For this exercise, we are only concerned about traditional Roman numerals, in which the largest number is MMMCMXCIX (or 3,999). -The Romans wrote numbers using letters - I, V, X, L, C, D, M. (notice -these letters have lots of straight lines and are hence easy to hack -into stone tablets). +~~~~exercism/note +There are lots of different ways to convert between Arabic and Roman numerals. +We recommend taking a naive approach first to familiarise yourself with the concept of Roman numerals and then search for more efficient methods. -```text - 1 => I -10 => X - 7 => VII -``` - -There is no need to be able to convert numbers larger than about 3000. -(The Romans themselves didn't tend to go any higher) - -Wikipedia says: Modern Roman numerals ... are written by expressing each -digit separately starting with the left most digit and skipping any -digit with a value of zero. - -To see this in practice, consider the example of 1990. - -In Roman numerals 1990 is MCMXC: - -1000=M -900=CM -90=XC - -2008 is written as MMVIII: - -2000=MM -8=VIII - -There is no need to be able to convert numbers larger than about 3000. - -See also: [http://www.novaroma.org/via_romana/numbers.html](http://www.novaroma.org/via_romana/numbers.html) +Make sure to check out our Deep Dive video at the end to explore the different approaches you can take! +~~~~ diff --git a/exercises/practice/roman-numerals/.docs/introduction.md b/exercises/practice/roman-numerals/.docs/introduction.md new file mode 100644 index 00000000..6fd942fe --- /dev/null +++ b/exercises/practice/roman-numerals/.docs/introduction.md @@ -0,0 +1,59 @@ +# Description + +Today, most people in the world use Arabic numerals (0–9). +But if you travelled back two thousand years, you'd find that most Europeans were using Roman numerals instead. + +To write a Roman numeral we use the following Latin letters, each of which has a value: + +| M | D | C | L | X | V | I | +| ---- | --- | --- | --- | --- | --- | --- | +| 1000 | 500 | 100 | 50 | 10 | 5 | 1 | + +A Roman numeral is a sequence of these letters, and its value is the sum of the letters' values. +For example, `XVIII` has the value 18 (`10 + 5 + 1 + 1 + 1 = 18`). + +There's one rule that makes things trickier though, and that's that **the same letter cannot be used more than three times in succession**. +That means that we can't express numbers such as 4 with the seemingly natural `IIII`. +Instead, for those numbers, we use a subtraction method between two letters. +So we think of `4` not as `1 + 1 + 1 + 1` but instead as `5 - 1`. +And slightly confusingly to our modern thinking, we write the smaller number first. +This applies only in the following cases: 4 (`IV`), 9 (`IX`), 40 (`XL`), 90 (`XC`), 400 (`CD`) and 900 (`CM`). + +Order matters in Roman numerals! +Letters (and the special compounds above) must be ordered by decreasing value from left to right. + +Here are some examples: + +```text + 105 => CV +---- => -- + 100 => C ++ 5 => V +``` + +```text + 106 => CVI +---- => -- + 100 => C ++ 5 => V ++ 1 => I +``` + +```text + 104 => CIV +---- => --- + 100 => C ++ 4 => IV +``` + +And a final more complex example: + +```text + 1996 => MCMXCVI +----- => ------- + 1000 => M ++ 900 => CM ++ 90 => XC ++ 5 => V ++ 1 => I +``` diff --git a/exercises/practice/roman-numerals/.meta/config.json b/exercises/practice/roman-numerals/.meta/config.json index 04b2c2c3..70fd42de 100644 --- a/exercises/practice/roman-numerals/.meta/config.json +++ b/exercises/practice/roman-numerals/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Write a function to convert from normal numbers to Roman Numerals.", + "blurb": "Convert modern Arabic numbers into Roman numerals.", "authors": [ "andrej-makarov-skrt" ], @@ -19,5 +19,5 @@ ] }, "source": "The Roman Numeral Kata", - "source_url": "http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals" + "source_url": "https://codingdojo.org/kata/RomanNumerals/" } diff --git a/exercises/practice/roman-numerals/runtests.jl b/exercises/practice/roman-numerals/runtests.jl index 359573ed..19df99e7 100644 --- a/exercises/practice/roman-numerals/runtests.jl +++ b/exercises/practice/roman-numerals/runtests.jl @@ -34,11 +34,13 @@ samples = Dict( 3999 => "MMMCMXCIX", ) -@testset "convert $(sample[1]) to roman numeral" for sample in samples - @test to_roman(sample[1]) == sample[2] -end +@testset verbose = true "tests" begin + @testset "convert $(sample[1]) to roman numeral" for sample in samples + @test to_roman(sample[1]) == sample[2] + end -@testset "error handling" begin - @test_throws ErrorException to_roman(0) - @test_throws ErrorException to_roman(-2017) + @testset "error handling" begin + @test_throws ErrorException to_roman(0) + @test_throws ErrorException to_roman(-2017) + end end diff --git a/exercises/practice/rotational-cipher/.docs/instructions.md b/exercises/practice/rotational-cipher/.docs/instructions.md index dbf6276f..4bf64ca1 100644 --- a/exercises/practice/rotational-cipher/.docs/instructions.md +++ b/exercises/practice/rotational-cipher/.docs/instructions.md @@ -2,11 +2,9 @@ Create an implementation of the rotational cipher, also sometimes called the Caesar cipher. -The Caesar cipher is a simple shift cipher that relies on -transposing all the letters in the alphabet using an integer key -between `0` and `26`. Using a key of `0` or `26` will always yield -the same output due to modular arithmetic. The letter is shifted -for as many values as the value of the key. +The Caesar cipher is a simple shift cipher that relies on transposing all the letters in the alphabet using an integer key between `0` and `26`. +Using a key of `0` or `26` will always yield the same output due to modular arithmetic. +The letter is shifted for as many values as the value of the key. The general notation for rotational ciphers is `ROT + `. The most commonly used rotational cipher is `ROT13`. @@ -24,8 +22,8 @@ Ciphertext is written out in the same formatting as the input including spaces a ## Examples -- ROT5 `omg` gives `trl` -- ROT0 `c` gives `c` +- ROT5 `omg` gives `trl` +- ROT0 `c` gives `c` - ROT26 `Cool` gives `Cool` - ROT13 `The quick brown fox jumps over the lazy dog.` gives `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` - ROT13 `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` gives `The quick brown fox jumps over the lazy dog.` diff --git a/exercises/practice/rotational-cipher/runtests.jl b/exercises/practice/rotational-cipher/runtests.jl index e98ed0fc..2f6baf3c 100644 --- a/exercises/practice/rotational-cipher/runtests.jl +++ b/exercises/practice/rotational-cipher/runtests.jl @@ -2,7 +2,7 @@ using Test include("rotational-cipher.jl") -@testset verbose = true "Rotational Cipher" begin +@testset verbose = true "tests" begin @testset "rotate function" begin @testset "rotate by n" begin @testset "no wrap" begin diff --git a/exercises/practice/run-length-encoding/.docs/instructions.md b/exercises/practice/run-length-encoding/.docs/instructions.md index 95f7a9d6..fc8ce056 100644 --- a/exercises/practice/run-length-encoding/.docs/instructions.md +++ b/exercises/practice/run-length-encoding/.docs/instructions.md @@ -2,8 +2,7 @@ Implement run-length encoding and decoding. -Run-length encoding (RLE) is a simple form of data compression, where runs -(consecutive data elements) are replaced by just one data value and count. +Run-length encoding (RLE) is a simple form of data compression, where runs (consecutive data elements) are replaced by just one data value and count. For example we can represent the original 53 characters with only 13. @@ -11,14 +10,11 @@ For example we can represent the original 53 characters with only 13. "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" -> "12WB12W3B24WB" ``` -RLE allows the original data to be perfectly reconstructed from -the compressed data, which makes it a lossless data compression. +RLE allows the original data to be perfectly reconstructed from the compressed data, which makes it a lossless data compression. ```text "AABCCCDEEEE" -> "2AB3CD4E" -> "AABCCCDEEEE" ``` -For simplicity, you can assume that the unencoded string will only contain -the letters A through Z (either lower or upper case) and whitespace. This way -data to be encoded will never contain any numbers and numbers inside data to -be decoded always represent the count for the following character. +For simplicity, you can assume that the unencoded string will only contain the letters A through Z (either lower or upper case) and whitespace. +This way data to be encoded will never contain any numbers and numbers inside data to be decoded always represent the count for the following character. diff --git a/exercises/practice/run-length-encoding/runtests.jl b/exercises/practice/run-length-encoding/runtests.jl index a4067147..eb3573d5 100644 --- a/exercises/practice/run-length-encoding/runtests.jl +++ b/exercises/practice/run-length-encoding/runtests.jl @@ -6,24 +6,26 @@ include("run-length-encoding.jl") # Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0 # Encode and decode the strings under the given specifications. -@testset "encode strings" begin - @test encode("") == "" - @test encode("XYZ") == "XYZ" - @test encode("AABBBCCCC") == "2A3B4C" - @test encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB") == "12WB12W3B24WB" - @test encode("aabbbcccc") == "2a3b4c" - @test encode(" hsqq qww ") == "2 hs2q q2w2 " -end +@testset verbose = true "tests" begin + @testset "encode strings" begin + @test encode("") == "" + @test encode("XYZ") == "XYZ" + @test encode("AABBBCCCC") == "2A3B4C" + @test encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB") == "12WB12W3B24WB" + @test encode("aabbbcccc") == "2a3b4c" + @test encode(" hsqq qww ") == "2 hs2q q2w2 " + end -@testset "decode strings" begin - @test decode("") == "" - @test decode("XYZ") == "XYZ" - @test decode("2A3B4C") == "AABBBCCCC" - @test decode("12WB12W3B24WB") == "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" - @test decode("2a3b4c") == "aabbbcccc" - @test decode("2 hs2q q2w2 ") == " hsqq qww " -end + @testset "decode strings" begin + @test decode("") == "" + @test decode("XYZ") == "XYZ" + @test decode("2A3B4C") == "AABBBCCCC" + @test decode("12WB12W3B24WB") == "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" + @test decode("2a3b4c") == "aabbbcccc" + @test decode("2 hs2q q2w2 ") == " hsqq qww " + end -@testset "encode then decode" begin - @test decode(encode("zzz ZZ zZ")) == "zzz ZZ zZ" + @testset "encode then decode" begin + @test decode(encode("zzz ZZ zZ")) == "zzz ZZ zZ" + end end diff --git a/exercises/practice/saddle-points/.docs/instructions.md b/exercises/practice/saddle-points/.docs/instructions.md index e2d74676..c585568b 100644 --- a/exercises/practice/saddle-points/.docs/instructions.md +++ b/exercises/practice/saddle-points/.docs/instructions.md @@ -5,14 +5,14 @@ Your task is to find the potential trees where you could build your tree house. The data company provides the data as grids that show the heights of the trees. The rows of the grid represent the east-west direction, and the columns represent the north-south direction. -An acceptable tree will be the the largest in its row, while being the smallest in its column. +An acceptable tree will be the largest in its row, while being the smallest in its column. A grid might not have any good trees at all. Or it might have one, or even several. Here is a grid that has exactly one candidate tree. -``` +```text 1 2 3 4 |----------- 1 | 9 8 7 8 @@ -20,7 +20,7 @@ Here is a grid that has exactly one candidate tree. 3 | 6 6 7 1 ``` -- Row 2 has values 5, 3, and 1. The largest value is 5. +- Row 2 has values 5, 3, 2, and 4. The largest value is 5. - Column 1 has values 9, 5, and 6. The smallest value is 5. So the point at `[2, 1]` (row: 2, column: 1) is a great spot for a tree house. diff --git a/exercises/practice/saddle-points/.docs/introduction.md b/exercises/practice/saddle-points/.docs/introduction.md index b582efbd..34b2c77e 100644 --- a/exercises/practice/saddle-points/.docs/introduction.md +++ b/exercises/practice/saddle-points/.docs/introduction.md @@ -1,9 +1,11 @@ # Introduction -You are planning on building a tree house in the woods near your house so that you can watch the sun rise and set. +You plan to build a tree house in the woods near your house so that you can watch the sun rise and set. -You've obtained data from a local survey company that shows the heights of all the trees in each rectangular section of the map. -You need to analyze each grid on the map to find the perfect tree for your tree house. +You've obtained data from a local survey company that show the height of every tree in each rectangular section of the map. +You need to analyze each grid on the map to find good trees for your tree house. -The best tree will be the tallest tree compared to all the other trees to the east and west, so that you have the best possible view of the sunrises and sunsets. -You don't like climbing too much, so the perfect tree will also be the shortest among all the trees to the north and to the south. +A good tree is both: + +- taller than every tree to the east and west, so that you have the best possible view of the sunrises and sunsets. +- shorter than every tree to the north and south, to minimize the amount of tree climbing. diff --git a/exercises/practice/saddle-points/runtests.jl b/exercises/practice/saddle-points/runtests.jl index f10f88c4..2c143f24 100644 --- a/exercises/practice/saddle-points/runtests.jl +++ b/exercises/practice/saddle-points/runtests.jl @@ -2,7 +2,7 @@ using Test include("saddle-points.jl") -@testset verbose = true "Saddle Points" begin +@testset verbose = true "tests" begin @testset "Can identify single saddle point" begin M = Int[9 8 7; 5 3 2; 6 6 7] @test saddlepoints(M) == NTuple{2,Int}[(2, 1)] diff --git a/exercises/practice/scrabble-score/.docs/instructions.md b/exercises/practice/scrabble-score/.docs/instructions.md index 3f986c94..738f928c 100644 --- a/exercises/practice/scrabble-score/.docs/instructions.md +++ b/exercises/practice/scrabble-score/.docs/instructions.md @@ -1,40 +1,25 @@ # Instructions -Given a word, compute the Scrabble score for that word. +Your task is to compute a word's Scrabble score by summing the values of its letters. -## Letter Values +The letters are valued as follows: -You'll need these: +| Letter | Value | +| ---------------------------- | ----- | +| A, E, I, O, U, L, N, R, S, T | 1 | +| D, G | 2 | +| B, C, M, P | 3 | +| F, H, V, W, Y | 4 | +| K | 5 | +| J, X | 8 | +| Q, Z | 10 | -```text -Letter Value -A, E, I, O, U, L, N, R, S, T 1 -D, G 2 -B, C, M, P 3 -F, H, V, W, Y 4 -K 5 -J, X 8 -Q, Z 10 -``` - -## Examples - -"cabbage" should be scored as worth 14 points: +For example, the word "cabbage" is worth 14 points: - 3 points for C -- 1 point for A, twice -- 3 points for B, twice +- 1 point for A +- 3 points for B +- 3 points for B +- 1 point for A - 2 points for G - 1 point for E - -And to total: - -- `3 + 2*1 + 2*3 + 2 + 1` -- = `3 + 2 + 6 + 3` -- = `5 + 9` -- = 14 - -## Extensions - -- You can play a double or a triple letter. -- You can play a double or a triple word. diff --git a/exercises/practice/scrabble-score/.docs/introduction.md b/exercises/practice/scrabble-score/.docs/introduction.md new file mode 100644 index 00000000..8821f240 --- /dev/null +++ b/exercises/practice/scrabble-score/.docs/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +[Scrabble][wikipedia] is a word game where players place letter tiles on a board to form words. +Each letter has a value. +A word's score is the sum of its letters' values. + +[wikipedia]: https://en.wikipedia.org/wiki/Scrabble diff --git a/exercises/practice/scrabble-score/runtests.jl b/exercises/practice/scrabble-score/runtests.jl index e8bcf175..bc861064 100644 --- a/exercises/practice/scrabble-score/runtests.jl +++ b/exercises/practice/scrabble-score/runtests.jl @@ -2,7 +2,7 @@ using Test include("scrabble-score.jl") -@testset verbose = true "Scrabble Score" begin +@testset verbose = true "tests" begin @testset "lowercase letter" begin @test score("a") == 1 end diff --git a/exercises/practice/secret-handshake/.meta/config.json b/exercises/practice/secret-handshake/.meta/config.json index 7eb73f7f..0f35ab4a 100644 --- a/exercises/practice/secret-handshake/.meta/config.json +++ b/exercises/practice/secret-handshake/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "Bert, in Mary Poppins", - "source_url": "http://www.imdb.com/title/tt0058331/quotes/qt0437047" + "source_url": "https://www.imdb.com/title/tt0058331/quotes/?item=qt0437047" } diff --git a/exercises/practice/secret-handshake/runtests.jl b/exercises/practice/secret-handshake/runtests.jl index 5c64d967..a812ab2e 100644 --- a/exercises/practice/secret-handshake/runtests.jl +++ b/exercises/practice/secret-handshake/runtests.jl @@ -2,7 +2,7 @@ using Test include("secret-handshake.jl") -@testset verbose = true "Secret Handshake" begin +@testset verbose = true "tests" begin @testset "wink for 1" begin @test secret_handshake(1) == ["wink"] end diff --git a/exercises/practice/sieve/.docs/instructions.md b/exercises/practice/sieve/.docs/instructions.md index 7228737a..085c0a57 100644 --- a/exercises/practice/sieve/.docs/instructions.md +++ b/exercises/practice/sieve/.docs/instructions.md @@ -1,30 +1,42 @@ # Instructions -Use the Sieve of Eratosthenes to find all the primes from 2 up to a given -number. - -The Sieve of Eratosthenes is a simple, ancient algorithm for finding all -prime numbers up to any given limit. It does so by iteratively marking as -composite (i.e. not prime) the multiples of each prime, starting with the -multiples of 2. It does not use any division or remainder operation. - -Create your range, starting at two and continuing up to and including the given limit. (i.e. [2, limit]) - -The algorithm consists of repeating the following over and over: - -- take the next available unmarked number in your list (it is prime) -- mark all the multiples of that number (they are not prime) - -Repeat until you have processed each number in your range. - -When the algorithm terminates, all the numbers in the list that have not -been marked are prime. - -The wikipedia article has a useful graphic that explains the algorithm: -https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes - -Notice that this is a very specific algorithm, and the tests don't check -that you've implemented the algorithm, only that you've come up with the -correct list of primes. A good first test is to check that you do not use -division or remainder operations (div, /, mod or % depending on the -language). +Your task is to create a program that implements the Sieve of Eratosthenes algorithm to find all prime numbers less than or equal to a given number. + +A prime number is a number larger than 1 that is only divisible by 1 and itself. +For example, 2, 3, 5, 7, 11, and 13 are prime numbers. +By contrast, 6 is _not_ a prime number as it not only divisible by 1 and itself, but also by 2 and 3. + +To use the Sieve of Eratosthenes, you first create a list of all the numbers between 2 and your given number. +Then you repeat the following steps: + +1. Find the next unmarked number in your list (skipping over marked numbers). + This is a prime number. +2. Mark all the multiples of that prime number as **not** prime. + +You keep repeating these steps until you've gone through every number in your list. +At the end, all the unmarked numbers are prime. + +~~~~exercism/note +The tests don't check that you've implemented the algorithm, only that you've come up with the correct list of primes. +To check you are implementing the Sieve correctly, a good first test is to check that you do not use division or remainder operations. +~~~~ + +## Example + +Let's say you're finding the primes less than or equal to 10. + +- List out 2, 3, 4, 5, 6, 7, 8, 9, 10, leaving them all unmarked. +- 2 is unmarked and is therefore a prime. + Mark 4, 6, 8 and 10 as "not prime". +- 3 is unmarked and is therefore a prime. + Mark 6 and 9 as not prime _(marking 6 is optional - as it's already been marked)_. +- 4 is marked as "not prime", so we skip over it. +- 5 is unmarked and is therefore a prime. + Mark 10 as not prime _(optional - as it's already been marked)_. +- 6 is marked as "not prime", so we skip over it. +- 7 is unmarked and is therefore a prime. +- 8 is marked as "not prime", so we skip over it. +- 9 is marked as "not prime", so we skip over it. +- 10 is marked as "not prime", so we stop as there are no more numbers to check. + +You've examined all numbers and found 2, 3, 5, and 7 are still unmarked, which means they're the primes less than or equal to 10. diff --git a/exercises/practice/sieve/.docs/introduction.md b/exercises/practice/sieve/.docs/introduction.md new file mode 100644 index 00000000..f6c1cf79 --- /dev/null +++ b/exercises/practice/sieve/.docs/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +You bought a big box of random computer parts at a garage sale. +You've started putting the parts together to build custom computers. + +You want to test the performance of different combinations of parts, and decide to create your own benchmarking program to see how your computers compare. +You choose the famous "Sieve of Eratosthenes" algorithm, an ancient algorithm, but one that should push your computers to the limits. diff --git a/exercises/practice/sieve/.meta/config.json b/exercises/practice/sieve/.meta/config.json index 40f81301..ec46c36a 100644 --- a/exercises/practice/sieve/.meta/config.json +++ b/exercises/practice/sieve/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "Sieve of Eratosthenes at Wikipedia", - "source_url": "http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" + "source_url": "https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" } diff --git a/exercises/practice/sieve/runtests.jl b/exercises/practice/sieve/runtests.jl index 23d02030..fbfb9ced 100644 --- a/exercises/practice/sieve/runtests.jl +++ b/exercises/practice/sieve/runtests.jl @@ -2,36 +2,38 @@ using Test include("sieve.jl") -@testset "no primes under two" begin - @test sieve(1) == [] -end +@testset verbose = true "tests" begin + @testset "no primes under two" begin + @test sieve(1) == [] + end -@testset "find first prime" begin - @test sieve(2) == [2] -end + @testset "find first prime" begin + @test sieve(2) == [2] + end -@testset "find primes up to 10" begin - @test sieve(10) == [2, 3, 5, 7] -end + @testset "find primes up to 10" begin + @test sieve(10) == [2, 3, 5, 7] + end -@testset "limit is prime" begin - @test sieve(13) == [2, 3, 5, 7, 11, 13] -end + @testset "limit is prime" begin + @test sieve(13) == [2, 3, 5, 7, 11, 13] + end -@testset "find primes up to 1000" begin - @test sieve(1000) == [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, - 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, - 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, - 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, - 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, - 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, - 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, - 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, - 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, - 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 - ] + @testset "find primes up to 1000" begin + @test sieve(1000) == [ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, + 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, + 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, + 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, + 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, + 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, + 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, + 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, + 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, + 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 + ] + end end diff --git a/exercises/practice/space-age/runtests.jl b/exercises/practice/space-age/runtests.jl index 4fbdc94a..35f6c64a 100644 --- a/exercises/practice/space-age/runtests.jl +++ b/exercises/practice/space-age/runtests.jl @@ -2,7 +2,7 @@ using Test include("space-age.jl") -@testset verbose = true "Space Age" begin +@testset verbose = true "tests" begin @testset "age on Earth" begin result = onEarth(1000000000) expected = 31.60 diff --git a/exercises/practice/spiral-matrix/.docs/instructions.md b/exercises/practice/spiral-matrix/.docs/instructions.md index af412dd8..01e8a77f 100644 --- a/exercises/practice/spiral-matrix/.docs/instructions.md +++ b/exercises/practice/spiral-matrix/.docs/instructions.md @@ -1,12 +1,11 @@ # Instructions -Given the size, return a square matrix of numbers in spiral order. +Your task is to return a square matrix of a given size. -The matrix should be filled with natural numbers, starting from 1 -in the top-left corner, increasing in an inward, clockwise spiral order, -like these examples: +The matrix should be filled with natural numbers, starting from 1 in the top-left corner, increasing in an inward, clockwise spiral order, like these examples: ## Examples + ### Spiral matrix of size 3 ```text diff --git a/exercises/practice/spiral-matrix/.docs/introduction.md b/exercises/practice/spiral-matrix/.docs/introduction.md new file mode 100644 index 00000000..25c7eb59 --- /dev/null +++ b/exercises/practice/spiral-matrix/.docs/introduction.md @@ -0,0 +1,11 @@ +# Introduction + +In a small village near an ancient forest, there was a legend of a hidden treasure buried deep within the woods. +Despite numerous attempts, no one had ever succeeded in finding it. +This was about to change, however, thanks to a young explorer named Elara. +She had discovered an old document containing instructions on how to locate the treasure. +Using these instructions, Elara was able to draw a map that revealed the path to the treasure. + +To her surprise, the path followed a peculiar clockwise spiral. +It was no wonder no one had been able to find the treasure before! +With the map in hand, Elara embarks on her journey to uncover the hidden treasure. diff --git a/exercises/practice/spiral-matrix/.meta/config.json b/exercises/practice/spiral-matrix/.meta/config.json index 82b737cd..c1a84b42 100644 --- a/exercises/practice/spiral-matrix/.meta/config.json +++ b/exercises/practice/spiral-matrix/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": " Given the size, return a square matrix of numbers in spiral order.", + "blurb": "Given the size, return a square matrix of numbers in spiral order.", "authors": [ "CNOT" ], @@ -19,5 +19,5 @@ ] }, "source": "Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension.", - "source_url": "https://www.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/" + "source_url": "https://web.archive.org/web/20230607064729/https://old.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/" } diff --git a/exercises/practice/spiral-matrix/runtests.jl b/exercises/practice/spiral-matrix/runtests.jl index 4472339b..bdb9c069 100644 --- a/exercises/practice/spiral-matrix/runtests.jl +++ b/exercises/practice/spiral-matrix/runtests.jl @@ -2,24 +2,25 @@ using Test include("spiral-matrix.jl") - -@testset "Different valid values" begin - @testset "Empty spiral" begin - @test spiral_matrix(0) == Matrix{Int}(undef,0,0) - end - @testset "Trivial spiral" begin - @test spiral_matrix(1) == reshape([1],(1,1)) - end - @testset "Spiral of size 2" begin - @test spiral_matrix(2) == [1 2; 4 3] - end - @testset "Spiral of size 3" begin - @test spiral_matrix(3) == [1 2 3; 8 9 4; 7 6 5] - end - @testset "Spiral of size 4" begin - @test spiral_matrix(4) == [1 2 3 4; 12 13 14 5; 11 16 15 6; 10 9 8 7] - end - @testset "Spiral of size 5" begin - @test spiral_matrix(5) == [1 2 3 4 5; 16 17 18 19 6; 15 24 25 20 7; 14 23 22 21 8; 13 12 11 10 9] +@testset verbose = true "tests" begin + @testset "Different valid values" begin + @testset "Empty spiral" begin + @test spiral_matrix(0) == Matrix{Int}(undef,0,0) + end + @testset "Trivial spiral" begin + @test spiral_matrix(1) == reshape([1],(1,1)) + end + @testset "Spiral of size 2" begin + @test spiral_matrix(2) == [1 2; 4 3] + end + @testset "Spiral of size 3" begin + @test spiral_matrix(3) == [1 2 3; 8 9 4; 7 6 5] + end + @testset "Spiral of size 4" begin + @test spiral_matrix(4) == [1 2 3 4; 12 13 14 5; 11 16 15 6; 10 9 8 7] + end + @testset "Spiral of size 5" begin + @test spiral_matrix(5) == [1 2 3 4 5; 16 17 18 19 6; 15 24 25 20 7; 14 23 22 21 8; 13 12 11 10 9] + end end end diff --git a/exercises/practice/square-root/.docs/instructions.md b/exercises/practice/square-root/.docs/instructions.md index faaf597b..e9905e9d 100644 --- a/exercises/practice/square-root/.docs/instructions.md +++ b/exercises/practice/square-root/.docs/instructions.md @@ -1,8 +1,13 @@ # Instructions -Find the square roots of positive non-zero integers. +Given a natural radicand, return its square root. -You may want to check out the Wikipedia pages on [square roots][square-root] and [methods of computing square roots][computing-square-roots]. +Note that the term "radicand" refers to the number for which the root is to be determined. +That is, it is the number under the root symbol. + +Check out the Wikipedia pages on [square root][square-root] and [methods of computing square roots][computing-square-roots]. + +Recall also that natural numbers are positive real whole numbers (i.e. 1, 2, 3 and up). [square-root]: https://en.wikipedia.org/wiki/Square_root -[computing-square-roots]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots \ No newline at end of file +[computing-square-roots]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots diff --git a/exercises/practice/square-root/.meta/config.json b/exercises/practice/square-root/.meta/config.json index e5e37046..66e3ce23 100644 --- a/exercises/practice/square-root/.meta/config.json +++ b/exercises/practice/square-root/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Calculate a positive integer's square root", + "blurb": "Given a natural radicand, return its square root.", "authors": [ "golanor" ], diff --git a/exercises/practice/square-root/runtests.jl b/exercises/practice/square-root/runtests.jl index 6738a82b..ff618938 100644 --- a/exercises/practice/square-root/runtests.jl +++ b/exercises/practice/square-root/runtests.jl @@ -2,35 +2,36 @@ using Test, Random include("square-root.jl") - -@testset "Different valid values" begin - @testset "Square root of 1 is 1" begin - @test square_root(1) == 1.0 - end - @testset "Square root of 4 is 2" begin - @test square_root(4) == 2.0 - end - @testset "Square root of 25 is 5" begin - @test square_root(25) == 5.0 - end - @testset "Square root of 81 is 9" begin - @test square_root(81) == 9.0 +@testset verbose = true "tests" begin + @testset "Different valid values" begin + @testset "Square root of 1 is 1" begin + @test square_root(1) == 1.0 + end + @testset "Square root of 4 is 2" begin + @test square_root(4) == 2.0 + end + @testset "Square root of 25 is 5" begin + @test square_root(25) == 5.0 + end + @testset "Square root of 81 is 9" begin + @test square_root(81) == 9.0 + end + @testset "Square root of 196 is 14" begin + @test square_root(196) == 14.0 + end + @testset "Square root of 65025 is 255" begin + @test square_root(65025) == 255.0 + end + @testset "Domain error for negative number" begin + @test_throws DomainError square_root(-65536) + end end - @testset "Square root of 196 is 14" begin - @test square_root(196) == 14.0 - end - @testset "Square root of 65025 is 255" begin - @test square_root(65025) == 255.0 - end - @testset "Domain error for negative number" begin - @test_throws DomainError square_root(-65536) - end -end -@testset "Random tests" begin - for _ in 1:1000 - s = rand(1:isqrt(typemax(Int64))) - @test square_root(s^2) == s + @testset "Random tests" begin + for _ in 1:1000 + s = rand(1:isqrt(typemax(Int64))) + @test square_root(s^2) == s + end end end diff --git a/exercises/practice/sum-of-multiples/runtests.jl b/exercises/practice/sum-of-multiples/runtests.jl index 9db03e30..b288b334 100644 --- a/exercises/practice/sum-of-multiples/runtests.jl +++ b/exercises/practice/sum-of-multiples/runtests.jl @@ -1,66 +1,69 @@ -include("sum-of-multiples.jl") using Test -@testset "no multiples within limit" begin - @test sum_of_multiples(1, [3, 5]) == 0 -end +include("sum-of-multiples.jl") -@testset "test one factor has multiples within limit" begin - @test sum_of_multiples(4, [3, 5]) == 3 -end +@testset verbose = true "tests" begin + @testset "no multiples within limit" begin + @test sum_of_multiples(1, [3, 5]) == 0 + end -@testset "more than one multiple within limit" begin - @test sum_of_multiples(7, [3]) == 9 -end + @testset "test one factor has multiples within limit" begin + @test sum_of_multiples(4, [3, 5]) == 3 + end -@testset "more than one factor with multiples within limit" begin - @test sum_of_multiples(10, [3, 5]) == 23 -end + @testset "more than one multiple within limit" begin + @test sum_of_multiples(7, [3]) == 9 + end -@testset "each multiple is only counted once" begin - @test sum_of_multiples(100, [3, 5]) == 2318 -end + @testset "more than one factor with multiples within limit" begin + @test sum_of_multiples(10, [3, 5]) == 23 + end -@testset "a much larger limit" begin - @test sum_of_multiples(1000, [3, 5]) == 233168 -end + @testset "each multiple is only counted once" begin + @test sum_of_multiples(100, [3, 5]) == 2318 + end -@testset "three factors" begin - @test sum_of_multiples(20, [7, 13, 17]) == 51 -end + @testset "a much larger limit" begin + @test sum_of_multiples(1000, [3, 5]) == 233168 + end -@testset "factors not relatively prime" begin - @test sum_of_multiples(15, [4, 6]) == 30 -end + @testset "three factors" begin + @test sum_of_multiples(20, [7, 13, 17]) == 51 + end -@testset "some pairs of factors relatively prime and some not" begin - @test sum_of_multiples(150, [5, 6, 8]) == 4419 -end + @testset "factors not relatively prime" begin + @test sum_of_multiples(15, [4, 6]) == 30 + end -@testset "one factor is a multiple of another" begin - @test sum_of_multiples(51, [5, 25]) == 275 -end + @testset "some pairs of factors relatively prime and some not" begin + @test sum_of_multiples(150, [5, 6, 8]) == 4419 + end -@testset "test much larger factors" begin - @test sum_of_multiples(10000, [43, 47]) == 2203160 -end + @testset "one factor is a multiple of another" begin + @test sum_of_multiples(51, [5, 25]) == 275 + end -@testset "all numbers are multiples of 1" begin - @test sum_of_multiples(100, [1]) == 4950 -end + @testset "test much larger factors" begin + @test sum_of_multiples(10000, [43, 47]) == 2203160 + end -@testset "no factors means an empty sum" begin - @test sum_of_multiples(10000, Int[]) == 0 -end + @testset "all numbers are multiples of 1" begin + @test sum_of_multiples(100, [1]) == 4950 + end -@testset "the only multiple of 0 is 0" begin - @test sum_of_multiples(1, [0]) == 0 -end + @testset "no factors means an empty sum" begin + @test sum_of_multiples(10000, Int[]) == 0 + end -@testset "the factor 0 does not affect the sum_of_multiples of other factors" begin - @test sum_of_multiples(4, [3, 0]) == 3 -end + @testset "the only multiple of 0 is 0" begin + @test sum_of_multiples(1, [0]) == 0 + end + + @testset "the factor 0 does not affect the sum_of_multiples of other factors" begin + @test sum_of_multiples(4, [3, 0]) == 3 + end -@testset "solutions using include exclude must extend to cardinality greater than 3" begin - @test sum_of_multiples(10000, [2, 3, 5, 7, 11]) == 39614537 + @testset "solutions using include exclude must extend to cardinality greater than 3" begin + @test sum_of_multiples(10000, [2, 3, 5, 7, 11]) == 39614537 + end end diff --git a/exercises/practice/transpose/runtests.jl b/exercises/practice/transpose/runtests.jl index bc290a77..211f2e2b 100644 --- a/exercises/practice/transpose/runtests.jl +++ b/exercises/practice/transpose/runtests.jl @@ -2,238 +2,240 @@ using Test include("transpose.jl") -@testset "empty string" begin - @test transpose_strings([]) == [] -end - -@testset "two characters in a row" begin - @test transpose_strings(["A1"]) == ["A", "1"] -end +@testset verbose = true "tests" begin + @testset "empty string" begin + @test transpose_strings([]) == [] + end -@testset "two characters in a column" begin - @test transpose_strings(["A", "1"]) == ["A1"] -end + @testset "two characters in a row" begin + @test transpose_strings(["A1"]) == ["A", "1"] + end -@testset "simple" begin - @test transpose_strings(["ABC", "123"]) == [ - "A1", - "B2", - "C3" - ] -end + @testset "two characters in a column" begin + @test transpose_strings(["A", "1"]) == ["A1"] + end -@testset "single line" begin - @test transpose_strings(["Single line."]) == [ - "S", - "i", - "n", - "g", - "l", - "e", - " ", - "l", - "i", - "n", - "e", - "." - ] -end + @testset "simple" begin + @test transpose_strings(["ABC", "123"]) == [ + "A1", + "B2", + "C3" + ] + end -@testset "first line longer than second line" begin - @test transpose_strings([ - "The fourth line.", - "The fifth line." - ]) == [ - "TT", - "hh", - "ee", - " ", - "ff", - "oi", - "uf", - "rt", - "th", - "h ", - " l", - "li", - "in", - "ne", - "e.", - "." - ] -end + @testset "single line" begin + @test transpose_strings(["Single line."]) == [ + "S", + "i", + "n", + "g", + "l", + "e", + " ", + "l", + "i", + "n", + "e", + "." + ] + end -@testset "second line longer than first line" begin - @test transpose_strings([ - "The first line.", - "The second line." - ]) == [ - "TT", - "hh", - "ee", - " ", - "fs", - "ie", - "rc", - "so", - "tn", - " d", - "l ", - "il", - "ni", - "en", - ".e", - " ." - ] -end + @testset "first line longer than second line" begin + @test transpose_strings([ + "The fourth line.", + "The fifth line." + ]) == [ + "TT", + "hh", + "ee", + " ", + "ff", + "oi", + "uf", + "rt", + "th", + "h ", + " l", + "li", + "in", + "ne", + "e.", + "." + ] + end -@testset "mixed line length" begin - @test transpose_strings([ - "The longest line.", - "A long line.", - "A longer line.", - "A line." - ]) == [ - "TAAA", - "h ", - "elll", - " ooi", - "lnnn", - "ogge", - "n e.", - "glr", - "ei ", - "snl", - "tei", - " .n", - "l e", - "i .", - "n", - "e", - "." - ] -end + @testset "second line longer than first line" begin + @test transpose_strings([ + "The first line.", + "The second line." + ]) == [ + "TT", + "hh", + "ee", + " ", + "fs", + "ie", + "rc", + "so", + "tn", + " d", + "l ", + "il", + "ni", + "en", + ".e", + " ." + ] + end -@testset "square" begin - @test transpose_strings([ - "HEART", - "EMBER", - "ABUSE", - "RESIN", - "TREND" + @testset "mixed line length" begin + @test transpose_strings([ + "The longest line.", + "A long line.", + "A longer line.", + "A line." ]) == [ - "HEART", - "EMBER", - "ABUSE", - "RESIN", - "TREND" + "TAAA", + "h ", + "elll", + " ooi", + "lnnn", + "ogge", + "n e.", + "glr", + "ei ", + "snl", + "tei", + " .n", + "l e", + "i .", + "n", + "e", + "." ] -end + end -@testset "rectangle" begin - @test transpose_strings([ - "FRACTURE", - "OUTLINED", - "BLOOMING", - "SEPTETTE" - ]) == [ - "FOBS", - "RULE", - "ATOP", - "CLOT", - "TIME", - "UNIT", - "RENT", - "EDGE" - ] -end + @testset "square" begin + @test transpose_strings([ + "HEART", + "EMBER", + "ABUSE", + "RESIN", + "TREND" + ]) == [ + "HEART", + "EMBER", + "ABUSE", + "RESIN", + "TREND" + ] + end -@testset "triangle" begin - @test transpose_strings([ - "T", - "EE", - "AAA", - "SSSS", - "EEEEE", - "RRRRRR" - ]) == [ - "TEASER", - " EASER", - " ASER", - " SER", - " ER", - " R" - ] -end + @testset "rectangle" begin + @test transpose_strings([ + "FRACTURE", + "OUTLINED", + "BLOOMING", + "SEPTETTE" + ]) == [ + "FOBS", + "RULE", + "ATOP", + "CLOT", + "TIME", + "UNIT", + "RENT", + "EDGE" + ] + end -@testset "many lines" begin - @test transpose_strings([ - "Chor. Two households, both alike in dignity,", - "In fair Verona, where we lay our scene,", - "From ancient grudge break to new mutiny,", - "Where civil blood makes civil hands unclean.", - "From forth the fatal loins of these two foes", - "A pair of star-cross'd lovers take their life;", - "Whose misadventur'd piteous overthrows", - "Doth with their death bury their parents' strife.", - "The fearful passage of their death-mark'd love,", - "And the continuance of their parents' rage,", - "Which, but their children's end, naught could remove,", - "Is now the two hours' traffic of our stage;", - "The which if you with patient ears attend,", - "What here shall miss, our toil shall strive to mend." - ]) == [ - "CIFWFAWDTAWITW", - "hnrhr hohnhshh", - "o oeopotedi ea", - "rfmrmash cn t", - ".a e ie fthow ", - " ia fr weh,whh", - "Trnco miae ie", - "w ciroitr btcr", - "oVivtfshfcuhhe", - " eeih a uote ", - "hrnl sdtln is", - "oot ttvh tttfh", - "un bhaeepihw a", - "saglernianeoyl", - "e,ro -trsui ol", - "h uofcu sarhu ", - "owddarrdan o m", - "lhg to'egccuwi", - "deemasdaeehris", - "sr als t ists", - ",ebk 'phool'h,", - " reldi ffd ", - "bweso tb rtpo", - "oea ileutterau", - "t kcnoorhhnatr", - "hl isvuyee'fi ", - " atv es iisfet", - "ayoior trr ino", - "l lfsoh ecti", - "ion vedpn l", - "kuehtteieadoe ", - "erwaharrar,fas", - " nekt te rh", - "ismdsehphnnosa", - "ncuse ra-tau l", - " et tormsural", - "dniuthwea'g t ", - "iennwesnr hsts", - "g,ycoi tkrttet", - "n ,l r s'a anr", - "i ef 'dgcgdi", - "t aol eoe,v", - "y nei sl,u; e", - ", .sf to l ", - " e rv d t", - " ; ie o", - " f, r ", - " e e m", - " . m e", - " o n", - " v d", - " e .", - " ,"] + @testset "triangle" begin + @test transpose_strings([ + "T", + "EE", + "AAA", + "SSSS", + "EEEEE", + "RRRRRR" + ]) == [ + "TEASER", + " EASER", + " ASER", + " SER", + " ER", + " R" + ] + end + + @testset "many lines" begin + @test transpose_strings([ + "Chor. Two households, both alike in dignity,", + "In fair Verona, where we lay our scene,", + "From ancient grudge break to new mutiny,", + "Where civil blood makes civil hands unclean.", + "From forth the fatal loins of these two foes", + "A pair of star-cross'd lovers take their life;", + "Whose misadventur'd piteous overthrows", + "Doth with their death bury their parents' strife.", + "The fearful passage of their death-mark'd love,", + "And the continuance of their parents' rage,", + "Which, but their children's end, naught could remove,", + "Is now the two hours' traffic of our stage;", + "The which if you with patient ears attend,", + "What here shall miss, our toil shall strive to mend." + ]) == [ + "CIFWFAWDTAWITW", + "hnrhr hohnhshh", + "o oeopotedi ea", + "rfmrmash cn t", + ".a e ie fthow ", + " ia fr weh,whh", + "Trnco miae ie", + "w ciroitr btcr", + "oVivtfshfcuhhe", + " eeih a uote ", + "hrnl sdtln is", + "oot ttvh tttfh", + "un bhaeepihw a", + "saglernianeoyl", + "e,ro -trsui ol", + "h uofcu sarhu ", + "owddarrdan o m", + "lhg to'egccuwi", + "deemasdaeehris", + "sr als t ists", + ",ebk 'phool'h,", + " reldi ffd ", + "bweso tb rtpo", + "oea ileutterau", + "t kcnoorhhnatr", + "hl isvuyee'fi ", + " atv es iisfet", + "ayoior trr ino", + "l lfsoh ecti", + "ion vedpn l", + "kuehtteieadoe ", + "erwaharrar,fas", + " nekt te rh", + "ismdsehphnnosa", + "ncuse ra-tau l", + " et tormsural", + "dniuthwea'g t ", + "iennwesnr hsts", + "g,ycoi tkrttet", + "n ,l r s'a anr", + "i ef 'dgcgdi", + "t aol eoe,v", + "y nei sl,u; e", + ", .sf to l ", + " e rv d t", + " ; ie o", + " f, r ", + " e e m", + " . m e", + " o n", + " v d", + " e .", + " ,"] + end end diff --git a/exercises/practice/triangle/.docs/instructions.md b/exercises/practice/triangle/.docs/instructions.md index 0a9c68e3..ac390087 100644 --- a/exercises/practice/triangle/.docs/instructions.md +++ b/exercises/practice/triangle/.docs/instructions.md @@ -4,20 +4,26 @@ Determine if a triangle is equilateral, isosceles, or scalene. An _equilateral_ triangle has all three sides the same length. -An _isosceles_ triangle has at least two sides the same length. (It is sometimes -specified as having exactly two sides the same length, but for the purposes of -this exercise we'll say at least two.) +An _isosceles_ triangle has at least two sides the same length. +(It is sometimes specified as having exactly two sides the same length, but for the purposes of this exercise we'll say at least two.) A _scalene_ triangle has all sides of different lengths. ## Note -For a shape to be a triangle at all, all sides have to be of length > 0, and -the sum of the lengths of any two sides must be greater than or equal to the -length of the third side. See [Triangle Inequality](https://en.wikipedia.org/wiki/Triangle_inequality). +For a shape to be a triangle at all, all sides have to be of length > 0, and the sum of the lengths of any two sides must be greater than or equal to the length of the third side. -## Dig Deeper +In equations: -The case where the sum of the lengths of two sides _equals_ that of the -third is known as a _degenerate_ triangle - it has zero area and looks like -a single line. Feel free to add your own code/tests to check for degenerate triangles. +Let `a`, `b`, and `c` be sides of the triangle. +Then all three of the following expressions must be true: + +```text +a + b ≥ c +b + c ≥ a +a + c ≥ b +``` + +See [Triangle Inequality][triangle-inequality] + +[triangle-inequality]: https://en.wikipedia.org/wiki/Triangle_inequality diff --git a/exercises/practice/triangle/.meta/config.json b/exercises/practice/triangle/.meta/config.json index 73efc525..67f9b788 100644 --- a/exercises/practice/triangle/.meta/config.json +++ b/exercises/practice/triangle/.meta/config.json @@ -18,5 +18,5 @@ ] }, "source": "The Ruby Koans triangle project, parts 1 & 2", - "source_url": "http://rubykoans.com" + "source_url": "https://web.archive.org/web/20220831105330/http://rubykoans.com" } diff --git a/exercises/practice/triangle/runtests.jl b/exercises/practice/triangle/runtests.jl index 835eedbf..6759a027 100644 --- a/exercises/practice/triangle/runtests.jl +++ b/exercises/practice/triangle/runtests.jl @@ -2,63 +2,65 @@ using Test include("triangle.jl") -@testset "check equilateral triangles" begin - @testset "true if all sides are equal" begin - @test is_equilateral([2, 2, 2]) - @test is_equilateral([0.5, 0.5, 0.5]) - end +@testset verbose = true "tests" begin + @testset "check equilateral triangles" begin + @testset "true if all sides are equal" begin + @test is_equilateral([2, 2, 2]) + @test is_equilateral([0.5, 0.5, 0.5]) + end - @testset "false if any side is unequal" begin - @test !is_equilateral([2, 3, 2]) - end + @testset "false if any side is unequal" begin + @test !is_equilateral([2, 3, 2]) + end - @testset "false if no sides are equal" begin - @test !is_equilateral([5, 4, 6]) - end + @testset "false if no sides are equal" begin + @test !is_equilateral([5, 4, 6]) + end - @testset "false if invalid triangle" begin - @test !is_equilateral([0, 0, 0]) + @testset "false if invalid triangle" begin + @test !is_equilateral([0, 0, 0]) + end end -end -@testset "check isosceles triangles" begin - @testset "true if at least 2 sides are equal" begin - @test is_isosceles([3, 4, 4]) - @test is_isosceles([4, 3, 4]) - @test is_isosceles([4, 4, 3]) - @test is_isosceles([4, 4, 4]) - @test is_isosceles([0.4, 0.5, 0.5]) - @test is_isosceles([0.5, 0.4, 0.5]) - @test is_isosceles([0.5, 0.5, 0.4]) - end + @testset "check isosceles triangles" begin + @testset "true if at least 2 sides are equal" begin + @test is_isosceles([3, 4, 4]) + @test is_isosceles([4, 3, 4]) + @test is_isosceles([4, 4, 3]) + @test is_isosceles([4, 4, 4]) + @test is_isosceles([0.4, 0.5, 0.5]) + @test is_isosceles([0.5, 0.4, 0.5]) + @test is_isosceles([0.5, 0.5, 0.4]) + end - @testset "false if no sides are equal" begin - @test !is_isosceles([2, 3, 4]) - end + @testset "false if no sides are equal" begin + @test !is_isosceles([2, 3, 4]) + end - @testset "false if invalid triangle" begin - @test !is_isosceles([1, 1, 3]) + @testset "false if invalid triangle" begin + @test !is_isosceles([1, 1, 3]) + end end -end -@testset "check scalene triangles" begin - @testset "true if no sides are equal" begin - @test is_scalene([5, 4, 6]) == true - @test is_scalene([0.5, 0.4, 0.6]) == true - end + @testset "check scalene triangles" begin + @testset "true if no sides are equal" begin + @test is_scalene([5, 4, 6]) == true + @test is_scalene([0.5, 0.4, 0.6]) == true + end - @testset "false if at least 2 sides are equal" begin - @test !is_scalene([3, 4, 4]) - @test !is_scalene([4, 3, 4]) - @test !is_scalene([4, 4, 3]) - @test !is_scalene([4, 4, 4]) - @test !is_scalene([0.4, 0.5, 0.5]) - @test !is_scalene([0.5, 0.4, 0.5]) - @test !is_scalene([0.5, 0.5, 0.4]) - end + @testset "false if at least 2 sides are equal" begin + @test !is_scalene([3, 4, 4]) + @test !is_scalene([4, 3, 4]) + @test !is_scalene([4, 4, 3]) + @test !is_scalene([4, 4, 4]) + @test !is_scalene([0.4, 0.5, 0.5]) + @test !is_scalene([0.5, 0.4, 0.5]) + @test !is_scalene([0.5, 0.5, 0.4]) + end - @testset "false if invalid triangle" begin - @test !is_scalene([7, 3, 2]) + @testset "false if invalid triangle" begin + @test !is_scalene([7, 3, 2]) + end end end diff --git a/exercises/practice/trinary/.docs/instructions.md b/exercises/practice/trinary/.docs/instructions.md index 3638ddb7..d38e3b5b 100644 --- a/exercises/practice/trinary/.docs/instructions.md +++ b/exercises/practice/trinary/.docs/instructions.md @@ -1,15 +1,13 @@ # Instructions -Convert a trinary number, represented as a string (e.g. '102012'), to its -decimal equivalent using first principles. +Convert a trinary number, represented as a string (e.g. '102012'), to its decimal equivalent using first principles. -The program should consider strings specifying an invalid trinary as the -value 0. +The program should consider strings specifying an invalid trinary as the value 0. Trinary numbers contain three symbols: 0, 1, and 2. -The last place in a trinary number is the 1's place. The second to last -is the 3's place, the third to last is the 9's place, etc. +The last place in a trinary number is the 1's place. +The second to last is the 3's place, the third to last is the 9's place, etc. ```shell # "102012" @@ -18,5 +16,4 @@ is the 3's place, the third to last is the 9's place, etc. 243 + 0 + 54 + 0 + 3 + 2 = 302 ``` -If your language provides a method in the standard library to perform the -conversion, pretend it doesn't exist and implement it yourself. +If your language provides a method in the standard library to perform the conversion, pretend it doesn't exist and implement it yourself. diff --git a/exercises/practice/trinary/.meta/config.json b/exercises/practice/trinary/.meta/config.json index 8b05fe2a..0c5b66cd 100644 --- a/exercises/practice/trinary/.meta/config.json +++ b/exercises/practice/trinary/.meta/config.json @@ -19,5 +19,5 @@ ] }, "source": "All of Computer Science", - "source_url": "http://www.wolframalpha.com/input/?i=binary&a=*C.binary-_*MathWorld-" + "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" } diff --git a/exercises/practice/trinary/runtests.jl b/exercises/practice/trinary/runtests.jl index 93f7bdc5..7a99b1f4 100644 --- a/exercises/practice/trinary/runtests.jl +++ b/exercises/practice/trinary/runtests.jl @@ -2,46 +2,48 @@ using Test include("trinary.jl") -@testset "trinary 1 is decimal 1" begin - @test trinary_to_decimal("1") == 1 -end - -@testset "trinary 2 is decimal 2" begin - @test trinary_to_decimal("2") == 2 -end - -@testset "trinary 10 is decimal 3" begin - @test trinary_to_decimal("10") == 3 -end - -@testset "trinary 11 is decimal 4" begin - @test trinary_to_decimal("11") == 4 -end - -@testset "trinary 100 is decimal 9" begin - @test trinary_to_decimal("100") == 9 -end - -@testset "trinary 112 is decimal 14" begin - @test trinary_to_decimal("112") == 14 -end - -@testset "trinary 222 is decimal 26" begin - @test trinary_to_decimal("222") == 26 -end - -@testset "trinary 1122000120 is decimal 32091" begin - @test trinary_to_decimal("1122000120") == 32091 -end - -@testset "invalid trinary digits returns 0" begin - @test trinary_to_decimal("1234") == 0 -end - -@testset "invalid word as input returns 0" begin - @test trinary_to_decimal("carrot") == 0 -end - -@testset "invalid numbers with letters as input returns 0" begin - @test trinary_to_decimal("0a1b2c") == 0 +@testset verbose = true "tests" begin + @testset "trinary 1 is decimal 1" begin + @test trinary_to_decimal("1") == 1 + end + + @testset "trinary 2 is decimal 2" begin + @test trinary_to_decimal("2") == 2 + end + + @testset "trinary 10 is decimal 3" begin + @test trinary_to_decimal("10") == 3 + end + + @testset "trinary 11 is decimal 4" begin + @test trinary_to_decimal("11") == 4 + end + + @testset "trinary 100 is decimal 9" begin + @test trinary_to_decimal("100") == 9 + end + + @testset "trinary 112 is decimal 14" begin + @test trinary_to_decimal("112") == 14 + end + + @testset "trinary 222 is decimal 26" begin + @test trinary_to_decimal("222") == 26 + end + + @testset "trinary 1122000120 is decimal 32091" begin + @test trinary_to_decimal("1122000120") == 32091 + end + + @testset "invalid trinary digits returns 0" begin + @test trinary_to_decimal("1234") == 0 + end + + @testset "invalid word as input returns 0" begin + @test trinary_to_decimal("carrot") == 0 + end + + @testset "invalid numbers with letters as input returns 0" begin + @test trinary_to_decimal("0a1b2c") == 0 + end end diff --git a/exercises/practice/two-fer/.docs/instructions.md b/exercises/practice/two-fer/.docs/instructions.md new file mode 100644 index 00000000..adc53487 --- /dev/null +++ b/exercises/practice/two-fer/.docs/instructions.md @@ -0,0 +1,24 @@ +# Instructions + +Your task is to determine what you will say as you give away the extra cookie. + +If you know the person's name (e.g. if they're named Do-yun), then you will say: + +```text +One for Do-yun, one for me. +``` + +If you don't know the person's name, you will say _you_ instead. + +```text +One for you, one for me. +``` + +Here are some examples: + +| Name | Dialogue | +| :----- | :-------------------------- | +| Alice | One for Alice, one for me. | +| Bohdan | One for Bohdan, one for me. | +| | One for you, one for me. | +| Zaphod | One for Zaphod, one for me. | diff --git a/exercises/practice/two-fer/.docs/introduction.md b/exercises/practice/two-fer/.docs/introduction.md new file mode 100644 index 00000000..5947a223 --- /dev/null +++ b/exercises/practice/two-fer/.docs/introduction.md @@ -0,0 +1,8 @@ +# Introduction + +In some English accents, when you say "two for" quickly, it sounds like "two fer". +Two-for-one is a way of saying that if you buy one, you also get one for free. +So the phrase "two-fer" often implies a two-for-one offer. + +Imagine a bakery that has a holiday offer where you can buy two cookies for the price of one ("two-fer one!"). +You take the offer and (very generously) decide to give the extra cookie to someone else in the queue. diff --git a/exercises/practice/two-fer/.meta/config.json b/exercises/practice/two-fer/.meta/config.json new file mode 100644 index 00000000..e696d460 --- /dev/null +++ b/exercises/practice/two-fer/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "two-fer.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Create a sentence of the form \"One for X, one for me.\".", + "source_url": "https://github.com/exercism/problem-specifications/issues/757" +} diff --git a/exercises/practice/two-fer/.meta/example.jl b/exercises/practice/two-fer/.meta/example.jl new file mode 100644 index 00000000..2f8b4aea --- /dev/null +++ b/exercises/practice/two-fer/.meta/example.jl @@ -0,0 +1,3 @@ +function twofer(name="you") + "One for $name, one for me." +end diff --git a/exercises/practice/two-fer/.meta/tests.toml b/exercises/practice/two-fer/.meta/tests.toml new file mode 100644 index 00000000..d0e38573 --- /dev/null +++ b/exercises/practice/two-fer/.meta/tests.toml @@ -0,0 +1,19 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[1cf3e15a-a3d7-4a87-aeb3-ba1b43bc8dce] +description = "no name given" + +[b4c6dbb8-b4fb-42c2-bafd-10785abe7709] +description = "a name given" + +[3549048d-1a6e-4653-9a79-b0bda163e8d5] +description = "another name given" diff --git a/exercises/practice/two-fer/runtests.jl b/exercises/practice/two-fer/runtests.jl new file mode 100644 index 00000000..acc4827b --- /dev/null +++ b/exercises/practice/two-fer/runtests.jl @@ -0,0 +1,17 @@ +using Test + +include("two-fer.jl") + +@testset verbose = true "tests" begin + @testset "no name given" begin + @test twofer() == "One for you, one for me." + end + + @testset "a name given" begin + @test twofer("Alice") == "One for Alice, one for me." + end + + @testset "another name given" begin + @test twofer("Bob") == "One for Bob, one for me." + end +end diff --git a/exercises/practice/two-fer/two-fer.jl b/exercises/practice/two-fer/two-fer.jl new file mode 100644 index 00000000..5711b529 --- /dev/null +++ b/exercises/practice/two-fer/two-fer.jl @@ -0,0 +1,3 @@ +function twofer(name) + +end diff --git a/exercises/practice/word-count/runtests.jl b/exercises/practice/word-count/runtests.jl index 5f10a99a..9b117f10 100644 --- a/exercises/practice/word-count/runtests.jl +++ b/exercises/practice/word-count/runtests.jl @@ -2,59 +2,61 @@ using Test include("word-count.jl") -@testset "no words" begin - @test wordcount(" .\n,\t!^&*()~@#\$%{}[]:;'/<>") == Dict() -end - -@testset "count one word" begin - @test wordcount("word") == Dict("word" => 1) -end - -@testset "count one of each word" begin - @test wordcount("one of each") == Dict("one" => 1, "of" => 1, "each" => 1) -end - -@testset "multiple occurrences of a word" begin - @test wordcount("one fish two fish red fish blue fish") == Dict("one" => 1, "fish" => 4, "two" => 1, "red" => 1, "blue" => 1) -end - -@testset "handles cramped lists" begin - @test wordcount("one,two,three") == Dict("one" => 1, "two" => 1, "three" => 1) -end - -@testset "handles expanded lists" begin - @test wordcount("one,\ntwo,\nthree") == Dict("one" => 1, "two" => 1, "three" => 1) -end - -@testset "ignore punctuation" begin - @test wordcount("car: carpet as java: javascript!!&@\$%^&") == Dict("car" => 1, "carpet" => 1, "as" => 1, "java" => 1, "javascript" => 1) -end - -@testset "include numbers" begin - @test wordcount("testing, 1, 2 testing") == Dict("testing" => 2, "1" => 1, "2" => 1) -end - -@testset "normalize case" begin - @test wordcount("go Go GO Stop stop") == Dict("go" => 3, "stop" => 2) -end - -@testset "with apostrophes" begin - @test wordcount("First: don't laugh. Then: don't cry.") == Dict("first" => 1, "don't" => 2, "laugh" => 1, "then" => 1, "cry" => 1) - @test wordcount("Should've could've would've") == Dict("should've" => 1, "could've" => 1, "would've" => 1) -end - -@testset "with quotations" begin - @test wordcount("Joe can't tell between 'large' and large.") == Dict("joe" => 1, "can't" => 1, "tell" => 1, "between" => 1, "large" => 2, "and" => 1) -end - -@testset "substrings from the beginning" begin - @test wordcount("Joe can't tell between app, apple and a.") == Dict("joe" => 1, "can't" => 1, "tell" => 1, "between" => 1, "app" => 1, "apple" => 1, "and" => 1, "a" => 1) -end - -@testset "multiple spaces not detected as a word" begin - @test wordcount(" multiple whitespaces") == Dict("multiple" => 1, "whitespaces" => 1) -end - -@testset "alternating word separators not detected as a word" begin - @test wordcount(",\n,one,\n ,two \n 'three'") == Dict("one" => 1, "two" => 1, "three" => 1) +@testset verbose = true "tests" begin + @testset "no words" begin + @test wordcount(" .\n,\t!^&*()~@#\$%{}[]:;'/<>") == Dict() + end + + @testset "count one word" begin + @test wordcount("word") == Dict("word" => 1) + end + + @testset "count one of each word" begin + @test wordcount("one of each") == Dict("one" => 1, "of" => 1, "each" => 1) + end + + @testset "multiple occurrences of a word" begin + @test wordcount("one fish two fish red fish blue fish") == Dict("one" => 1, "fish" => 4, "two" => 1, "red" => 1, "blue" => 1) + end + + @testset "handles cramped lists" begin + @test wordcount("one,two,three") == Dict("one" => 1, "two" => 1, "three" => 1) + end + + @testset "handles expanded lists" begin + @test wordcount("one,\ntwo,\nthree") == Dict("one" => 1, "two" => 1, "three" => 1) + end + + @testset "ignore punctuation" begin + @test wordcount("car: carpet as java: javascript!!&@\$%^&") == Dict("car" => 1, "carpet" => 1, "as" => 1, "java" => 1, "javascript" => 1) + end + + @testset "include numbers" begin + @test wordcount("testing, 1, 2 testing") == Dict("testing" => 2, "1" => 1, "2" => 1) + end + + @testset "normalize case" begin + @test wordcount("go Go GO Stop stop") == Dict("go" => 3, "stop" => 2) + end + + @testset "with apostrophes" begin + @test wordcount("First: don't laugh. Then: don't cry.") == Dict("first" => 1, "don't" => 2, "laugh" => 1, "then" => 1, "cry" => 1) + @test wordcount("Should've could've would've") == Dict("should've" => 1, "could've" => 1, "would've" => 1) + end + + @testset "with quotations" begin + @test wordcount("Joe can't tell between 'large' and large.") == Dict("joe" => 1, "can't" => 1, "tell" => 1, "between" => 1, "large" => 2, "and" => 1) + end + + @testset "substrings from the beginning" begin + @test wordcount("Joe can't tell between app, apple and a.") == Dict("joe" => 1, "can't" => 1, "tell" => 1, "between" => 1, "app" => 1, "apple" => 1, "and" => 1, "a" => 1) + end + + @testset "multiple spaces not detected as a word" begin + @test wordcount(" multiple whitespaces") == Dict("multiple" => 1, "whitespaces" => 1) + end + + @testset "alternating word separators not detected as a word" begin + @test wordcount(",\n,one,\n ,two \n 'three'") == Dict("one" => 1, "two" => 1, "three" => 1) + end end