Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Parser {
- private string $bits;
- private int $pointer;
- public function __construct(string $bits)
- {
- $this->bits = $bits;
- $this->pointer = 0;
- }
- public function read(int $length): string
- {
- $buffer = substr($this->bits, $this->pointer, $length);
- $this->pointer += $length;
- return $buffer;
- }
- public function parse(): Packet
- {
- $version = bindec($this->read(3));
- $type = bindec($this->read(3));
- if ($type === 4) return new Packet($version, $type, $this);
- return new OpPacket($version, $type, $this);
- }
- public function getPointer(): int
- {
- return $this->pointer;
- }
- }
- class Packet {
- protected int $version;
- protected int $type;
- private string $value;
- public function __construct(int $version, int $type, Parser $parser)
- {
- $this->version = $version;
- $this->type = $type;
- $this->value = '';
- $this->readPacket($parser);
- }
- public function readPacket(Parser $parser): void
- {
- do {
- $flag = $parser->read(1);
- $this->value .= $parser->read(4);
- } while ($flag > 0);
- }
- public function getVersionSum(): int
- {
- return $this->version;
- }
- public function getValue(): int
- {
- return bindec($this->value);
- }
- }
- class OpPacket extends Packet {
- private array $subPackets = [];
- public function readPacket(Parser $parser): void
- {
- $lengthTypeId = intval($parser->read(1));
- if ($lengthTypeId === 1) {
- $qty = bindec($parser->read(11));
- for ($i = 0; $i < $qty; $i++) {
- $this->subPackets[] = $parser->parse();
- }
- } else {
- $length = bindec($parser->read(15));
- $pointer = $parser->getPointer();
- while ($parser->getPointer() - $pointer < $length) {
- $this->subPackets[] = $parser->parse();
- }
- }
- }
- public function getVersionSum(): int
- {
- return $this->version + array_reduce($this->subPackets, fn ($versionSum, Packet $subPacket) => $versionSum + $subPacket->getVersionSum(), 0);
- }
- public function getValue(): int
- {
- $operations = [
- fn ($v) => array_sum($v),
- fn ($v) => array_product($v),
- fn ($v) => min($v),
- fn ($v) => max($v),
- fn ($v) => 0,
- fn ($v) => intval($v[0] > $v[1]),
- fn ($v) => intval($v[0] < $v[1]),
- fn ($v) => intval($v[0] == $v[1])
- ];
- $values = array_reduce($this->subPackets, fn ($values, Packet $subPacket) => array_merge($values, [$subPacket->getValue()]), []);
- return $operations[$this->type]($values);
- }
- }
- $inputs = file_get_contents('input.txt');
- $bits = implode(array_map(fn($char) => str_pad(base_convert($char, 16, 2), 4, '0', STR_PAD_LEFT), str_split($inputs)));
- $parser = new Parser($bits);
- $packet = $parser->parse();
- echo $packet->getVersionSum().PHP_EOL;
- echo $packet->getValue();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement