diff --git a/exercises/practice/binary-search-tree/.docs/instructions.md b/exercises/practice/binary-search-tree/.docs/instructions.md new file mode 100644 index 00000000..c9bbba5b --- /dev/null +++ b/exercises/practice/binary-search-tree/.docs/instructions.md @@ -0,0 +1,47 @@ +# Instructions + +Insert and search for numbers in a binary tree. + +When we need to represent sorted data, an array does not make a good data structure. + +Say we have the array `[1, 3, 4, 5]`, and we add 2 to it so it becomes `[1, 3, 4, 5, 2]`. +Now we must sort the entire array again! +We can improve on this by realizing that we only need to make space for the new item `[1, nil, 3, 4, 5]`, and then adding the item in the space we added. +But this still requires us to shift many elements down by one. + +Binary Search Trees, however, can operate on sorted data much more efficiently. + +A binary search tree consists of a series of connected nodes. +Each node contains a piece of data (e.g. the number 3), a variable named `left`, and a variable named `right`. +The `left` and `right` variables point at `nil`, or other nodes. +Since these other nodes in turn have other nodes beneath them, we say that the left and right variables are pointing at subtrees. +All data in the left subtree is less than or equal to the current node's data, and all data in the right subtree is greater than the current node's data. + +For example, if we had a node containing the data 4, and we added the data 2, our tree would look like this: + + 4 + / + 2 + +If we then added 6, it would look like this: + + 4 + / \ + 2 6 + +If we then added 3, it would look like this + + 4 + / \ + 2 6 + \ + 3 + +And if we then added 1, 5, and 7, it would look like this + + 4 + / \ + / \ + 2 6 + / \ / \ + 1 3 5 7 diff --git a/exercises/practice/binary-search-tree/.meta/config.json b/exercises/practice/binary-search-tree/.meta/config.json new file mode 100644 index 00000000..d38e32cc --- /dev/null +++ b/exercises/practice/binary-search-tree/.meta/config.json @@ -0,0 +1,16 @@ +{ + "authors": [], + "files": { + "solution": [ + "binary-search-tree.jl" + ], + "test": [ + "runtests.jl" + ], + "example": [ + ".meta/example.jl" + ] + }, + "blurb": "Insert and search for numbers in a binary tree.", + "source": "Josh Cheek" +} diff --git a/exercises/practice/binary-search-tree/.meta/example.jl b/exercises/practice/binary-search-tree/.meta/example.jl new file mode 100644 index 00000000..936f2024 --- /dev/null +++ b/exercises/practice/binary-search-tree/.meta/example.jl @@ -0,0 +1,38 @@ +mutable struct BinarySearchTree + data + left + right + BinarySearchTree(node::T) where T<:Real = new(node, nothing, nothing) +end + +function BinarySearchTree(vec::Vector{T}) where T<:Real + tree = BinarySearchTree(popfirst!(vec)) + foreach(node -> push!(tree, node), vec) + tree +end + +function Base.in(node, tree::BinarySearchTree) + tree.data == node && return true + if node ≤ tree.data + isnothing(tree.left) ? false : in(node, tree.left) + else + isnothing(tree.right) ? false : in(node, tree.right) + end +end + +function Base.push!(tree::BinarySearchTree, node) + if node ≤ tree.data + isnothing(tree.left) ? (tree.left = BinarySearchTree(node)) : push!(tree.left, node) + else + isnothing(tree.right) ? (tree.right = BinarySearchTree(node)) : push!(tree.right, node) + end + tree +end + +function traverse(tree::BinarySearchTree, channel::Channel) + !isnothing(tree.left) && traverse(tree.left, channel) + put!(channel, tree.data) + !isnothing(tree.right) && traverse(tree.right, channel) +end + +Base.sort(tree::BinarySearchTree) = collect(Channel(channel -> traverse(tree, channel))) diff --git a/exercises/practice/binary-search-tree/.meta/tests.toml b/exercises/practice/binary-search-tree/.meta/tests.toml new file mode 100644 index 00000000..c7d32021 --- /dev/null +++ b/exercises/practice/binary-search-tree/.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. + +[e9c93a78-c536-4750-a336-94583d23fafa] +description = "data is retained" + +[7a95c9e8-69f6-476a-b0c4-4170cb3f7c91] +description = "insert data at proper node -> smaller number at left node" + +[22b89499-9805-4703-a159-1a6e434c1585] +description = "insert data at proper node -> same number at left node" + +[2e85fdde-77b1-41ed-b6ac-26ce6b663e34] +description = "insert data at proper node -> greater number at right node" + +[dd898658-40ab-41d0-965e-7f145bf66e0b] +description = "can create complex tree" + +[9e0c06ef-aeca-4202-b8e4-97f1ed057d56] +description = "can sort data -> can sort single number" + +[425e6d07-fceb-4681-a4f4-e46920e380bb] +description = "can sort data -> can sort if second number is smaller than first" + +[bd7532cc-6988-4259-bac8-1d50140079ab] +description = "can sort data -> can sort if second number is same as first" + +[b6d1b3a5-9d79-44fd-9013-c83ca92ddd36] +description = "can sort data -> can sort if second number is greater than first" + +[d00ec9bd-1288-4171-b968-d44d0808c1c8] +description = "can sort data -> can sort complex tree" diff --git a/exercises/practice/binary-search-tree/binary-search-tree.jl b/exercises/practice/binary-search-tree/binary-search-tree.jl new file mode 100644 index 00000000..f95b91b8 --- /dev/null +++ b/exercises/practice/binary-search-tree/binary-search-tree.jl @@ -0,0 +1,2 @@ +# Create a (Mutable) Struct BinarySearchTree, which has fields: data, left, right +# Also write a sort method, which returns a sorted array of the elements in a BinarySearchTree \ No newline at end of file diff --git a/exercises/practice/binary-search-tree/runtests.jl b/exercises/practice/binary-search-tree/runtests.jl new file mode 100644 index 00000000..b60fd3a7 --- /dev/null +++ b/exercises/practice/binary-search-tree/runtests.jl @@ -0,0 +1,85 @@ +using Test +include("binary-search-tree.jl") + +@testset "data is retained" begin + tree = BinarySearchTree([4]) + @test tree.data == 4 + @test isnothing(tree.left) + @test isnothing(tree.right) +end + +@testset "insert data at proper node" begin + @testset "smaller number at left node" begin + tree = BinarySearchTree([4, 2]) + @test tree.data == 4 + @test tree.left.data == 2 + @test isnothing(tree.left.left) + @test isnothing(tree.left.right) + @test isnothing(tree.right) + end + + @testset "same number at left node" begin + tree = BinarySearchTree([4, 4]) + @test tree.data == 4 + @test tree.left.data == 4 + @test isnothing(tree.left.left) + @test isnothing(tree.left.right) + @test isnothing(tree.right) + end + + @testset "greater number at right node" begin + tree = BinarySearchTree([4, 5]) + @test tree.data == 4 + @test isnothing(tree.left) + @test tree.right.data == 5 + @test isnothing(tree.right.left) + @test isnothing(tree.right.right) + end +end + +@testset "can create complex tree" begin + tree = BinarySearchTree([4, 2, 6, 1, 3, 5, 7]) + @test tree.data == 4 + @test tree.left.data == 2 + @test tree.left.left.data == 1 + @test isnothing(tree.left.left.left) + @test isnothing(tree.left.left.right) + @test tree.left.right.data == 3 + @test isnothing(tree.left.right.left) + @test isnothing(tree.left.right.right) + @test tree.right.data == 6 + @test tree.right.left.data == 5 + @test isnothing(tree.right.left.left) + @test isnothing(tree.right.left.right) + @test tree.right.right.data == 7 + @test isnothing(tree.right.right.left) + @test isnothing(tree.right.right.right) + +end + +@testset "can sort data" begin + @testset "can sort single number" begin + tree = BinarySearchTree([2]) + @test sort(tree) == [2] + end + + @testset "can sort if second number is smaller than first" begin + tree = BinarySearchTree([2, 1]) + @test sort(tree) == [1, 2] + end + + @testset "can sort if second number is same as first" begin + tree = BinarySearchTree([2, 2]) + @test sort(tree) == [2, 2] + end + + @testset "can sort if second number is greater than first" begin + tree = BinarySearchTree([2, 3]) + @test sort(tree) == [2, 3] + end + + @testset "can sort complex tree" begin + tree = BinarySearchTree([4, 2, 6, 1, 3, 5, 7]) + @test sort(tree) == [1, 2, 3, 4, 5, 6, 7] + end +end