In [1]:
inputLines = lines <$> readFile "input/day9.txt"
In [2]:
decompressedLength :: Bool -> String -> Int
decompressedLength recursive xs = decompressedLength' xs
where
-- getSequenceLength determines the (decompressed) length of the sequence after a marker.
getSequenceLength :: String -> Int
getSequenceLength = if recursive then decompressedLength' else length
-- It seems that there are currently no Haskell modules for regular expressions in
-- ihaskell, so we parse the markers manually.
decompressedLength' "" = 0
decompressedLength' ('(':xs) = parseSequenceLength xs
decompressedLength' xs = length beforeMarker + decompressedLength' rest
where (beforeMarker, rest) = span (/= '(') xs
-- The beginning of ys is the length declaration inside a marker.
-- Parse it and continue processing.
parseSequenceLength :: String -> Int
parseSequenceLength ys = parseCount (read markerLength) $ tail rest
where
(markerLength, rest) = span (/= 'x') ys
-- The beginning of ys is the repeat count declaration inside a marker.
-- Parse it and continue processing.
parseCount :: Int -> String -> Int
parseCount markerLength ys = parseSequence markerLength (read markerCount) $ tail rest
where
(markerCount, rest) = span (/= ')') ys
-- The beginning of ys is the string after the marker. Calculate the total decompressed
-- length of the marker and add the decompressed length of the remainder.
parseSequence :: Int -> Int -> String -> Int
parseSequence markerLength markerCount ys =
markerCount * getSequenceLength zs + decompressedLength' rest
where
(zs, rest) = splitAt markerLength ys
In [3]:
decompressedLength1 = decompressedLength False
In [4]:
-- Verify the given expample results.
decompressedLength1 "ADVENT"
decompressedLength1 "A(1x5)BC"
decompressedLength1 "(3x3)XYZ"
decompressedLength1 "A(2x2)BCD(2x2)EFG"
decompressedLength1 "(6x1)(1x3)A"
decompressedLength1 "X(8x2)(3x3)ABCY"
In [5]:
decompressedLength1 . head <$> inputLines
In [6]:
decompressedLength2 = decompressedLength True
In [7]:
-- Verify the given expample results.
decompressedLength2 "(3x3)XYZ"
decompressedLength2 "X(8x2)(3x3)ABCY"
decompressedLength2 "(27x12)(20x12)(13x14)(7x10)(1x12)A"
decompressedLength2 "(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN"
In [8]:
decompressedLength2 . head <$> inputLines