module Task6 open System type BinaryTree = | Empty | Node of string * BinaryTree * BinaryTree let empty = Empty let rec insert value tree = match tree with | Empty -> Node(value, Empty, Empty) | Node(v, left, right) -> if value < v then Node(v, insert value left, right) elif value > v then Node(v, left, insert value right) else tree let rec contains value tree = match tree with | Empty -> false | Node(v, left, right) -> if value = v then true elif value < v then contains value left else contains value right let rec findMin tree = match tree with | Empty -> None | Node(v, Empty, _) -> Some v | Node(_, left, _) -> findMin left let rec findMax tree = match tree with | Empty -> None | Node(v, _, Empty) -> Some v | Node(_, _, right) -> findMax right let rec remove value tree = match tree with | Empty -> Empty | Node(v, left, right) -> if value < v then Node(v, remove value left, right) elif value > v then Node(v, left, remove value right) else match left, right with | Empty, Empty -> Empty | Empty, right -> right | left, Empty -> left | left, right -> match findMin right with | Some minValue -> Node(minValue, left, remove minValue right) | None -> left let rec inOrder tree = match tree with | Empty -> [] | Node(v, left, right) -> (inOrder left) @ [v] @ (inOrder right) let rec preOrder tree = match tree with | Empty -> [] | Node(v, left, right) -> [v] @ (preOrder left) @ (preOrder right) let rec postOrder tree = match tree with | Empty -> [] | Node(v, left, right) -> (postOrder left) @ (postOrder right) @ [v] let rec height tree = match tree with | Empty -> 0 | Node(_, left, right) -> 1 + max (height left) (height right) let rec size tree = match tree with | Empty -> 0 | Node(_, left, right) -> 1 + (size left) + (size right) let rec map f tree = match tree with | Empty -> Empty | Node(v, left, right) -> Node(f v, map f left, map f right) let rec fold f acc tree = match tree with | Empty -> acc | Node(v, left, right) -> let leftAcc = fold f acc left let nodeAcc = f leftAcc v fold f nodeAcc right let rec filter predicate tree = match tree with | Empty -> Empty | Node(v, left, right) -> let filteredLeft = filter predicate left let filteredRight = filter predicate right if predicate v then Node(v, filteredLeft, filteredRight) else let leftList = inOrder filteredLeft let rightList = inOrder filteredRight let combinedList = leftList @ rightList List.fold (fun acc x -> insert x acc) Empty combinedList let fromList lst = List.fold (fun acc x -> insert x acc) Empty lst let toList tree = inOrder tree [] let main argv = let tree1 = empty |> insert "dog" |> insert "cat" |> insert "elephant" |> insert "bird" |> insert "fish" printfn "Tree contents (in-order): %A" (inOrder tree1) printfn "Tree contents (pre-order): %A" (preOrder tree1) printfn "Tree contents (post-order): %A" (postOrder tree1) printfn "Contains 'cat': %b" (contains "cat" tree1) printfn "Contains 'zebra': %b" (contains "zebra" tree1) printfn "Min value: %A" (findMin tree1) printfn "Max value: %A" (findMax tree1) printfn "Tree height: %d" (height tree1) printfn "Tree size: %d" (size tree1) let tree2 = remove "cat" tree1 printfn "After removing 'cat': %A" (inOrder tree2) let upperTree = map (fun s -> s.ToUpper()) tree1 printfn "Uppercase tree: %A" (inOrder upperTree) let longWords = filter (fun s -> s.Length > 3) tree1 printfn "Words longer than 3 chars: %A" (inOrder longWords) let wordCount = fold (fun acc _ -> acc + 1) 0 tree1 printfn "Word count using fold: %d" wordCount let listTree = fromList ["apple"; "banana"; "cherry"; "date"] printfn "Tree from list: %A" (toList listTree) 0