Просмотр исходного кода

Day 7 Cleanup and modularisation

main
Jens Kadenbach 2 лет назад
Родитель
Сommit
7f4a4329b0
5 измененных файлов: 92 добавлений и 83 удалений
  1. 2
    0
      aoc2022.cabal
  2. 2
    78
      src/Day7.hs
  3. 80
    0
      src/Day7/Interpreter.hs
  4. 6
    0
      src/Shared.hs
  5. 2
    5
      test/Day7Spec.hs

+ 2
- 0
aoc2022.cabal Просмотреть файл

@@ -45,8 +45,10 @@ library
45 45
       Day5.Shared
46 46
       Day6
47 47
       Day7
48
+      Day7.Interpreter
48 49
       Day7.Parser
49 50
       Lib
51
+      Shared
50 52
   other-modules:
51 53
       Paths_aoc2022
52 54
   hs-source-dirs:

+ 2
- 78
src/Day7.hs Просмотреть файл

@@ -1,86 +1,10 @@
1 1
 module Day7 (
2
-  buildTree,
3
-  buildTree',
4
-  mkdir,
5
-  Directory (..),
6
-  calculateSize,
7
-  filterDirectories,
8
-  sumUp,
9 2
   day7
10 3
 ) where
11 4
 
12 5
 import Day7.Parser
13
-import Data.Map (Map)
14
-import qualified Data.Map as Map
15
-
16
-data Directory = Directory
17
-  { sub :: Map String Directory
18
-  , files :: Map String Int
19
-  , isRoot :: Bool
20
-} deriving (Eq)
21
-
22
-
23
-instance Show Directory where
24
-  show d = show (files d) ++ " - " ++ show (sub d) ++ "\n"
25
-
26
-mkdir :: Directory
27
-mkdir = Directory { sub = Map.empty, files = Map.empty, isRoot = False }
28
-
29
-rootDirectory :: Directory
30
-rootDirectory = Directory { sub = Map.empty, files = Map.empty, isRoot = True  }
31
-
32
-buildTree :: [TerminalCommand] -> Directory
33
-buildTree commands = fst (buildTree' rootDirectory commands)
34
-
35
-buildTree' :: Directory -> [TerminalCommand] -> (Directory, [TerminalCommand])
36
-buildTree'  dir [] = (dir, [])
37
-buildTree' dir (command:cs) =  case command of
38
-  Listing entries ->
39
-    let asFiles = Map.fromList $ toFiles entries
40
-        newDir = dir { files = asFiles }
41
-    in buildTree' newDir cs
42
-  In dirName ->
43
-   let subFolders = sub dir
44
-       selectedDir = Map.findWithDefault mkdir  dirName subFolders
45
-       (replacement, rest) = buildTree' selectedDir cs
46
-       updatedSub = Map.insert dirName replacement subFolders
47
-   in buildTree' dir { sub = updatedSub} rest
48
-  Out -> (dir, cs)
49
-  Root -> if isRoot dir
50
-            then buildTree' dir cs
51
-            else (dir, command:cs)
52
-
53
-toFiles :: [ListingEntry] -> [(String, Int)]
54
-toFiles ((FileListing name size):rest) = (name, size): toFiles rest
55
-toFiles (_:rest) = toFiles rest
56
-toFiles [] = []
57
-
58
-calculateSize :: Directory -> Int
59
-calculateSize dir = sum (Map.elems (files dir)) + sum sizes
60
-  where
61
-    subFolders = Map.elems (sub dir)
62
-    sizes = map calculateSize subFolders
63
-
64
-flatten :: Directory -> [(String, Directory)]
65
-flatten dir = flatten' ("/", dir)
66
-  where
67
-  flatten' (name, d) = (name, d) : concatMap flatten' (Map.toList (sub d))
68
-
69
-sizeOfDirectories :: Directory -> [(String, Int)]
70
-sizeOfDirectories dir = map withSize allDirectories
71
-  where
72
-    allDirectories = flatten dir
73
-    withSize (name, directory) = (name, calculateSize directory)
74
-
75
-filterDirectories :: (Int -> Bool) -> Directory -> [(String, Int)]
76
-filterDirectories predicate dir = filter (\(_, size) -> predicate size) $ sizeOfDirectories dir
77
-
78
-sumUp :: [(String, Int)] -> Int
79
-sumUp = sum . map snd
80
-
81
-forceRight :: Either a b -> b
82
-forceRight (Left _) = error "forced Right but got Left"
83
-forceRight (Right b) = b
6
+import Day7.Interpreter
7
+import Shared
84 8
 
85 9
 day7 :: IO ()
86 10
 day7 = do

+ 80
- 0
src/Day7/Interpreter.hs Просмотреть файл

@@ -0,0 +1,80 @@
1
+module Day7.Interpreter (
2
+  buildTree,
3
+  mkdir,
4
+  Directory (..),
5
+  calculateSize,
6
+  filterDirectories,
7
+  sizeOfDirectories,
8
+  sumUp,
9
+) where
10
+
11
+import Day7.Parser
12
+import Data.Map (Map)
13
+import qualified Data.Map as Map
14
+
15
+data Directory = Directory
16
+  { sub :: Map String Directory
17
+  , files :: Map String Int
18
+  , isRoot :: Bool
19
+} deriving (Eq)
20
+
21
+
22
+instance Show Directory where
23
+  show d = "DIR " ++ show (Map.toList $ files d) ++ " - " ++ show (Map.toList $ sub d) ++ "\n"
24
+
25
+mkdir :: Directory
26
+mkdir = Directory { sub = Map.empty, files = Map.empty, isRoot = False }
27
+
28
+rootDirectory :: Directory
29
+rootDirectory = mkdir { isRoot = True  }
30
+
31
+buildTree :: [TerminalCommand] -> Directory
32
+buildTree commands = fst (buildTree' rootDirectory commands)
33
+  where
34
+  -- executes terminal commands and returns all remaining commands
35
+  buildTree' :: Directory -> [TerminalCommand] -> (Directory, [TerminalCommand])
36
+  buildTree'  dir [] = (dir, [])
37
+  buildTree' dir (command:cs) =  case command of
38
+    Listing entries ->
39
+      let asFiles = Map.fromList $ toFiles entries
40
+          newDir = dir { files = asFiles }
41
+      in buildTree' newDir cs -- update current directory and return all remaining commands
42
+    In dirName ->
43
+     let subFolders = sub dir
44
+         selectedDir = Map.findWithDefault mkdir dirName subFolders -- select or create folder
45
+         (replacement, rest) = buildTree' selectedDir cs -- recurse down
46
+         updatedSub = Map.insert dirName replacement subFolders -- update folder the map of the current directory
47
+     in buildTree' dir { sub = updatedSub} rest -- continue with updated folder and rest of commands
48
+    Out -> (dir, cs) -- return to previous caller and return all remaining commands
49
+    Root -> if isRoot dir
50
+              then buildTree' dir cs -- return to previous caller as long is current directory is not root
51
+              else (dir, command:cs) -- keep the Root command because it is not yet completed
52
+
53
+-- convert to file-pairs and ignore directories
54
+toFiles :: [ListingEntry] -> [(String, Int)]
55
+toFiles ((FileListing name size):rest) = (name, size): toFiles rest
56
+toFiles (_:rest) = toFiles rest
57
+toFiles [] = []
58
+
59
+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
64
+
65
+flatten :: Directory -> [(String, Directory)]
66
+flatten dir = flatten' ("/", dir)
67
+  where
68
+  flatten' (name, d) = (name, d) : concatMap flatten' (Map.toList (sub d))
69
+
70
+sizeOfDirectories :: Directory -> [(String, Int)]
71
+sizeOfDirectories dir = map withSize allDirectories
72
+  where
73
+    allDirectories = flatten dir
74
+    withSize (name, directory) = (name, calculateSize directory)
75
+
76
+filterDirectories :: (Int -> Bool) -> Directory -> [(String, Int)]
77
+filterDirectories predicate dir = filter (\(_, size) -> predicate size) $ sizeOfDirectories dir
78
+
79
+sumUp :: [(String, Int)] -> Int
80
+sumUp = sum . map snd

+ 6
- 0
src/Shared.hs Просмотреть файл

@@ -0,0 +1,6 @@
1
+module Shared(forceRight) where
2
+
3
+forceRight :: Either a b -> b
4
+forceRight (Left _) = error "forced Right but got Left"
5
+forceRight (Right b) = b
6
+

+ 2
- 5
test/Day7Spec.hs Просмотреть файл

@@ -4,8 +4,9 @@ module Day7Spec (spec) where
4 4
 import Test.Hspec
5 5
 import Text.Heredoc
6 6
 
7
-import Day7
7
+import Shared
8 8
 import Day7.Parser
9
+import Day7.Interpreter
9 10
 import qualified Data.Map as Map
10 11
 
11 12
 inputPart1 :: String
@@ -72,10 +73,6 @@ cdOutParsed = [
72 73
     Listing [FileListing "f" 23, DirListing "foo", DirListing "bar"]
73 74
   ]
74 75
 
75
-forceRight :: Either a b -> b
76
-forceRight (Left _) = error "forced Right but got Left"
77
-forceRight (Right b) = b
78
-
79 76
 spec :: Spec
80 77
 spec =
81 78
   describe "Day7" $ do

Загрузка…
Отмена
Сохранить