import Data.List import qualified Data.Map.Strict as DMS import Control.Monad.State.Lazy type Path = [String] type FilesizeEntry = (Path, Int) path :: FilesizeEntry -> Path path (p,_) = p filesize :: FilesizeEntry -> Int filesize (_,i) = i normalizePath l|("..":_:r)<-l=r|let=l traversePath :: Path -> [String] -> [FilesizeEntry] traversePath currentPath (line:input) |"$ cd .." == line = traversePath (tail currentPath) input |("$ cd ",directory)<-splitAt 5 line,normalizedPath<-directory:currentPath = traversePath normalizedPath input |[(filesize, "")]<-reads$fst$head$lex line, (_, filename) <- span (/=' ') line = (tail filename:currentPath,filesize):traversePath currentPath input |let=traversePath currentPath input traversePath _ [] = [] recFiles :: Path -> [FilesizeEntry] -> [Int] recFiles directory = map filesize.filter(\entry->directory `isSuffixOf` path entry) allDirectories = nub.map (tail.path) gather :: [FilesizeEntry] -> [FilesizeEntry] gather directoryFileEntries = [ (uniqueDirectory,sum$recFiles uniqueDirectory directoryFileEntries) | uniqueDirectory<-allDirectories directoryFileEntries] sumsmall :: [FilesizeEntry] -> Int sumsmall l=sum[f|(d,f)<-l, f<=100000] main=interact$pprint[].take 20.traversePath [].lines updateOrInsert :: Int -> Maybe Int -> Maybe Int updateOrInsert a (Just x) = Just (x+a) updateOrInsert a _ = Just (a) files2folders :: [FilesizeEntry] -> State (DMS.Map Path Int) () files2folders [] = return () files2folders ((_:path, size):xs) = do forM (init$tails path) (\part -> modify $ DMS.alter (updateOrInsert size) part) files2folders xs pprint _ [] = [] pprint cur (entry:list) |cur == (tail $ path entry) = show(filesize entry) ++ " " ++ (head$path entry) ++ "\n" ++ pprint cur list |otherwise = (tail$concat$intersperse "/"$reverse$tail$path entry) ++ "\n" ++ pprint (tail $ path entry) (entry:list) -- t = map(\(h,t)->(h,sum t)) -- t l=groupBy(\(i,_)(j,_)->i==j)$[(o,i)|(e,_)<-l,(o,i)<-l,isPrefixOf e o] -- main=interact$show.map(foldr1(\(d,i)(c,j)->(d,i+j))).t.sort.x.lines -- input = readFile "day7long" prepare = input >>= (return.traversePath [].lines)