forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request JuliaLang#30 from SaschaMann/smann/ex-custom-set
Add exercise: custom set
- Loading branch information
Showing
5 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
The tests require a constructor that takes an array. The internals of your custom set implementation can use other data structures but you may have to implement an outer constructor that takes exactly one array for the tests to pass. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import Base: AbstractSet, isempty, length, in, issubset, start, next, done, | ||
push!, ==, copy, intersect!, intersect, union!, union | ||
|
||
type CustomSet{T} <: AbstractSet | ||
elements::Array{T, 1} | ||
end | ||
|
||
isempty(s::CustomSet) = isempty(s.elements) | ||
length(s::CustomSet) = length(s.elements) | ||
in(element, s::CustomSet) = in(element, s.elements) # this also defines issubset(::CustomSet, ::CustomSet) | ||
==(s1::CustomSet, s2::CustomSet) = issubset(s1, s2) && issubset(s2, s1) | ||
copy(s::CustomSet) = CustomSet(copy(s.elements)) | ||
push!(s::CustomSet, element) = push!(s.elements, element) | ||
|
||
# Iterator protocol | ||
start(::CustomSet) = 1 | ||
next(s::CustomSet, state) = s.elements[state], state + 1 | ||
done(s::CustomSet, state) = state > length(s) | ||
|
||
function disjoint(s1::CustomSet, s2::CustomSet) | ||
for element in s1 | ||
element in s2 && return false | ||
end | ||
return true | ||
end | ||
|
||
function complement!(s1::CustomSet, s2::CustomSet) | ||
for (i, element) in enumerate(s1) | ||
element in s2 && deleteat!(s1.elements, i) | ||
end | ||
return s1 | ||
end | ||
complement(s1::CustomSet, s2::CustomSet) = complement!(copy(s1), s2) | ||
|
||
function intersect!(s1::CustomSet, s2::CustomSet) | ||
tbd = Int[] | ||
for (i, element) in enumerate(s1) | ||
element in s2 || push!(tbd, i) | ||
end | ||
deleteat!(s1.elements, tbd) | ||
return s1 | ||
end | ||
intersect(s1::CustomSet, s2::CustomSet) = intersect!(copy(s1), s2) | ||
|
||
function union!(s1::CustomSet, s2::CustomSet) | ||
for element in s2 | ||
element in s1 || push!(s1, element) | ||
end | ||
return s1 | ||
end | ||
union(s1::CustomSet, s2::CustomSet) = union!(copy(s1), s2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
using Base.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 # TODO ⊆, ⊈ | ||
@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 "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]) | ||
end | ||
|
||
@testset "add" begin | ||
@test begin | ||
custom_set = CustomSet([]) | ||
push!(custom_set, 3) | ||
custom_set == CustomSet([3]) | ||
end | ||
@test begin | ||
custom_set = CustomSet([1, 2, 4]) | ||
push!(custom_set, 3) | ||
custom_set == CustomSet([1, 2, 3, 4]) | ||
end | ||
@test begin | ||
custom_set = CustomSet([1, 2, 3]) | ||
push!(custom_set, 3) | ||
custom_set == CustomSet([1, 2, 3]) | ||
end | ||
end | ||
|
||
@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 | ||
@testset "not in-place" begin # TODO use operator ∩ | ||
@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) | ||
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 | ||
@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) | ||
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 | ||
@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 | ||
|
||
@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) | ||
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]) | ||
end | ||
end |