69 lines
1.8 KiB
Haskell
69 lines
1.8 KiB
Haskell
import Data.List
|
|
|
|
type Name = String
|
|
|
|
type Size = Int
|
|
|
|
data Inode
|
|
= File Name Size
|
|
| Folder Name [Inode]
|
|
deriving (Show)
|
|
|
|
data ICrumb =
|
|
ICrumb Name [Inode]
|
|
deriving (Show)
|
|
|
|
type IZipper = (Inode, [ICrumb])
|
|
|
|
main :: IO ()
|
|
main = do
|
|
input <- map words . lines <$> readFile "input"
|
|
let fullFS = walk (tail input) (Folder "/" [], [])
|
|
let sizeList = getDirSizeList $ upTop fullFS
|
|
print $ sum $ filter (< 100000) sizeList
|
|
let toDelete = subtract 40000000 $ getDirSize $ upTop fullFS
|
|
print $ head $ dropWhile (< toDelete) $ sort sizeList
|
|
|
|
up :: IZipper -> IZipper
|
|
up (node, ICrumb name nodes:crumbs) = (Folder name (node : nodes), crumbs)
|
|
|
|
upTop :: IZipper -> IZipper
|
|
upTop (inode, []) = (inode, [])
|
|
upTop z = upTop (up z)
|
|
|
|
newFile :: Inode -> IZipper -> IZipper
|
|
newFile node (Folder name nodes, crumbs) = (Folder name (node : nodes), crumbs)
|
|
|
|
goTo :: Name -> IZipper -> IZipper
|
|
goTo name (Folder fname nodes, crumbs) =
|
|
let (ls, node:rs) = break (nameIs name) nodes
|
|
in (node, ICrumb fname (ls ++ rs) : crumbs)
|
|
|
|
nameIs :: Name -> Inode -> Bool
|
|
nameIs name (Folder folderName _) = name == folderName
|
|
nameIs name (File fileName _) = name == fileName
|
|
|
|
walk :: [[String]] -> IZipper -> IZipper
|
|
walk (["$", "cd", name]:xs) z =
|
|
walk xs $
|
|
if name == ".."
|
|
then up z
|
|
else goTo name z
|
|
walk (["$", "ls"]:xs) z = walk xs z
|
|
walk (["dir", name]:xs) z = walk xs $ newFile (Folder name []) z
|
|
walk ([size, name]:xs) z = walk xs $ newFile (File name (read size)) z
|
|
walk _ z = z
|
|
|
|
getDirSize :: IZipper -> Int
|
|
getDirSize (Folder _ nodes, _) = sum $ map getSize nodes
|
|
where
|
|
getSize (File _ size) = size
|
|
getSize folder = getDirSize (folder, [])
|
|
getDirSize _ = 0
|
|
|
|
getDirSizeList :: IZipper -> [Int]
|
|
getDirSizeList (Folder _ nodes, _) =
|
|
getDirSize (Folder "" nodes, []) :
|
|
concat [getDirSizeList (node, []) | node <- nodes]
|
|
getDirSizeList _ = []
|