-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path07.hs
64 lines (48 loc) · 2.14 KB
/
07.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import Data.List
import Lib
type Filename = String
type Filesize = Int
data File = Dir Filename | File Filename Filesize deriving (Show)
data Command = Cd String | Ls [File] deriving (Show)
data FileTree = TreeDir Filesize [FileTree] | TreeFile Filesize deriving (Show)
type Input = [Int]
main :: IO ()
main = aoc 2022 7 setup solve1 solve2 ["1"]
solve1 :: Input -> Int
solve1 = sum . filter (<= 100000)
solve2 :: Input -> Int
solve2 dirs = minimum $ filter (>= 30000000 - 70000000 + head dirs) dirs
setup :: String -> Input
setup = flattenTree . (: []) . buildTree . collectFiles [] . parseCommands . lines
parseCommands :: [String] -> [Command]
parseCommands [] = []
parseCommands (x : xs)
| "$ cd" `isPrefixOf` x = Cd (drop 5 x) : parseCommands xs
| "$ ls" `isPrefixOf` x = Ls (map parseFile $ takeWhile inLs xs) : parseCommands (dropWhile inLs xs)
where
inLs = not . isPrefixOf "$"
parseFile :: String -> File
parseFile ('d' : 'i' : 'r' : ' ' : x) = Dir x
parseFile x = File (drop 1 $ dropWhile (/= ' ') x) (read $ takeWhile (/= ' ') x)
collectFiles :: [Filename] -> [Command] -> [([String], Int)]
collectFiles path [] = []
collectFiles path (Cd "/" : xs) = collectFiles [] xs
collectFiles [] (Cd ".." : xs) = collectFiles [] xs
collectFiles path (Cd ".." : xs) = collectFiles (init path) xs
collectFiles path (Cd name : xs) = collectFiles (path ++ [name]) xs
collectFiles path (Ls x : xs) = [(path ++ [name], size) | (File name size) <- x] ++ collectFiles path xs
buildTree :: [([String], Int)] -> FileTree
buildTree xs = TreeDir (treeSize $ dirs ++ files) $ dirs ++ files
where
files = [TreeFile size | ([name], size) <- xs]
dirNames = nub [name | (name : _ : _, _) <- xs]
dirEntries dir = [(ps, size) | (p : ps, size) <- xs, p == dir]
dirs = [buildTree $ dirEntries name | name <- dirNames]
treeSize :: [FileTree] -> Int
treeSize [] = 0
treeSize ((TreeDir size entries) : xs) = treeSize entries + treeSize xs
treeSize ((TreeFile size) : xs) = size + treeSize xs
flattenTree :: [FileTree] -> [Int]
flattenTree [] = []
flattenTree (TreeDir size entries : xs) = size : (flattenTree entries ++ flattenTree xs)
flattenTree (_ : xs) = flattenTree xs