diff --git a/exercises/practice/binary-search-tree/.meta/Example.cs b/exercises/practice/binary-search-tree/.meta/Example.cs index a77fc35bf5..eab267ea5a 100644 --- a/exercises/practice/binary-search-tree/.meta/Example.cs +++ b/exercises/practice/binary-search-tree/.meta/Example.cs @@ -1,79 +1,113 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Linq; +using Newtonsoft.Json; -public class BinarySearchTree : IEnumerable +public class BinarySearchTree where T : IComparable { - public BinarySearchTree(int value) + class Node { - Value = value; - } - - public BinarySearchTree(IEnumerable values) - { - var array = values.ToArray(); + public T Value { get; set; } + public Node Left { get; set; } + public Node Right { get; set; } - if (array.Length == 0) + public static object ToData(Node node) { - throw new ArgumentException("Cannot create tree from empty list"); + if (node == null) return null; + + return new + { + data = node.Value, + left = Node.ToData(node.Left), + right = Node.ToData(node.Right) + }; } - Value = array[0]; - - foreach (var value in array.Skip(1)) + public IEnumerable GetOrderedValues() { - Add(value); + if (Left != null) + { + foreach(var value in Left.GetOrderedValues()) + { + yield return value; + } + } + yield return Value; + if (Right != null) + { + foreach(var value in Right.GetOrderedValues()) + { + yield return value; + } + } } } - public int Value { get; } + Node head; - public BinarySearchTree Left { get; private set; } + public int Count { get; private set; } - public BinarySearchTree Right { get; private set; } - - public BinarySearchTree Add(int value) + public void Add(T value) { - if (value <= Value) - { - Left = Add(value, Left); + Count++; + + if (head == null) { + head = new Node { Value = value }; + return; } - else + + var node = head; + + while(true) { - Right = Add(value, Right); + if (node.Value.CompareTo(value) >= 0) + { + if (node.Left == null) + { + node.Left = new Node { Value = value }; + break; + } + node = node.Left; + } else { + if (node.Right == null) + { + node.Right = new Node { Value = value }; + break; + } + node = node.Right; + } } - - return this; } - private static BinarySearchTree Add(int value, BinarySearchTree tree) + public bool Contains(T value) { - if (tree == null) + var node = head; + while(node != null) { - return new BinarySearchTree(value); - } + if (node.Value.CompareTo(value) == 0) { return true; } - return tree.Add(value); + if (node.Value.CompareTo(value) < 0) { node = node.Left; } + else { node = node.Right; } + } + return false; } - public IEnumerator GetEnumerator() + public string ToJson() { - foreach (var left in Left?.AsEnumerable() ?? Enumerable.Empty()) + if (head == null) return null; + + var settings = new JsonSerializerSettings { - yield return left; - } + Formatting = Formatting.Indented, + }; - yield return Value; + var data = Node.ToData(head); - foreach (var right in Right?.AsEnumerable() ?? Enumerable.Empty()) - { - yield return right; - } + return JsonConvert.SerializeObject(data, settings); } - IEnumerator IEnumerable.GetEnumerator() + public IEnumerable GetOrderedValues() { - return GetEnumerator(); + if (head == null) return new T[0]; + return head.GetOrderedValues(); } } \ No newline at end of file diff --git a/exercises/practice/binary-search-tree/.meta/config.json b/exercises/practice/binary-search-tree/.meta/config.json index 5415236961..a20ab16c41 100644 --- a/exercises/practice/binary-search-tree/.meta/config.json +++ b/exercises/practice/binary-search-tree/.meta/config.json @@ -7,7 +7,8 @@ "j2jensen", "robkeim", "ShamilS", - "wolf99" + "wolf99", + "michalporeba" ], "files": { "solution": [ diff --git a/exercises/practice/binary-search-tree/BinarySearchTree.cs b/exercises/practice/binary-search-tree/BinarySearchTree.cs index 02c277c40a..074f506e25 100644 --- a/exercises/practice/binary-search-tree/BinarySearchTree.cs +++ b/exercises/practice/binary-search-tree/BinarySearchTree.cs @@ -1,53 +1,21 @@ using System; -using System.Collections; using System.Collections.Generic; +using Newtonsoft.Json; -public class BinarySearchTree : IEnumerable +public class BinarySearchTree where T : IComparable { - public BinarySearchTree(int value) - { - } + public int Count + => throw new NotImplementedException("Please implement the Count property of the BinarySearchTree class."); - public BinarySearchTree(IEnumerable values) - { - } + public void Add(T value) + => throw new NotImplementedException("Please implement the Add(T) method of the BinarySearchTree class."); - public int Value - { - get - { - throw new NotImplementedException("You need to implement this function."); - } - } + public bool Contains(T value) + => throw new NotImplementedException("Please implement the Contains(T) method of the BinarySearchTree class."); - public BinarySearchTree Left - { - get - { - throw new NotImplementedException("You need to implement this function."); - } - } + public string ToJson() + => throw new NotImplementedException("Please implement the ToJson() method of the BinarySearchTree class."); - public BinarySearchTree Right - { - get - { - throw new NotImplementedException("You need to implement this function."); - } - } - - public BinarySearchTree Add(int value) - { - throw new NotImplementedException("You need to implement this function."); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException("You need to implement this function."); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException("You need to implement this function."); - } + public IEnumerable GetOrderedValues() + => throw new NotImplementedException("Please implement the GetOrderedValues() method of the BinarySearchTree class."); } \ No newline at end of file diff --git a/exercises/practice/binary-search-tree/BinarySearchTreeTests.cs b/exercises/practice/binary-search-tree/BinarySearchTreeTests.cs index 4725c2a5c1..7c7768c5fd 100644 --- a/exercises/practice/binary-search-tree/BinarySearchTreeTests.cs +++ b/exercises/practice/binary-search-tree/BinarySearchTreeTests.cs @@ -1,84 +1,199 @@ -using System.Linq; using Xunit; +using System.Text.RegularExpressions; public class BinarySearchTreeTests { [Fact] - public void Data_is_retained() + public void New_bst_is_empty() { - var tree = new BinarySearchTree(4); - Assert.Equal(4, tree.Value); + var sut = new BinarySearchTree(); + Assert.Equal(0, sut.Count); } [Fact(Skip = "Remove this Skip property to run this test")] - public void Smaller_number_at_left_node() + public void New_bst_can_be_serialized_to_json() { - var tree = new BinarySearchTree(new[] { 4, 2 }); - Assert.Equal(4, tree.Value); - Assert.Equal(2, tree.Left.Value); + var sut = new BinarySearchTree(); + Assert.Null(sut.ToJson()); } [Fact(Skip = "Remove this Skip property to run this test")] - public void Same_number_at_left_node() + public void Single_value_can_be_found() { - var tree = new BinarySearchTree(new[] { 4, 4 }); - Assert.Equal(4, tree.Value); - Assert.Equal(4, tree.Left.Value); + var sut = new BinarySearchTree(); + sut.Add(4); + Assert.False(sut.Contains(1)); + Assert.True(sut.Contains(4)); } [Fact(Skip = "Remove this Skip property to run this test")] - public void Greater_number_at_right_node() + public void Single_value_can_be_serialized() { - var tree = new BinarySearchTree(new[] { 4, 5 }); - Assert.Equal(4, tree.Value); - Assert.Equal(5, tree.Right.Value); + var sut = new BinarySearchTree(); + sut.Add(4); + var expected = """ + { + "data": 4, + "left": null, + "right": null + } + """; + Assert.Equal(WithoutSpaces(expected), WithoutSpaces(sut.ToJson())); } [Fact(Skip = "Remove this Skip property to run this test")] - public void Can_create_complex_tree() + public void Insert_data_at_proper_node_42() { - var tree = new BinarySearchTree(new[] { 4, 2, 6, 1, 3, 5, 7 }); - Assert.Equal(4, tree.Value); - Assert.Equal(2, tree.Left.Value); - Assert.Equal(1, tree.Left.Left.Value); - Assert.Equal(3, tree.Left.Right.Value); - Assert.Equal(6, tree.Right.Value); - Assert.Equal(5, tree.Right.Left.Value); - Assert.Equal(7, tree.Right.Right.Value); + var sut = new BinarySearchTree(); + sut.Add(4); + sut.Add(2); + var expected = """ + { + "data": 4, + "left": { + "data": 2, + "left": null, + "right": null + }, + "right": null + } + """; + Assert.Equal(WithoutSpaces(expected), WithoutSpaces(sut.ToJson())); } [Fact(Skip = "Remove this Skip property to run this test")] - public void Can_sort_single_number() + public void Insert_data_at_proper_node_44() { - var tree = new BinarySearchTree(2); - Assert.Equal(new[] { 2 }, tree.AsEnumerable()); + var sut = new BinarySearchTree(); + sut.Add(4); + sut.Add(4); + var expected = """ + { + "data": 4, + "left": { + "data": 4, + "left": null, + "right": null + }, + "right": null + } + """; + Assert.Equal(WithoutSpaces(expected), WithoutSpaces(sut.ToJson())); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Insert_data_at_proper_node_45() + { + var sut = new BinarySearchTree(); + sut.Add(4); + sut.Add(5); + var expected = """ + { + "data": 4, + "left": null, + "right": { + "data": 5, + "left": null, + "right": null + } + } + """; + Assert.Equal(WithoutSpaces(expected), WithoutSpaces(sut.ToJson())); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Insert_data_at_proper_node_4261357() + { + var sut = new BinarySearchTree(); + sut.Add(4); + sut.Add(2); + sut.Add(6); + sut.Add(1); + sut.Add(3); + sut.Add(5); + sut.Add(7); + var expected = """ + { + "data": 4, + "left": { + "data": 2, + "left": { + "data": 1, + "left": null, + "right": null + }, + "right": { + "data": 3, + "left": null, + "right": null + } + }, + "right": { + "data": 6, + "left": { + "data": 5, + "left": null, + "right": null + }, + "right": { + "data": 7, + "left": null, + "right": null + } + } + } + """; + Assert.Equal(WithoutSpaces(expected), WithoutSpaces(sut.ToJson())); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Can_sort_a_single_number() + { + var sut = new BinarySearchTree(); + sut.Add(2); + Assert.Equal(new int[] {2}, sut.GetOrderedValues()); } [Fact(Skip = "Remove this Skip property to run this test")] public void Can_sort_if_second_number_is_smaller_than_first() { - var tree = new BinarySearchTree(new[] { 2, 1 }); - Assert.Equal(new[] { 1, 2 }, tree.AsEnumerable()); + var sut = new BinarySearchTree(); + sut.Add(2); + sut.Add(1); + Assert.Equal(new int[] {1, 2}, sut.GetOrderedValues()); } [Fact(Skip = "Remove this Skip property to run this test")] public void Can_sort_if_second_number_is_same_as_first() { - var tree = new BinarySearchTree(new[] { 2, 2 }); - Assert.Equal(new[] { 2, 2 }, tree.AsEnumerable()); + var sut = new BinarySearchTree(); + sut.Add(2); + sut.Add(2); + Assert.Equal(new int[] {2, 2}, sut.GetOrderedValues()); } [Fact(Skip = "Remove this Skip property to run this test")] public void Can_sort_if_second_number_is_greater_than_first() { - var tree = new BinarySearchTree(new[] { 2, 3 }); - Assert.Equal(new[] { 2, 3 }, tree.AsEnumerable()); + var sut = new BinarySearchTree(); + sut.Add(2); + sut.Add(3); + Assert.Equal(new int[] {2, 3}, sut.GetOrderedValues()); } [Fact(Skip = "Remove this Skip property to run this test")] public void Can_sort_complex_tree() { - var tree = new BinarySearchTree(new[] { 2, 1, 3, 6, 7, 5 }); - Assert.Equal(new[] { 1, 2, 3, 5, 6, 7 }, tree.AsEnumerable()); + var sut = new BinarySearchTree(); + sut.Add(2); + sut.Add(1); + sut.Add(3); + sut.Add(6); + sut.Add(7); + sut.Add(5); + Assert.Equal(new int[] {1, 2, 3, 5, 6, 7}, sut.GetOrderedValues()); } + + private static string WithoutSpaces(string text) + => Regex.Replace(text, @"\s+", ""); } \ No newline at end of file