day7. finally.
This commit is contained in:
parent
f576146891
commit
3a1d612f97
|
@ -0,0 +1,122 @@
|
||||||
|
import System.IO
|
||||||
|
|
||||||
|
import Data.List
|
||||||
|
import Data.List.Split
|
||||||
|
|
||||||
|
import Debug.Trace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data Node = File String Int | Dir String Int [Node] deriving (Show)
|
||||||
|
|
||||||
|
instance Eq Node where
|
||||||
|
Dir n1 _ _ == Dir n2 _ _ = n1 == n2
|
||||||
|
File n1 _ == File n2 _ = n1 == n2
|
||||||
|
|
||||||
|
instance Ord Node where
|
||||||
|
Dir _ s1 _ `compare` Dir _ s2 _ = s1 `compare` s2
|
||||||
|
File _ s1 `compare` File _ s2 = s1 `compare` s2
|
||||||
|
|
||||||
|
nodeSize :: Node -> Int
|
||||||
|
nodeSize (File _ s) = s
|
||||||
|
nodeSize (Dir _ s _) = s
|
||||||
|
|
||||||
|
|
||||||
|
nodeInfo :: Node -> String
|
||||||
|
nodeInfo (File n s) = n ++ "(file, size=" ++ show s ++ ")"
|
||||||
|
nodeInfo (Dir n s _) = n ++ "(dir, size=" ++ show s ++ ")"
|
||||||
|
|
||||||
|
printNode :: Int -> Node -> String
|
||||||
|
printNode lvl n = case n of
|
||||||
|
File n s -> sp ++ "- " ++ n ++ " (file, size=" ++ show s ++ ")\n"
|
||||||
|
Dir n s c -> sp ++ "- " ++ n ++ " (dir, size=" ++ show s ++ ")\n" ++ printNodes (lvl+1) c
|
||||||
|
where
|
||||||
|
sp = replicate (2*lvl) ' '
|
||||||
|
|
||||||
|
printNodes :: Int -> [Node] -> String
|
||||||
|
printNodes a = concat . map (printNode a)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--parseDir' :: [String] -> [Node]
|
||||||
|
--parseDir' (x:xs) =
|
||||||
|
|
||||||
|
dirInNodes :: String -> [Node] -> (Bool,Node,[Node])
|
||||||
|
dirInNodes name onodes = (exists, instanc, removed)
|
||||||
|
where
|
||||||
|
matches = filter (\node@(Dir n _ _) -> n == name) onodes
|
||||||
|
exists = (length matches) > 0
|
||||||
|
instanc = if exists then head matches else File "<nonexistent>" 0
|
||||||
|
removed = delete instanc onodes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
parseDir :: [Node] -> [Node] -> [String] -> ([Node],[String])
|
||||||
|
parseDir onodes nodes (x:xs)
|
||||||
|
| "$ cd " `isPrefixOf` x = ((Dir (drop 5 x) (sum $ map nodeSize nodes) nodes:onodes), xs)
|
||||||
|
| "dir " `isPrefixOf` x = case dirInNodes (drop 4 x) onodes of
|
||||||
|
(True,node,restnodes) -> parseDir restnodes (node:nodes) xs
|
||||||
|
(False,_,_) -> parseDir onodes nodes xs
|
||||||
|
| otherwise = parseDir onodes (File fname fsize:nodes) xs
|
||||||
|
where
|
||||||
|
[fsize',fname] = splitOn " " x
|
||||||
|
fsize = read fsize' :: Int
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
parseCli :: [Node] -> [String] -> [String] -> [Node]
|
||||||
|
parseCli nodes [] [] = []
|
||||||
|
parseCli nodes stack [] = onodes ++ parseCli onodes reststack []
|
||||||
|
where (onodes,reststack) = parseDir nodes [] $ stack
|
||||||
|
parseCli nodes stack (x:xs)
|
||||||
|
| x == "$ cd .." = onodes ++ parseCli onodes reststack xs
|
||||||
|
| otherwise = parseCli nodes (x:stack) xs
|
||||||
|
where (onodes,reststack) = parseDir nodes [] $ stack
|
||||||
|
|
||||||
|
|
||||||
|
prepCli :: [String] -> [String]
|
||||||
|
prepCli = filter (/= "$ ls")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
findNodes :: (Node -> Bool) -> Node -> [Node]
|
||||||
|
findNodes f file@(File _ _) = if (f file) then [file] else []
|
||||||
|
findNodes f dir@(Dir _ _ c) = (if (f dir) then [dir] else []) ++ (concat $ map (findNodes f) c)
|
||||||
|
|
||||||
|
|
||||||
|
dirSize :: (Int -> Bool) -> Node -> Bool
|
||||||
|
dirSize _ (File _ _) = False
|
||||||
|
dirSize f (Dir _ s _) = f s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
findDeletable :: Int -> Int -> Node -> Node
|
||||||
|
findDeletable fss req root@(Dir _ used _) = smallest
|
||||||
|
where
|
||||||
|
tbf = req - (fss-used)
|
||||||
|
candidates = findNodes (dirSize (>= tbf)) root
|
||||||
|
smallest = head $ sort candidates
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
handler :: String -> String
|
||||||
|
handler s = (show sumUnder) ++ "\n" ++
|
||||||
|
(show savsize) ++ "\n"
|
||||||
|
where
|
||||||
|
rootNode = last $ parseCli [] [] $ prepCli $ lines s
|
||||||
|
under100k = findNodes (dirSize (<= 100000)) rootNode
|
||||||
|
sumUnder = sum $ map (\(Dir _ s _) -> s) under100k
|
||||||
|
(Dir _ savsize _) = findDeletable 70000000 30000000 rootNode
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
interact handler
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue