From 34ba97c9d013d637bd07a5770285a19666f7cd66 Mon Sep 17 00:00:00 2001 From: Andrej Makarov Date: Thu, 26 Jan 2017 09:21:08 +0000 Subject: [PATCH] Add exercise: anagram (#17) * Add exercise: anagram * Anagram exercise: use AbstractString as suggested * Fix exercise anagram template file: use AbstractString --- config.json | 13 ++++++- exercises/anagram/anagram.jl | 4 +++ exercises/anagram/example.jl | 43 ++++++++++++++++++++++ exercises/anagram/runtests.jl | 68 +++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 exercises/anagram/anagram.jl create mode 100644 exercises/anagram/example.jl create mode 100644 exercises/anagram/runtests.jl diff --git a/config.json b/config.json index 737779d7a31ca..3f16ab1e7bfaf 100644 --- a/config.json +++ b/config.json @@ -5,7 +5,7 @@ "active": false, "test_pattern": "TODO", "exercises": [ - { + { "slug": "leap", "difficulty": 1, "topics": [ @@ -13,6 +13,17 @@ "integers", "mathematics" ] + }, + { + "slug": "anagram", + "difficulty": 2, + "topics": [ + "control-flow (loops)", + "arrays", + "strings", + "sorting", + "filtering" + ] } ], "deprecated": [ diff --git a/exercises/anagram/anagram.jl b/exercises/anagram/anagram.jl new file mode 100644 index 0000000000000..237379ba9c6b7 --- /dev/null +++ b/exercises/anagram/anagram.jl @@ -0,0 +1,4 @@ +function detect_anagrams(subject::AbstractString, candidates::AbstractArray) + +end + diff --git a/exercises/anagram/example.jl b/exercises/anagram/example.jl new file mode 100644 index 0000000000000..a81f52ca19361 --- /dev/null +++ b/exercises/anagram/example.jl @@ -0,0 +1,43 @@ +# Anagrams are two or more words that composed of the same characters but in a different order + +function is_anagram(s1::AbstractString, s2::AbstractString) + # Disable case sensitivity + s1 = lowercase(s1) + s2 = lowercase(s2) + + # Similar and different-length strings are not anagrams + if length(s1) != length(s2) || s1 == s2 + return false + end + + # Calculate count of every character in the first string + chr_count = Dict() + for c in s1 + chr_count[c] = get(chr_count, c, 0) + 1 + end + + # Reduce the count by every character from the second string + for c in s2 + t = get(chr_count, c, 0) - 1 + if t < 0 + # Got character that not exist in the first string + return false + else + chr_count[c] = t + end + end + + # Check all counts to be zeroes + return all(i->(i==0), values(chr_count)) +end + +function detect_anagrams(subject::AbstractString, candidates::AbstractArray) + result = [] + for candidate = candidates + if is_anagram(subject, candidate) + push!(result, candidate) + end + end + result +end + diff --git a/exercises/anagram/runtests.jl b/exercises/anagram/runtests.jl new file mode 100644 index 0000000000000..d71b867cab3cc --- /dev/null +++ b/exercises/anagram/runtests.jl @@ -0,0 +1,68 @@ +using Base.Test + +include("anagram.jl") + +@testset "no matches" begin + @test detect_anagrams("diasper", ["hello", "world", "zombies", "pants"]) == [] +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"]) == [] +end + +@testset "detects multiple 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"]) == [] +end + +@testset "detects anagram" begin + @test detect_anagrams("listen", ["enlists", "google", "inlets", "banana"]) == ["inlets"] +end + +@testset "detects multiple anagrams" begin + @test detect_anagrams("allergy", ["gallery", "ballerina", "regally", "clergy", "largely", "leading"]) == ["gallery", "regally", "largely"] +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"]) == [] +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 a word as its own anagram" begin + @test detect_anagrams("banana", ["Banana"]) == [] +end + +@testset "does not detect a anagram if the original word is repeated" begin + @test detect_anagrams("go", ["go Go GO"]) == [] +end + +@testset "anagrams must use all letters exactly once" begin + @test detect_anagrams("tapper", ["patter"]) == [] +end + +@testset "capital word is not own anagram" begin + @test detect_anagrams("BANANA", ["Banana"]) == [] +end +