Print Binary Search Tree in a tree like structure in Haskell - haskell

I created a binary search tree and tried to print the binary search tree with this instance
data Tree a = Nil | Node (Tree a) a (Tree a)
instance Show a => Show (Tree a) where
show t = intercalate "\n" (map snd (draw t))
draw :: Show a => Tree a -> [(Int,String)]
draw Nil = [(1,"*")]
draw (Node Nil x Nil) = [(1,show x)]
draw (Node tl x tr) = zip (repeat 0) (map shiftl (draw tl)) ++ [(1,show x ++ "-+")] ++ zip (repeat 2) (map shiftr (draw tr)) where
shiftl (0,x) = spaces ++ " " ++ x
shiftl (1,x) = spaces ++ "+-" ++ x
shiftl (2,x) = spaces ++ "| " ++ x
shiftr (0,x) = spaces ++ "| " ++ x
shiftr (1,x) = spaces ++ "+-" ++ x
shiftr (2,x) = spaces ++ " " ++ x
spaces = replicate (length (show x)+1) ' '
createTree :: [a] -> BTree a
createTree [] = Nil
createTree xs = Node
(createTree front) x (createTree back) where
n = length xs
(front, x:back) = splitAt (n `div` 2) xs
Now I want to print it horizontally, which i am not able to do so. I want to print the binary search tree like this picture below. (Sorry for the low quality of the picture but you get the idea). How can i do it ?
Use the sample example [1..50]
UPDATE ANSWER :-
I found my answer myself. I created one function that shows like that. The code is in the comments.
If you have an other solution please share

Here's my solution. It's might not be perfect. It prints Nil nodes as a *.
The basic idea is to first get the visualizations of the left and right trees as two lists of strings. Then they are zipped using concatenation to produce a list of strings representing the two trees side-by-side.
instance Show a => Show (Tree a) where
show tree =
let (s, _) = show' tree
in intercalate "\n" s
where
show' :: Show a => Tree a -> ([String], Int)
show' Nil = (["*"], 0)
show' (Node ltree value rtree) = (ashow, acenter)
where
-- middle_padding_length = 1
-- middle_padding = replicate (2*middle_padding_length+1) ' '
middle_padding = " "
pwidth = length middle_padding
lshow, rshow :: [String]
lcenter, rcenter :: Int
(lshow, lcenter) = show' ltree
(rshow, rcenter) = show' rtree
lwidth, rwidth :: Int
lwidth = length (head lshow)
rwidth = length (head rshow)
awidth, acenter :: Int
awidth = lwidth + length middle_padding + rwidth
acenter = lwidth + pwidth `div` 2
-- Put subtrees side by side with some padding
sshow :: [String]
sshow =
zipWith (\s1 s2 -> s1 ++ middle_padding ++ s2)
(extend_depth lwidth lshow)
(extend_depth rwidth rshow)
where
extend_depth twidth tshow =
let
sdepth = max (length lshow) (length rshow)
in
tshow ++ replicate (sdepth - length tshow) (replicate twidth ' ')
vshow :: String
vshow =
let
text = show value
textWidth = length text
whitespaceWidth = awidth - textWidth
leftPadding = acenter - textWidth `div` 2
rightPadding = whitespaceWidth - leftPadding
in
replicate leftPadding ' ' ++ text ++ replicate rightPadding ' '
row :: [Char] -> String
row [lc, mc, rc, hc, sc] =
replicate lcenter sc ++ [lc] ++ replicate (acenter-lcenter-1) hc ++
[mc] ++
replicate (lwidth+pwidth+rcenter-acenter-1) hc ++ [rc] ++ replicate (awidth-lwidth-pwidth-rcenter-1) sc
row _ = error "incorrect number of characters"
two_pipes, splitter, one_pipe :: String
two_pipes = row "| | "
splitter = row "/^\\- "
one_pipe = row " | "
ashow :: [String]
ashow =
vshow :
one_pipe :
splitter :
two_pipes :
sshow
Output for createTree [0..10]:

I found my answer myself. I created one function that shows like that. Here is the code
import Data.List (intercalate)
data BTree a = Nil | Node (BTree a) a (BTree a) deriving Eq
-- Instances of BST
instance Show a => Show (BTree a) where
show t = "\n" ++ intercalate "\n" (map (map snd) (fst $ draw5 t)) ++ "\n"
-- End of instances
data Tag = L | M | R deriving (Eq,Show)
type Entry = (Tag, Char)
type Line = [Entry]
--the tag thing is for my own understanding that do no work here.
createTree :: [a] -> BTree a
createTree [] = Nil
createTree xs = Node
(createTree front) x (createTree back) where
n = length xs
(front, x:back) = splitAt (n `div` 2) xs
-- my own draw
draw5 :: Show a => BTree a -> ([Line],(Int,Int,Int))
draw5 Nil = ([zip [M] "*"],(0,1,0) )
draw5 (Node Nil x Nil) =
let (sx,n,m) = (show x, length sx, n `div` 2) in
([zip (replicate m L ++ [M] ++ replicate (n-m-1) R) sx], (m,1,n-m-1))
draw5 (Node tl x tr) = (l1:l2:l3:l4:mainline,(a,b,c)) where
(mainline ,(a,b,c)) = drawing xs ys
(xs,(xsa,xsb,xsc)) = draw5 tl
(ys,(ysa,ysb,ysc)) = draw5 tr
drawing xs ys = (join xs ys, (xsa+xsb+xsc+1, 1, ysa+ysb+ysc+1) )
join (as:ass) (bs:bss) = go as bs : join ass bss
join xss [] = map (++ ([(L,' '),(M, ' '),(R,' ')] ++ replicate (ysa+ysb+ysc) (R,' ') )) xss
join [] yss = map ((replicate (xsa+xsb+xsc) (L,' ') ++ [(L,' '),(M, ' '),(R,' ')]) ++ ) yss
go xss yss = xss ++ [(L,' '),(M, ' '),(R,' ')] ++ yss
([cs],(m,n,o)) = draw5 (Node Nil x Nil)
l1 = replicate (a-m) (L,' ') ++ cs ++ replicate (c-o) (R,' ')
l2 = replicate a (L,' ') ++ [(M, '|')] ++ replicate c (R,' ')
l3 = replicate xsa (L,' ') ++ [(L,'+')] ++ replicate (xsc+1) (L,'-') ++ [(M,'+')] ++ replicate (ysa+1) (R,'-') ++ [(R,'+')] ++ replicate ysc (R,' ')
l4 = replicate xsa (L,' ') ++ [(L,'|')] ++ replicate (xsc+ysa+3) (M,' ') ++ [(R,'|')] ++ replicate ysc (R,' ')

Related

how to pass a string around a list of strings in haskell

How would I get this piece of code to accept a list of strings and output a frame around the outside. I understand the concept but just cannot execute the code in the final frame function.
minusdots :: Int -> String
minusdots 1 = "-."
minusdots n
| n > 1 = "-." ++ (minusdots (n-1))
| otherwise = error "please enter greater than 1"
bar :: Int -> String
bar n
| even n = minusdots (div n 2)
| otherwise = (minusdots (div n 2)) ++ ['-']
frame :: [String] -> IO String
frame text = map putStrLn (bar m) ++ "\n" ++ textshown ++ "\n" ++ (bar m)
where
textshown = "- " ++ text ++ " -"
m = length textshown
I have worked on this all day and come up with this but there's still some bugs I need to work out 1. When I pass the border string into the frameM function, If I was to pass say "S S" is there any way I could make the S'S frame on top of each other,istead of side by side so the more letters i put into the first argument the bigger the total perimeter of the frame gets? heres what I've done:
minusdots :: Int -> String -> String
minusdots 1 a = a
minusdots n a
| n > 1 = a ++ (minusdots (n-1) a)
| otherwise = error "argument not addmissible"
bar :: String -> Int -> String
bar s n
| even n = minusdots (div n 2) s
| otherwise = (minusdots (div n 2) s) ++ s
frameM :: String -> String -> String
frameM a text = (bar a m) ++ "\n" ++ textshown ++ "\n" ++ (bar a m)
where
textshown = b ++ text ++ b
m = length textshown
b = a
I believe the type of your frame should be frame :: String -> IO () — it takes a string a puts a "framed" version of it to stdout. Then you don't need map putStrLn and can just use putStrLn.
Now, consider this line:
putStrLn (bar m) ++ "\n" ++ textshown ++ "\n" ++ (bar m)
you are calling putStrLn (bar m) and then trying to append some stuff to the result of that (hint: use parentheses or $).

How to optimize a transitive closure?

I have the following code, which I would like to optimize.
I'm particularly unhappy with nub :
deep (Op o x) = [f (Op o x)] ++ map (\y->(Op o y)) (sf x)
deep x = [x]
sf [x] = [[f x]]
sf (x:xs) = map (\y->(y:xs)) (deep x) ++ map (x:) (sf xs)
eqlst l
| l == ll = l
| otherwise = eqlst ll
where ll = nub $ l ++ (concat $ map deep l)
For a full understanding of this, I provide all my code, which is not so long:
module Nat ( Nat, Operator(Add, Mul), Exp(Const, Name, Op), toNat, fromNat) where
import Data.List(nub)
newtype Nat = Nat Integer deriving (Eq, Show, Ord)
toNat :: Integer -> Nat
toNat x | x <= 0 = error "Natural numbers should be positive."
| otherwise = Nat x
fromNat :: Nat -> Integer
fromNat (Nat n) = n
instance Num Nat where
fromInteger = toNat
x + y = toNat (fromNat x + fromNat y)
x - y = toNat (fromNat x - fromNat y)
x * y = toNat (fromNat x * fromNat y)
abs x = x
signum x = 1
data Operator = Add | Sub | Mul
deriving (Eq, Show, Ord)
data Exp = Const Nat | Name { name::String } | Op{ op::Operator, kids::[Exp] }
deriving (Eq, Ord)
precedence :: Exp -> Integer
precedence (Const x) = 10
precedence (Name x) = 10
precedence (Op Add x) = 6
precedence (Op Sub x) = 6
precedence (Op Mul x) = 7
instance Show Exp where
show Op { op = Add, kids = [x, y] } =
let left = if precedence x <= 6 then "(" ++ show x ++ ")" else show x in
let right = if precedence y <= 6 then "(" ++ show y ++ ")" else show y in
left ++ "+" ++ right
show Op { op = Sub, kids = [x, y] } =
let left = if precedence x <= 6 then "(" ++ show x ++ ")" else show x in
let right = if precedence y <= 6 then "(" ++ show y ++ ")" else show y in
left ++ "-" ++ right
show Op { op = Mul, kids = [x, y] } =
let left = if precedence x <= 7 then "(" ++ show x ++ ")" else show x in
let right = if precedence y <= 7 then "(" ++ show y ++ ")" else show y in
left ++ "∙" ++ right
show (Const (Nat x)) = show x
show (Name x) = x
show x = "wat"
instance Num Exp where
fromInteger = Const . toNat
(Const x) + (Const y) = Const (x+y)
x + y = simplify $ Op { op = Add, kids = [x, y] }
(Const x) - (Const y) = Const (x-y)
x - y = simplify $ Op { op = Sub, kids = [x, y] }
(Const x) * (Const y) = Const (x*y)
x * y = simplify $ Op { op = Mul, kids = [x, y] }
abs x = x
signum x = 1
simplify :: Exp -> Exp
simplify (Op Mul [x,1]) = x
simplify (Op Mul [1,x]) = x
simplify (Op Sub [x,y])
| x == y = 0
| otherwise = (Op Sub [x,y])
simplify x = x
f (Op Add [x,y]) = y+x
f (Op Sub [x,y]) = y-x
f (Op Mul [x,y]) = y*x
f x = x
deep (Op o x) = [f (Op o x)] ++ map (\y->(Op o y)) (sf x)
deep x = [x]
sf [x] = [[f x]]
sf (x:xs) = map (\y->(y:xs)) (deep x) ++ map (x:) (sf xs)
eqlst l
| l == ll = l
| otherwise = eqlst ll
where ll = nub $ l ++ (concat $ map deep l)
eq x = eqlst [x]
main = do
let x = Name "x";y = Name "x";z = Name "z";w = Name "w";q = Name "q"
let g = (x+y+(z+w)+q)+(x+y+(z+w)+q)+(x+y+(z+w)+q)+(x+y+(z+w)+q)
putStr $ unlines $ map show $ eq g
I also have a side question, about the function deep and sf that are using f::Exp->Exp. In the end, f should probably be f::[Exp]->[Exp].
Right now, f only performs one kind of transformation. In the end, I would like it to perform many kinds of transformations, for example :
a+b->b+a, (a+b)+c->a+(b+c), etc.
The function nub is inefficient since it only uses an Eq constraint and therefore has to compare every nondiscarded pair of elements. Using the more efficient Data.Set, which is based internally on sorted trees, should improve on this:
import qualified Data.Set as S
eqset s
| s == ss = s
| otherwise = eqset ss
where ss = S.unions $ s : map (S.fromList . deep) (S.toList s)
eqlst = S.toList . eqset . S.fromList

Displaying binary tree in Haskell

data BinTree a = Empty | Node a (BinTree a) (BinTree a)
deriving (Show)
I'm trying to figure out a way to display a binary tree in a manner such that for each level I go down in the tree, I want to add an additional * next to the name of the node and have them all separated by \n.
For example:
let x = Node "Parent" (Node "childLeft" (Node "grandChildLeftLeft" Emp Emp) Emp) (Node "childRight" Emp Emp)
putStrLn $ displayTree x
should return:
"Parent"
*"childLeft"
**"grandChildLeftLeft"
*"childRight"
My function (only prints up to one *):
displayTree :: Show a => BinTree a -> String
displayTree Emp = ""
displayTree (Node head Emp Emp) = (show head)
displayTree (Node head left Emp) = (show head) ++ "\n*" ++ displayTree left
displayTree (Node head Emp right) = (show head) ++ "\n*" ++ displayTree right
displayTree (Node head left right) = (show head) ++ "\n*" ++ displayTree left ++ "\n*" ++ displayTree right
My displayTree function would print:
"Parent"
*"childLeft"
*"grandChildLeftLeft"
*"childRight"
I want "grandChildLeftLeft" to have ** next to it instead of just *.
Any suggestions?
NOTE: I don't want to change the parameters that are passed into the function, so it should stay as displayTree :: Show a => BinTree a -> String
I think this is what you want:
module Main (main) where
data BinTree a = Empty | Node a (BinTree a) (BinTree a)
deriving (Show)
showTree :: Show a => BinTree a -> Int -> String
showTree (Empty) _ = []
showTree (Node t l r) n = replicate n '*' ++ show t ++ "\n" ++ showTree l (n+1) ++ showTree r (n+1)
main :: IO ()
main = do
let x = Node "Parent" (Node "childLeft" (Node "grandChildLeftLeft" Empty Empty) Empty) (Node "childRight" Empty Empty)
putStrLn $ showTree x 0
Note the accumulator n which changes the indent level with each recursive call.
http://ideone.com/lphCoV
"Parent"
*"childLeft"
**"grandChildLeftLeft"
*"childRight"
Why not pass in the depth to the displayTree function?
displayTree :: Show a => BinTree a -> String
displayTree = displayTree' ""
displayTree' str Emp = ""
displayTree' str (Node head Emp Emp) = str ++ (show head)
displayTree' str (Node head left Emp) = str ++ (show head) ++ "\n" ++ displayTree' (str ++ "*") left
displayTree' str (Node head Emp right) = str ++ (show head) ++ "\n" ++ displayTree' (str ++ "*") right
displayTree' str (Node head left right) = str ++ (show head) ++ "\n" ++ displayTree' (str ++ "*") left ++ "\n" ++ displayTree (str ++ "*") right
Also, here's it refactored to be kinda more readable:
displayTree :: Show a => BinTree a -> String
displayTree = displayTree' ""
displayTree' str Empty = ""
displayTree' str (Node h l r) = hstr ++ lstr ++ rstr
where
hstr = str ++ (show head) ++ "\n"
lstr = makeTreeStr l
rstr = makeTreeStr r
makeTreeStr Empty = ""
makeTreeStr tree = displayTree' (str ++ "*") tree ++ "\n"

How does one pretty print recursion depth in Haskell?

Let's say I have a binary tree.
main = putStrLn $ printTree tree
data Tree = Empty | Node Int (Tree) (Tree) deriving (Show)
tree = Node 4 (Node 3 Empty (Node 2 Empty Empty)) Empty
printTree :: Tree -> String
printTree x = case x of
Node num treeA treeB -> show num ++ "\n" ++ printTree treeA ++ "\n" ++ printTree treeB
Empty -> "Empty"
Output
*Main> main
4
3
Empty
2
Empty
Empty
Empty
Desired Output (delimited by tabs or double space is fine)
*Main> main
4
3
Empty
2
Empty
Empty
Empty
You can use an accumulator (here, depth) to keep track of how deep you currently are in the tree - then create a number of spaces corresponding to the depth the line is at:
main = putStrLn $ printTree tree
data Tree = Empty | Node Int (Tree) (Tree) deriving (Show)
tree = Node 4 (Node 3 Empty (Node 2 Empty Empty)) Empty
printTree :: Tree -> String
printTree x = printTree' x 0
where
printTree' x depth = case x of
Node num treeA treeB -> (replicate (2 * depth) ' ') ++ show num ++ "\n" ++ (printTree' treeA (depth + 1)) ++ "\n" ++ (printTree' treeB (depth + 1))
Empty -> (replicate (2 * depth) ' ') ++ "Empty"
Output:
*Main> main
4
3
Empty
2
Empty
Empty
Empty
Here's a solution using -XImplicitParams in GHC
{-# LANGUAGE ImplicitParams #-}
module ImplicitTabs where
data Tree = Empty | Node Int (Tree) (Tree) deriving (Show)
tree = Node 4 (Node 3 Empty (Node 2 Empty Empty)) Empty
tab :: (?tab_level :: Int) => String
tab = replicate (2 * ?tab_level) ' '
printTree :: (?tab_level :: Int) => Tree -> String
printTree x = let
?tab_level = ?tab_level + 1
in case x of
Node num treeA treeB -> tab ++ show num ++ "\n" ++ tab ++ printTree treeA ++ "\n" ++ tab ++ printTree treeB
Empty -> tab ++ "Empty"
main = let ?tab_level = -1 in putStrLn $ printTree tree
> runhaskell implicit-tabulation.hs
4
3
Empty
2
Empty
Empty
Empty
Ok I think I got it to work.
printTree :: Tree -> String
printTree x = printT 0 x
space x = take x $ cycle " "
printT :: Int -> Tree -> String
printT num x =
case x of
(Node o treeA treeB) -> show o ++
"\n" ++
space num ++
printT (num+1) treeA ++
"\n" ++
space num ++
printT (num+1) treeB
Empty -> "Empty"
If you convert to a Data.Tree, then you can use the library function drawTree which does almost what you are looking for (it also draws branches with ASCII art).

Instantiate Show class for a new data type

I defined these datatype:
data Term = Symbol [Char] | Number [Int]
data Exp = Fun (String, Term) | Exp (String, [Exp])
And then i wrote some Show rules:
instance Show Term where
show (Symbol [x]) = [x]
show (Symbol (x:xs)) = [x]++", "++(show (Symbol xs))
show (Number [x]) = (show x)
show (Number (x:xs)) = (show x)++", "++(show (Number xs))
instance Show Exp where
show (Fun (name, args)) = name++"("++(show args)++")"
show (Exp (name, args)) = name++"("++(show args)++")"
Now if i let:
bt = Exp("z", [Fun("f", Number [1,2,3]), Fun("g", Symbol ['a', 'b', 'c'])])
showing it i get:
z([f(1, 2, 3),g(a, b, c)])
I would prefer to have this representation:
z(f(1, 2, 3),g(a, b, c))
i.e. without square brackets inside.
Can someone help me?
I tried to add these statements:
instance Show [Exp] where
show [x] = show x
show (x:xs) = (show x)++(show xs)
but ghci claims that it's note legal code.
You can define the showList function in your Show instance for Exp.
instance Show Exp where
show (Fun (name, args)) = name++"("++(show args)++")"
show (Exp (name, args)) = name++"("++(show args)++")"
showList [] _ = ""
showList [x] _ = show x
showList (x:xs) _ = show x ++ "," ++ show xs
You can simply change this line:
show (Exp (name, args)) = name++"("++(show args)++")"
... so that it says:
show (Exp (name, args)) = name++"("++(intercalate ", " . map show $ args)++")"
The function intercalate is from Data.List.

Resources