Day 9: Explosives in Cyberspace


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

Part 1: No recursive decompression of markers


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"


6
7
9
11
6
18

In [5]:
decompressedLength1 . head <$> inputLines


99145

Part 2: Decompress markers recursively


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"


9
20
241920
445

In [8]:
decompressedLength2 . head <$> inputLines


10943094568