mirror of
https://codeberg.org/JasterV/aoc2024-haskell.git
synced 2026-04-27 02:15:43 +00:00
day9 part two
This commit is contained in:
parent
ce45f19638
commit
f886c73c42
2 changed files with 32 additions and 8 deletions
38
src/Day9.hs
38
src/Day9.hs
|
|
@ -13,6 +13,7 @@ data Block = FileBlock Position FileId | FreeBlock Position
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data Object = File Position Space FileId | FreeSpace Position Space
|
data Object = File Position Space FileId | FreeSpace Position Space
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
partOne :: String -> Int
|
partOne :: String -> Int
|
||||||
partOne input = calculateCheckSum compactFiles
|
partOne input = calculateCheckSum compactFiles
|
||||||
|
|
@ -28,32 +29,55 @@ partOne input = calculateCheckSum compactFiles
|
||||||
| lIndex > rIndex = reverse acc
|
| lIndex > rIndex = reverse acc
|
||||||
| otherwise = case (lBlock, rBlock) of
|
| otherwise = case (lBlock, rBlock) of
|
||||||
(FileBlock _ _, _) -> go xs (rBlock : ys) (lBlock : acc)
|
(FileBlock _ _, _) -> go xs (rBlock : ys) (lBlock : acc)
|
||||||
(FreeBlock _, FileBlock _ _) -> go xs ys (rBlock : acc)
|
(FreeBlock lPos, FileBlock _ fId) -> go xs ys (FileBlock lPos fId : acc)
|
||||||
(FreeBlock _, FreeBlock _) -> go (lBlock : xs) ys acc
|
(FreeBlock _, FreeBlock _) -> go (lBlock : xs) ys acc
|
||||||
where
|
where
|
||||||
lIndex = getBlockPosition lBlock
|
lIndex = getBlockPosition lBlock
|
||||||
rIndex = getBlockPosition rBlock
|
rIndex = getBlockPosition rBlock
|
||||||
|
|
||||||
partTwo :: String -> Int
|
partTwo :: String -> Int
|
||||||
partTwo _ = 0
|
partTwo input = calculateCheckSum $ concatMap getBlocks compactFiles
|
||||||
|
where
|
||||||
|
objects = parseDisk input
|
||||||
|
|
||||||
|
compactFiles :: [Object]
|
||||||
|
compactFiles = go (reverse objects)
|
||||||
|
where
|
||||||
|
go [] = []
|
||||||
|
go ((FreeSpace _ _) : ys) = go ys
|
||||||
|
go (file@(File pos space fId) : ys) =
|
||||||
|
let mYs = replaceLeftMostSpace (reverse ys) (pos, space, fId)
|
||||||
|
in case mYs of
|
||||||
|
Nothing -> go ys ++ [file]
|
||||||
|
Just ys' -> go $ reverse ys'
|
||||||
|
|
||||||
|
replaceLeftMostSpace :: [Object] -> (Position, Space, FileId) -> Maybe [Object]
|
||||||
|
replaceLeftMostSpace [] _ = Nothing
|
||||||
|
replaceLeftMostSpace (left : xs) right@(_, rSpace, fId) =
|
||||||
|
case left of
|
||||||
|
(File {}) -> (left :) <$> replaceLeftMostSpace xs right
|
||||||
|
(FreeSpace lPos lSpace)
|
||||||
|
| lSpace == rSpace -> Just (File lPos rSpace fId : xs)
|
||||||
|
| lSpace > rSpace -> Just (File lPos rSpace fId : FreeSpace (lPos + rSpace) (lSpace - rSpace) : xs)
|
||||||
|
| otherwise -> (left :) <$> replaceLeftMostSpace xs right
|
||||||
|
|
||||||
-- Blocks & Objects
|
-- Blocks & Objects
|
||||||
|
|
||||||
calculateCheckSum :: [Block] -> Int
|
calculateCheckSum :: [Block] -> Int
|
||||||
calculateCheckSum blocks = sum $ zipWith ((*) . fromMaybe 0 . getFileId) blocks [0 ..]
|
calculateCheckSum blocks = sum $ mapMaybe blockCheckSum blocks
|
||||||
|
|
||||||
getBlocks :: Object -> [Block]
|
getBlocks :: Object -> [Block]
|
||||||
getBlocks (File position space fileId) = map (`FileBlock` fileId) [position .. (position + space - 1)]
|
getBlocks (File position space fileId) = map (`FileBlock` fileId) [position .. (position + space - 1)]
|
||||||
getBlocks (FreeSpace position space) = map FreeBlock [position .. (position + space - 1)]
|
getBlocks (FreeSpace position space) = map FreeBlock [position .. (position + space - 1)]
|
||||||
|
|
||||||
getFileId :: Block -> Maybe FileId
|
|
||||||
getFileId (FileBlock _ fileId) = Just fileId
|
|
||||||
getFileId _ = Nothing
|
|
||||||
|
|
||||||
getBlockPosition :: Block -> Position
|
getBlockPosition :: Block -> Position
|
||||||
getBlockPosition (FileBlock pos _) = pos
|
getBlockPosition (FileBlock pos _) = pos
|
||||||
getBlockPosition (FreeBlock pos) = pos
|
getBlockPosition (FreeBlock pos) = pos
|
||||||
|
|
||||||
|
blockCheckSum :: Block -> Maybe Int
|
||||||
|
blockCheckSum (FileBlock pos fileId) = Just (pos * fileId)
|
||||||
|
blockCheckSum _ = Nothing
|
||||||
|
|
||||||
-- Parsing
|
-- Parsing
|
||||||
|
|
||||||
data ParseStep = ParseFile | ParseFree
|
data ParseStep = ParseFile | ParseFree
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@ spec = do
|
||||||
partOne input `shouldBe` 1928
|
partOne input `shouldBe` 1928
|
||||||
describe "PartTwo" $ do
|
describe "PartTwo" $ do
|
||||||
it "works" $ do
|
it "works" $ do
|
||||||
partTwo input `shouldBe` 0
|
partTwo input `shouldBe` 2858
|
||||||
where
|
where
|
||||||
input = "2333133121414131402"
|
input = "2333133121414131402"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue