From 205c5deed3a8402f1e9ddc546c3fbac163c1c491 Mon Sep 17 00:00:00 2001 From: Amneesh Singh Date: Wed, 7 Dec 2022 16:43:56 +0530 Subject: [PATCH] day7: clean up a bit and add comments Signed-off-by: Amneesh Singh --- day7'.hs | 33 ++++++++++++++++----------------- day7.hs | 40 +++++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/day7'.hs b/day7'.hs index f5c0022..849164e 100644 --- a/day7'.hs +++ b/day7'.hs @@ -2,7 +2,7 @@ import Data.Tree main :: IO () main = do - tree <- flip parse (emptyFs "/") . map words . lines <$> readFile "day7.in" + tree <- snd . flip parse (emptyFs "/") . map words . lines <$> readFile "day7.in" putStr "Q1: " print $ foldTree @@ -22,36 +22,35 @@ main = do ) tree +type Filesystem = Tree (String, Int) + tail' :: [a] -> [a] tail' = drop 1 -emptyFs :: String -> Tree (String, Int) +emptyFs :: String -> Filesystem emptyFs n = Node (n, 0) [] -insertFs :: Tree (String, Int) -> String -> Tree (String, Int) -> Tree (String, Int) -insertFs (Node n xs) name dir = Node (fst n, snd n + snd (rootLabel dir)) (dir : xs) +insertFs :: Filesystem -> String -> Filesystem -> Filesystem +insertFs (Node n xs) name fs = Node (fst n, snd n + snd (rootLabel fs)) (fs : xs) -totalSize :: [Tree (String, Int)] -> Int +totalSize :: [Filesystem] -> Int totalSize = sum . map (snd . rootLabel) -ls :: [[String]] -> [Tree (String, Int)] +ls :: [[String]] -> [Filesystem] ls = map (\[a, b] -> Node (b, read a) []) . filter ((/= "dir") . head) -parse :: [[String]] -> Tree (String, Int) -> Tree (String, Int) -parse input fs = snd $ parse' input fs - -parse' :: [[String]] -> Tree (String, Int) -> ([[String]], Tree (String, Int)) -parse' input fs - | null input || cur !! 1 == "cd" && cur !! 2 == ".." = (tail' input, fs) - | cur !! 1 == "ls" = +parse :: [[String]] -> Filesystem -> ([[String]], Filesystem) +parse input fs + | null input || cur == ["$", "cd", ".."] = (tail' input, fs) + | cur == ["$", "ls"] = let (children, rest) = span ((/= "$") . head) (tail' input) - childFs = ls children + leaves = ls children name = fst $ rootLabel fs - in parse' rest (Node (name, totalSize childFs) childFs) + in parse rest (Node (name, totalSize leaves) leaves) | otherwise = let name = cur !! 2 - (nextInput, newFs) = parse' (tail' input) (emptyFs name) + (nextInput, newFs) = parse (tail' input) (emptyFs name) replaced = insertFs fs name newFs -- replace empty directory - in parse' nextInput replaced + in parse nextInput replaced where cur = head input diff --git a/day7.hs b/day7.hs index c7e5ff7..de5fed9 100644 --- a/day7.hs +++ b/day7.hs @@ -1,12 +1,12 @@ import Data.Tree -- this solution assumes that empty directories can exist, --- if you want to ignore that, there is a slightly more compact code as day7'.hs +-- if you want to ignore that, there is a slightly different code in day7'.hs -- needs cleaning and improvement main :: IO () main = do - tree <- flip parse (emptyFs "/") . map words . lines <$> readFile "day7.in" + tree <- snd . flip parse (emptyFs "/") . map words . lines <$> readFile "day7.in" putStr "Q1: " print $ foldTree @@ -26,40 +26,46 @@ main = do ) tree +type Filesystem = Tree (String, Int) + tail' :: [a] -> [a] tail' = drop 1 -emptyFs :: String -> Tree (String, Int) +-- wrapper to create an empty tree +emptyFs :: String -> Filesystem emptyFs n = Node (n, 0) [] -replaceFs :: Tree (String, Int) -> String -> Tree (String, Int) -> Tree (String, Int) +-- This function is to replace a filesystem by name +-- Used to replace empty directories with parsed directories in code +replaceFs :: Filesystem -> String -> Filesystem -> Filesystem replaceFs (Node n xs) name fs = let (h, t) = span ((/= name) . fst . rootLabel) xs in Node (fst n, snd n + snd (rootLabel fs)) (h ++ [fs] ++ tail' t) -totalSize :: [Tree (String, Int)] -> Int +-- Sum of all filesystems in the list +-- Used to calculate sum of leaves in code +totalSize :: [Filesystem] -> Int totalSize = sum . map (snd . rootLabel) -ls :: [[String]] -> [Tree (String, Int)] +-- All directories/files are parsed here into leaves +ls :: [[String]] -> [Filesystem] ls = map (\[a, b] -> if a == "dir" then Node (b, 0) [] else Node (b, read a) []) -parse :: [[String]] -> Tree (String, Int) -> Tree (String, Int) -parse input fs = snd $ parse' input fs - -parse' :: [[String]] -> Tree (String, Int) -> ([[String]], Tree (String, Int)) -parse' input fs - | null input || cur !! 1 == "cd" && cur !! 2 == ".." = (tail' input, fs) - | cur !! 1 == "ls" = +-- main function where stuff happens +parse :: [[String]] -> Filesystem -> ([[String]], Filesystem) +parse input fs + | null input || cur == ["$", "cd", ".."] = (tail' input, fs) + | cur == ["$", "ls"] = let (children, rest) = span ((/= "$") . head) (tail' input) - childFs = ls children + leaves = ls children name = fst $ rootLabel fs - in parse' rest (Node (name, totalSize childFs) childFs) + in parse rest (Node (name, totalSize leaves) leaves) | otherwise = let name = cur !! 2 - (nextInput, newFs) = parse' (tail' input) (emptyFs name) + (nextInput, newFs) = parse (tail' input) (emptyFs name) replaced = replaceFs fs name newFs -- replace empty directory - in parse' nextInput replaced + in parse nextInput replaced where cur = head input