2022-12-08 22:50:11 +01:00
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
2022-12-08 23:00:15 +01:00
getDirSize ( ( Folder _ nodes ) , _ ) = sum $ map getSize nodes
2022-12-08 22:50:11 +01:00
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 _ = []