Day16
Copyright(c) Eric Mertens 2021
LicenseISC
Maintaineremertens@gmail.com
Safe HaskellNone
LanguageHaskell2010

Main

Description

https://adventofcode.com/2021/day/16

Decode an expression from a bitstream.

This solution uses the ReadP parser combinator module. Since ReadP only operates on String parsing bits is simulated by parsing strings of the characters '0' and '1'. ReadP's gather operation is useful for computing the bitsize of a packet which comes up in some of the operator packets.

Examples

>>> vers <$> parse (decodeHex "8A004A801A8002F478")
Just 16
>>> vers <$> parse (decodeHex "620080001611562C8802118E34")
Just 12
>>> vers <$> parse (decodeHex "C0015000016115A2E0802F182340")
Just 23
>>> vers <$> parse (decodeHex "A0016C880162017C3686B18A3D4780")
Just 31
>>> eval <$> parse (decodeHex "C200B40A82")
Just 3
>>> eval <$> parse (decodeHex "04005AC33890")
Just 54
>>> eval <$> parse (decodeHex "880086C3E88112")
Just 7
>>> eval <$> parse (decodeHex "CE00C43D881120")
Just 9
>>> eval <$> parse (decodeHex "D8005AC2A8F0")
Just 1
>>> eval <$> parse (decodeHex "F600BC2D8F")
Just 0
>>> eval <$> parse (decodeHex "9C005AC2F8F0")
Just 0
>>> eval <$> parse (decodeHex "9C0141080250320F1802104A08")
Just 1
Synopsis

Documentation

main :: IO () Source #

>>> :main
843
5390807940351

data Packet Source #

A BITS packet

Constructors

Lit Int Int

Literal with version and value

Op Int Int [Packet]

Operator with version, opcode, and arguments

vers :: Packet -> Int Source #

Compute the sum of the versions of all nested packets

eval :: Packet -> Int Source #

Evaluate the packet as an expression

parse :: String -> Maybe Packet Source #

Parser for strings of '1' and '0' to Packet

>>> parse "110100101111111000101000"
Just (Lit 6 2021)
>>> parse "00111000000000000110111101000101001010010001001000000000"
Just (Op 1 6 [Lit 6 10,Lit 2 20])
>>> parse "11101110000000001101010000001100100000100011000001100000"
Just (Op 7 3 [Lit 2 1,Lit 4 2,Lit 1 3])

decodeHex :: String -> String Source #

Decode a hex string into bit string

>>> decodeHex "D2FE28"
"110100101111111000101000"
>>> decodeHex "38006F45291200"
"00111000000000000110111101000101001010010001001000000000"

ReadP parser combinators

pPacket :: ReadP Packet Source #

Parse a single packet

field Source #

Arguments

:: Int

bit width

-> ReadP Int 

Parse an n-bit fixed-width big-endian, binary number

flag :: ReadP Bool Source #

Parse a single bit as a boolean flag

pLiteral :: ReadP Int Source #

Parse a variable-sized number in 4-bit chunks

pArguments :: ReadP [Packet] Source #

Parse a list of sub-packets either by packet count or bit-size

pSized Source #

Arguments

:: Int

bit width

-> ReadP [Packet] 

Parse a list of packets that fit exactly in n bits