Skip to content

Instantly share code, notes, and snippets.

@zofy
Created January 5, 2019 16:32
Show Gist options
  • Save zofy/f38c6be389b794926a637265a7d32763 to your computer and use it in GitHub Desktop.
Save zofy/f38c6be389b794926a637265a7d32763 to your computer and use it in GitHub Desktop.
Haskell solution (using zipper) for tree_manager task at https://hackerrank.com
import Data.List (isPrefixOf, intercalate)
import Data.List.Split
import Control.Monad
data Tree a = Empty | Node a [Tree a] deriving (Show, Eq)
type Zipper a = (Tree a, [Tree a], [Int])
_nthItem :: [a] -> Int -> a
_nthItem (x:xs) 1 = x
_nthItem (x:xs) n = _nthItem xs (n - 1)
_insertItem :: [a] -> a -> Int -> [a]
_insertItem xs item 1 = item : xs
_insertItem (x:xs) item n = x : (_insertItem xs item (n - 1))
_deleteItem :: [a] -> Int -> [a]
_deleteItem (x:xs) 1 = xs
_deleteItem (x:xs) n = x : (_deleteItem xs (n - 1))
_modifyItem :: [a] -> Int -> a -> [a]
_modifyItem (x:xs) 1 y = y:xs
_modifyItem (x:xs) n y = x : (_modifyItem xs (n - 1) y)
_get_node :: Zipper a -> Tree a
_get_node (t, _, _) = t
deleteChild :: Zipper a -> Int -> Zipper a
deleteChild (Node x chs, ps, is) n = (Node x (_deleteItem chs n), ps, is)
modifyChild :: Zipper a -> Tree a -> Int -> Zipper a
modifyChild (Node x chs, ps, is) child_tree idx = (Node x (_modifyItem chs idx child_tree), ps, is)
visitChild :: Zipper a -> Int -> Zipper a
visitChild (Node x chs, ps, is) n = (_nthItem chs n, me:ps, n:is)
where
me = Node x chs
goUp :: Zipper a -> Zipper a
goUp (_, (p:ps), (i:is)) = (p, ps, is)
goLeft :: Zipper a -> Zipper a
goLeft (t, ps, (idx:is)) = visitChild parent (idx - 1)
where
parent = goUp (t, ps, (idx:is))
goRight :: Zipper a -> Zipper a
goRight (t, ps, (idx:is)) = visitChild parent (idx + 1)
where
parent = goUp (t, ps, (idx:is))
change :: Zipper a -> a -> Zipper a
change (Node x chs, [], []) value = (Node value chs, [], [])
change (Node x chs, ps, idx:is) value = visitChild parent idx
where
child = Node value chs
parent = modifyChild (goUp (Node x chs, ps, idx:is)) child idx
insertChild :: Zipper a -> a -> Int -> Zipper a
insertChild (Node x chs, ps, is) value idx = (Node x children, ps, is)
where
child = Node value []
children = _insertItem chs child idx
insert :: Zipper a -> a -> Zipper a
insert (t, [], []) value = insertChild (t, [], []) value 1
insert (Node x chs, ps, (idx:is)) value = visitChild parent idx
where
me = (Node x chs, ps, (idx:is))
new_node = _get_node (insertChild me value 1)
parent = modifyChild (goUp me) new_node idx
insertLeft :: Zipper a -> a -> Zipper a
insertLeft (t, ps, (idx:is)) value = visitChild parent (idx + 1)
where
parent = insertChild (goUp (t, ps, (idx:is))) value idx
insertRight :: Zipper a -> a -> Zipper a
insertRight (t, ps, (idx:is)) value = visitChild parent idx
where
parent = insertChild (goUp (t, ps, (idx:is))) value (idx + 1)
delete :: Zipper a -> Zipper a
delete (t, ps, idx:is) = deleteChild parent idx
where parent = goUp (t, ps, idx:is)
mapCmd :: String -> Zipper Int -> Zipper Int
mapCmd s z
| isPrefixOf "delete" s = delete z
| isPrefixOf "visit parent" s = goUp z
| isPrefixOf "visit left" s = goLeft z
| isPrefixOf "visit right" s = goRight z
| isPrefixOf "change" s = change z (read (last (splitOn " " s)) :: Int)
| isPrefixOf "insert child" s = insert z (read (last (splitOn " " s)) :: Int)
| isPrefixOf "insert right" s = insertRight z (read (last (splitOn " " s)) :: Int)
| isPrefixOf "insert left" s = insertLeft z (read (last (splitOn " " s)) :: Int)
| isPrefixOf "visit child" s = visitChild z ((read (last (splitOn " " s)) :: Int))
| otherwise = z
mapCmds :: Zipper Int -> [String] -> [Zipper Int]
mapCmds z [] = []
mapCmds z (x:xs) = zz : (mapCmds zz xs)
where zz = mapCmd x z
getValue :: Zipper Int -> String
getValue (Node x _, _, _) = show x
main :: IO()
main = do
line <- getLine
let n = read line :: Int
let zipper = (Node 0 [], [], [])
cmds <- forM [1..n] (\a -> do
string <- getLine
return string)
let rs = map (\t -> getValue $ snd t) $ filter (\t -> fst t == "print") $ zip cmds $ mapCmds zipper cmds
mapM_ print rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment