Created
January 5, 2019 16:32
-
-
Save zofy/f38c6be389b794926a637265a7d32763 to your computer and use it in GitHub Desktop.
Haskell solution (using zipper) for tree_manager task at https://hackerrank.com
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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