From 553cdd7d597849c18e2f1c42d4f4e296cae20676 Mon Sep 17 00:00:00 2001 From: "Jill \"oatmealine\" Monoids" Date: Wed, 7 Dec 2022 11:14:01 +0300 Subject: [PATCH] day 7 --- 7-a.hs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7-b.hs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 7-a.hs create mode 100644 7-b.hs diff --git a/7-a.hs b/7-a.hs new file mode 100644 index 0000000..2a60c8b --- /dev/null +++ b/7-a.hs @@ -0,0 +1,62 @@ +{-# LANGUAGE OverloadedStrings #-} + +import qualified Data.Text as T +import Data.Char (isSpace) +import Data.List (uncons, nub, isPrefixOf) +import GHC.Data.Maybe (mapMaybe) + +evaluateCD :: [String] -> String -> [String] +evaluateCD dir command = case cdTo of + ".." -> init dir + "/" -> [] + d -> dir ++ [d] + where cdTo = words command !! 1 + +evaluateLS :: [String] -> [([String], Int)] -> [String] -> [([String], Int)] +evaluateLS dir files cr = files ++ map (\[size, file] -> (dir ++ [file], read size)) onlyFiles + where onlyFiles = filter (\[h,_] -> h /= "dir") splitFiles + splitFiles = map words cr + +evaluateCommand :: [String] -> [([String], Int)] -> (String, [String]) -> ([String], [([String], Int)]) +evaluateCommand dir files (c, cr) = case head $ words $ c of + "cd" -> (evaluateCD dir c, files) + "ls" -> (dir, evaluateLS dir files cr) + c -> error $ "Unknown command: " ++ c + +-- takes in a starting directory, a list of files, and a sequence of commands, and evaluates them, +-- returning the a list of tuples representing the filepath and the filesize +evaluateCommands :: [String] -> [([String], Int)] -> [(String, [String])] -> [([String], Int)] +evaluateCommands dir files (c:xs) = evaluateCommands newDir newFiles xs + where (newDir, newFiles) = evaluateCommand dir files c +evaluateCommands dir files [] = files + +getAllPossibleDirectoriesOfPath :: [String] -> [[String]] +getAllPossibleDirectoriesOfPath [] = [[]] +getAllPossibleDirectoriesOfPath p = p : getAllPossibleDirectoriesOfPath (init p) + +filterByListPrefix :: [String] -> [[String]] -> [[String]] +filterByListPrefix prefix = filter (`elem` decomposedPrefix) + where decomposedPrefix = getAllPossibleDirectoriesOfPath prefix + +-- takes in a list of filepaths, and transforms them into a deduplicated list of only the +-- directories those files are stored in +getDirectories :: [[String]] -> [[String]] +getDirectories = nub . concatMap (getAllPossibleDirectoriesOfPath . init) + +fromFileSizesToPaths :: [([String], Int)] -> [[String]] +fromFileSizesToPaths = map fst + +calculateDirSize :: [[String]] -> [([String], Int)] -> [String] -> Int +calculateDirSize dirs files dir = sum $ map snd justFiles + where justFiles = filter (isPrefixOf dir . fst) files + +getDirectorySums f = map (calculateDirSize (getDirectories $ fromFileSizesToPaths f) f) (getDirectories $ fromFileSizesToPaths f) + +main = interact $ + show + . sum . filter (<= 100000) + . getDirectorySums + . evaluateCommands [] [] + . mapMaybe (uncons . lines . dropWhile isSpace) + . takeWhile (not . null) . dropWhile null + . map T.unpack . T.splitOn "$" . T.pack \ No newline at end of file diff --git a/7-b.hs b/7-b.hs new file mode 100644 index 0000000..b9cc3e7 --- /dev/null +++ b/7-b.hs @@ -0,0 +1,66 @@ +{-# LANGUAGE OverloadedStrings #-} + +import qualified Data.Text as T +import Data.Char (isSpace) +import Data.List (uncons, nub, isPrefixOf, sort) +import GHC.Data.Maybe (mapMaybe) +import Data.Foldable (find) +import Data.Maybe (fromJust) + +evaluateCD :: [String] -> String -> [String] +evaluateCD dir command = case cdTo of + ".." -> init dir + "/" -> [] + d -> dir ++ [d] + where cdTo = words command !! 1 + +evaluateLS :: [String] -> [([String], Int)] -> [String] -> [([String], Int)] +evaluateLS dir files cr = files ++ map (\[size, file] -> (dir ++ [file], read size)) onlyFiles + where onlyFiles = filter (\[h,_] -> h /= "dir") splitFiles + splitFiles = map words cr + +evaluateCommand :: [String] -> [([String], Int)] -> (String, [String]) -> ([String], [([String], Int)]) +evaluateCommand dir files (c, cr) = case head $ words $ c of + "cd" -> (evaluateCD dir c, files) + "ls" -> (dir, evaluateLS dir files cr) + c -> error $ "Unknown command: " ++ c + +-- takes in a starting directory, a list of files, and a sequence of commands, and evaluates them, +-- returning the a list of tuples representing the filepath and the filesize +evaluateCommands :: [String] -> [([String], Int)] -> [(String, [String])] -> [([String], Int)] +evaluateCommands dir files (c:xs) = evaluateCommands newDir newFiles xs + where (newDir, newFiles) = evaluateCommand dir files c +evaluateCommands dir files [] = files + +getAllPossibleDirectoriesOfPath :: [String] -> [[String]] +getAllPossibleDirectoriesOfPath [] = [[]] +getAllPossibleDirectoriesOfPath p = p : getAllPossibleDirectoriesOfPath (init p) + +filterByListPrefix :: [String] -> [[String]] -> [[String]] +filterByListPrefix prefix = filter (`elem` decomposedPrefix) + where decomposedPrefix = getAllPossibleDirectoriesOfPath prefix + +-- takes in a list of filepaths, and transforms them into a deduplicated list of only the +-- directories those files are stored in +getDirectories :: [[String]] -> [[String]] +getDirectories = nub . concatMap (getAllPossibleDirectoriesOfPath . init) + +fromFileSizesToPaths :: [([String], Int)] -> [[String]] +fromFileSizesToPaths = map fst + +calculateDirSize :: [[String]] -> [([String], Int)] -> [String] -> Int +calculateDirSize dirs files dir = sum $ map snd justFiles + where justFiles = filter (isPrefixOf dir . fst) files + +getDirectorySums :: [([String], Int)] -> [Int] +getDirectorySums f = map (calculateDirSize (getDirectories $ fromFileSizesToPaths f) f) (getDirectories $ fromFileSizesToPaths f) + +main = interact $ + show + . fromJust + . (\d -> find (>= (30000000 - (70000000 - maximum d))) $ sort d) + . getDirectorySums + . evaluateCommands [] [] + . mapMaybe (uncons . lines . dropWhile isSpace) + . takeWhile (not . null) . dropWhile null + . map T.unpack . T.splitOn "$" . T.pack \ No newline at end of file