Przeglądaj źródła

Day 7 - Foldable instance for summing up directories

main
Jens Kadenbach 2 lat temu
rodzic
commit
435a06fd59
4 zmienionych plików z 30 dodań i 32 usunięć
  1. 3
    6
      src/Day7.hs
  2. 25
    24
      src/Day7/Interpreter.hs
  3. 1
    1
      src/Day7/Parser.hs
  4. 1
    1
      test/Day7Spec.hs

+ 3
- 6
src/Day7.hs Wyświetl plik

@@ -13,15 +13,12 @@ day7 = do
13 13
    let parsed = forceRight $ parseTerminalLines input
14 14
    let tree = buildTree parsed
15 15
    let small = filterDirectories (<= 100000) tree
16
-   let sumOfSmall = sumUp small
16
+   let sumOfSmall = sum small
17 17
    putStrLn ("Sum of those directories is " ++ show sumOfSmall)
18
-   let rootSize = snd . head $ sizeOfDirectories tree
19
-   putStrLn ("Root size is " ++ show rootSize)
18
+   let rootSize = head $ sizeOfDirectories tree
20 19
    let freeSpace = 70000000 - rootSize
21 20
    let requiredSpace = 30000000 - freeSpace
22
-   putStrLn ("Required space is " ++ show requiredSpace)
23 21
    let bigEnough = filterDirectories (>= requiredSpace) tree
24
-   let onlySizes = map snd bigEnough
25
-   let smallest = minimum onlySizes
22
+   let smallest = minimum bigEnough
26 23
    putStrLn ("Smallest directory that is still large enough " ++ show smallest)
27 24
 

+ 25
- 24
src/Day7/Interpreter.hs Wyświetl plik

@@ -1,29 +1,40 @@
1 1
 module Day7.Interpreter (
2 2
   buildTree,
3 3
   mkdir,
4
-  Directory (..),
4
+  FileTree (..),
5
+  Directory,
5 6
   calculateSize,
6 7
   filterDirectories,
7 8
   sizeOfDirectories,
8
-  sumUp,
9 9
 ) where
10 10
 
11 11
 import Day7.Parser
12 12
 import Data.Map (Map)
13 13
 import qualified Data.Map as Map
14
+import qualified Data.Foldable as F
14 15
 
15
-data Directory = Directory
16
-  { sub :: Map String Directory
17
-  , files :: Map String Int
16
+
17
+data FileTree a = FileTree
18
+  { sub :: Map String (FileTree a)
19
+  , files :: Map String a
18 20
   , isRoot :: Bool
19 21
 } deriving (Eq)
20 22
 
23
+-- Directory is a FileTree with file sizes of Int
24
+type Directory = FileTree Int
25
+
26
+-- pretty much only useful for summing up file sizes 
27
+instance F.Foldable FileTree where
28
+  foldMap f dir = foldMap f (files dir) <> mconcat mappedSubfolders
29
+    where
30
+      subFolders = Map.elems $ sub dir
31
+      mappedSubfolders = map (foldMap f) subFolders
21 32
 
22
-instance Show Directory where
33
+instance Show a => Show (FileTree a) where
23 34
   show d = "DIR " ++ show (Map.toList $ files d) ++ " - " ++ show (Map.toList $ sub d) ++ "\n"
24 35
 
25 36
 mkdir :: Directory
26
-mkdir = Directory { sub = Map.empty, files = Map.empty, isRoot = False }
37
+mkdir = FileTree { sub = Map.empty, files = Map.empty, isRoot = False }
27 38
 
28 39
 rootDirectory :: Directory
29 40
 rootDirectory = mkdir { isRoot = True  }
@@ -57,24 +68,14 @@ toFiles (_:rest) = toFiles rest
57 68
 toFiles [] = []
58 69
 
59 70
 calculateSize :: Directory -> Int
60
-calculateSize dir = sum (Map.elems (files dir)) + sum sizes
61
-  where
62
-    subFolders = Map.elems (sub dir)
63
-    sizes = map calculateSize subFolders
71
+calculateSize = F.foldl' (+) 0
64 72
 
65
-flatten :: Directory -> [(String, Directory)]
66
-flatten dir = flatten' ("/", dir)
67
-  where
68
-  flatten' (name, d) = (name, d) : concatMap flatten' (Map.toList (sub d))
73
+flatten :: Directory -> [Directory]
74
+flatten d = d : concatMap flatten (Map.elems (sub d))
69 75
 
70
-sizeOfDirectories :: Directory -> [(String, Int)]
71
-sizeOfDirectories dir = map withSize allDirectories
72
-  where
73
-    allDirectories = flatten dir
74
-    withSize (name, directory) = (name, calculateSize directory)
76
+sizeOfDirectories :: Directory -> [Int]
77
+sizeOfDirectories = map calculateSize . flatten
75 78
 
76
-filterDirectories :: (Int -> Bool) -> Directory -> [(String, Int)]
77
-filterDirectories predicate dir = filter (\(_, size) -> predicate size) $ sizeOfDirectories dir
79
+filterDirectories :: (Int -> Bool) -> Directory -> [Int]
80
+filterDirectories predicate dir = filter predicate $ sizeOfDirectories dir
78 81
 
79
-sumUp :: [(String, Int)] -> Int
80
-sumUp = sum . map snd

+ 1
- 1
src/Day7/Parser.hs Wyświetl plik

@@ -18,7 +18,7 @@ data ListingEntry = DirListing DirName | FileListing FileName Size
18 18
 
19 19
 data TerminalCommand = In DirName | Out | Root | Listing [ListingEntry]
20 20
  deriving (Show, Eq)
21
- 
21
+
22 22
 parseTerminalLines :: String -> Either ParseError  [TerminalCommand]
23 23
 parseTerminalLines = parse terminal "(error)"
24 24
 

+ 1
- 1
test/Day7Spec.hs Wyświetl plik

@@ -126,5 +126,5 @@ spec =
126 126
            let parsed = forceRight $ parseTerminalLines inputPart1
127 127
            let tree = buildTree parsed
128 128
            let filtered = filterDirectories (<= 100000) tree
129
-           let summed = sumUp filtered
129
+           let summed = sum filtered
130 130
            summed `shouldBe` 95437

Ładowanie…
Anuluj
Zapisz