day7: clean up a bit and add comments
Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
		
							
								
								
									
										33
									
								
								day7'.hs
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								day7'.hs
									
									
									
									
									
								
							@@ -2,7 +2,7 @@ import Data.Tree
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
main :: IO ()
 | 
					main :: IO ()
 | 
				
			||||||
main = do
 | 
					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: "
 | 
					  putStr "Q1: "
 | 
				
			||||||
  print $
 | 
					  print $
 | 
				
			||||||
    foldTree
 | 
					    foldTree
 | 
				
			||||||
@@ -22,36 +22,35 @@ main = do
 | 
				
			|||||||
      )
 | 
					      )
 | 
				
			||||||
      tree
 | 
					      tree
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Filesystem = Tree (String, Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tail' :: [a] -> [a]
 | 
					tail' :: [a] -> [a]
 | 
				
			||||||
tail' = drop 1
 | 
					tail' = drop 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
emptyFs :: String -> Tree (String, Int)
 | 
					emptyFs :: String -> Filesystem
 | 
				
			||||||
emptyFs n = Node (n, 0) []
 | 
					emptyFs n = Node (n, 0) []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
insertFs :: Tree (String, Int) -> String -> Tree (String, Int) -> Tree (String, Int)
 | 
					insertFs :: Filesystem -> String -> Filesystem -> Filesystem
 | 
				
			||||||
insertFs (Node n xs) name dir = Node (fst n, snd n + snd (rootLabel dir)) (dir : xs)
 | 
					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)
 | 
					totalSize = sum . map (snd . rootLabel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ls :: [[String]] -> [Tree (String, Int)]
 | 
					ls :: [[String]] -> [Filesystem]
 | 
				
			||||||
ls = map (\[a, b] -> Node (b, read a) []) . filter ((/= "dir") . head)
 | 
					ls = map (\[a, b] -> Node (b, read a) []) . filter ((/= "dir") . head)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
parse :: [[String]] -> Tree (String, Int) -> Tree (String, Int)
 | 
					parse :: [[String]] -> Filesystem -> ([[String]], Filesystem)
 | 
				
			||||||
parse input fs = snd $ parse' input fs
 | 
					parse input fs
 | 
				
			||||||
 | 
					  | null input || cur == ["$", "cd", ".."] = (tail' input, fs)
 | 
				
			||||||
parse' :: [[String]] -> Tree (String, Int) -> ([[String]], Tree (String, Int))
 | 
					  | cur == ["$", "ls"] =
 | 
				
			||||||
parse' input fs
 | 
					 | 
				
			||||||
  | null input || cur !! 1 == "cd" && cur !! 2 == ".." = (tail' input, fs)
 | 
					 | 
				
			||||||
  | cur !! 1 == "ls" =
 | 
					 | 
				
			||||||
    let (children, rest) = span ((/= "$") . head) (tail' input)
 | 
					    let (children, rest) = span ((/= "$") . head) (tail' input)
 | 
				
			||||||
        childFs = ls children
 | 
					        leaves = ls children
 | 
				
			||||||
        name = fst $ rootLabel fs
 | 
					        name = fst $ rootLabel fs
 | 
				
			||||||
     in parse' rest (Node (name, totalSize childFs) childFs)
 | 
					     in parse rest (Node (name, totalSize leaves) leaves)
 | 
				
			||||||
  | otherwise =
 | 
					  | otherwise =
 | 
				
			||||||
    let name = cur !! 2
 | 
					    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
 | 
					        replaced = insertFs fs name newFs -- replace empty directory
 | 
				
			||||||
     in parse' nextInput replaced
 | 
					     in parse nextInput replaced
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
    cur = head input
 | 
					    cur = head input
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										40
									
								
								day7.hs
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								day7.hs
									
									
									
									
									
								
							@@ -1,12 +1,12 @@
 | 
				
			|||||||
import Data.Tree
 | 
					import Data.Tree
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- this solution assumes that empty directories can exist,
 | 
					-- 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
 | 
					-- needs cleaning and improvement
 | 
				
			||||||
 | 
					
 | 
				
			||||||
main :: IO ()
 | 
					main :: IO ()
 | 
				
			||||||
main = do
 | 
					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: "
 | 
					  putStr "Q1: "
 | 
				
			||||||
  print $
 | 
					  print $
 | 
				
			||||||
    foldTree
 | 
					    foldTree
 | 
				
			||||||
@@ -26,40 +26,46 @@ main = do
 | 
				
			|||||||
      )
 | 
					      )
 | 
				
			||||||
      tree
 | 
					      tree
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Filesystem = Tree (String, Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tail' :: [a] -> [a]
 | 
					tail' :: [a] -> [a]
 | 
				
			||||||
tail' = drop 1
 | 
					tail' = drop 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
emptyFs :: String -> Tree (String, Int)
 | 
					-- wrapper to create an empty tree
 | 
				
			||||||
 | 
					emptyFs :: String -> Filesystem
 | 
				
			||||||
emptyFs n = Node (n, 0) []
 | 
					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 =
 | 
					replaceFs (Node n xs) name fs =
 | 
				
			||||||
  let (h, t) = span ((/= name) . fst . rootLabel) xs
 | 
					  let (h, t) = span ((/= name) . fst . rootLabel) xs
 | 
				
			||||||
   in Node
 | 
					   in Node
 | 
				
			||||||
        (fst n, snd n + snd (rootLabel fs))
 | 
					        (fst n, snd n + snd (rootLabel fs))
 | 
				
			||||||
        (h ++ [fs] ++ tail' t)
 | 
					        (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)
 | 
					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) [])
 | 
					ls = map (\[a, b] -> if a == "dir" then Node (b, 0) [] else Node (b, read a) [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
parse :: [[String]] -> Tree (String, Int) -> Tree (String, Int)
 | 
					-- main function where stuff happens
 | 
				
			||||||
parse input fs = snd $ parse' input fs
 | 
					parse :: [[String]] -> Filesystem -> ([[String]], Filesystem)
 | 
				
			||||||
 | 
					parse input fs
 | 
				
			||||||
parse' :: [[String]] -> Tree (String, Int) -> ([[String]], Tree (String, Int))
 | 
					  | null input || cur == ["$", "cd", ".."] = (tail' input, fs)
 | 
				
			||||||
parse' input fs
 | 
					  | cur == ["$", "ls"] =
 | 
				
			||||||
  | null input || cur !! 1 == "cd" && cur !! 2 == ".." = (tail' input, fs)
 | 
					 | 
				
			||||||
  | cur !! 1 == "ls" =
 | 
					 | 
				
			||||||
    let (children, rest) = span ((/= "$") . head) (tail' input)
 | 
					    let (children, rest) = span ((/= "$") . head) (tail' input)
 | 
				
			||||||
        childFs = ls children
 | 
					        leaves = ls children
 | 
				
			||||||
        name = fst $ rootLabel fs
 | 
					        name = fst $ rootLabel fs
 | 
				
			||||||
     in parse' rest (Node (name, totalSize childFs) childFs)
 | 
					     in parse rest (Node (name, totalSize leaves) leaves)
 | 
				
			||||||
  | otherwise =
 | 
					  | otherwise =
 | 
				
			||||||
    let name = cur !! 2
 | 
					    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
 | 
					        replaced = replaceFs fs name newFs -- replace empty directory
 | 
				
			||||||
     in parse' nextInput replaced
 | 
					     in parse nextInput replaced
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
    cur = head input
 | 
					    cur = head input
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user