Skip to content

Commit ce45f19

Browse files
committed
refactor Day9
1 parent a881f45 commit ce45f19

File tree

1 file changed

+49
-23
lines changed

1 file changed

+49
-23
lines changed

src/Day9.hs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,71 @@
11
module Day9 (partOne, partTwo) where
22

33
import Data.Char (digitToInt, isDigit)
4+
import Data.Maybe
45

56
type FileId = Int
67

7-
data Block = File FileId | Free
8+
type Space = Int
9+
10+
type Position = Int
11+
12+
data Block = FileBlock Position FileId | FreeBlock Position
813
deriving (Show, Eq)
914

15+
data Object = File Position Space FileId | FreeSpace Position Space
16+
1017
partOne :: String -> Int
11-
partOne input = sum $ zipWith (*) [0 ..] $ compactFiles $ parseDisk input
18+
partOne input = calculateCheckSum compactFiles
19+
where
20+
blocks = concatMap getBlocks $ parseDisk input
21+
22+
compactFiles :: [Block]
23+
compactFiles = go blocks (reverse blocks) []
24+
where
25+
go [] _ acc = reverse acc
26+
go _ [] acc = reverse acc
27+
go (lBlock : xs) (rBlock : ys) acc
28+
| lIndex > rIndex = reverse acc
29+
| otherwise = case (lBlock, rBlock) of
30+
(FileBlock _ _, _) -> go xs (rBlock : ys) (lBlock : acc)
31+
(FreeBlock _, FileBlock _ _) -> go xs ys (rBlock : acc)
32+
(FreeBlock _, FreeBlock _) -> go (lBlock : xs) ys acc
33+
where
34+
lIndex = getBlockPosition lBlock
35+
rIndex = getBlockPosition rBlock
1236

1337
partTwo :: String -> Int
1438
partTwo _ = 0
1539

16-
-- Compacting
17-
compactFiles :: [Block] -> [FileId]
18-
compactFiles blocks = go enumeratedBlocks (reverse enumeratedBlocks) []
19-
where
20-
enumeratedBlocks :: [(Int, Block)]
21-
enumeratedBlocks = zip [0 ..] blocks
22-
23-
go [] _ acc = reverse acc
24-
go _ [] acc = reverse acc
25-
go ((lIndex, lBlock) : xs) ((rIndex, rBlock) : ys) acc
26-
| lIndex > rIndex = reverse acc
27-
| otherwise = case (lBlock, rBlock) of
28-
(File fileId, _) -> go xs ((rIndex, rBlock) : ys) (fileId : acc)
29-
(Free, File fileId) -> go xs ys (fileId : acc)
30-
(Free, Free) -> go ((lIndex, lBlock) : xs) ys acc
40+
-- Blocks & Objects
41+
42+
calculateCheckSum :: [Block] -> Int
43+
calculateCheckSum blocks = sum $ zipWith ((*) . fromMaybe 0 . getFileId) blocks [0 ..]
44+
45+
getBlocks :: Object -> [Block]
46+
getBlocks (File position space fileId) = map (`FileBlock` fileId) [position .. (position + space - 1)]
47+
getBlocks (FreeSpace position space) = map FreeBlock [position .. (position + space - 1)]
48+
49+
getFileId :: Block -> Maybe FileId
50+
getFileId (FileBlock _ fileId) = Just fileId
51+
getFileId _ = Nothing
52+
53+
getBlockPosition :: Block -> Position
54+
getBlockPosition (FileBlock pos _) = pos
55+
getBlockPosition (FreeBlock pos) = pos
3156

3257
-- Parsing
3358

3459
data ParseStep = ParseFile | ParseFree
3560

36-
parseDisk :: String -> [Block]
37-
parseDisk input = go (parseInts input) ParseFile 0 []
61+
parseDisk :: String -> [Object]
62+
parseDisk input = go (parseInts input) ParseFile 0 0 []
3863
where
39-
go [] _ _id acc = reverse acc
40-
go (space : xs) _ fileId [] = go xs ParseFree (fileId + 1) (replicate space (File fileId))
41-
go (space : xs) ParseFree fileId acc = go xs ParseFile fileId (replicate space Free ++ acc)
42-
go (space : xs) ParseFile fileId acc = go xs ParseFree (fileId + 1) (replicate space (File fileId) ++ acc)
64+
go :: [Int] -> ParseStep -> FileId -> Position -> [Object] -> [Object]
65+
go [] _ _ _ acc = reverse acc
66+
go (space : xs) _ fileId position [] = go xs ParseFree (fileId + 1) (position + space) [File position space fileId]
67+
go (space : xs) ParseFree fileId position acc = go xs ParseFile fileId (position + space) (FreeSpace position space : acc)
68+
go (space : xs) ParseFile fileId position acc = go xs ParseFree (fileId + 1) (position + space) (File position space fileId : acc)
4369

4470
parseInts :: String -> [Int]
4571
parseInts = map digitToInt . filter isDigit

0 commit comments

Comments
 (0)