1
0
Fork 0
advent-of-code/2020/day14.php

89 lines
2.2 KiB
PHP

<?php
$input_file = '../inputs/day14.txt';
if (file_exists($input_file)) {
$input = file_get_contents($input_file);
if ($input != null) {
$instructions = array_map('trim', explode("\n", $input));
print 'Part 1 answer: ' . solve_part_one($instructions) . "\n";
print 'Part 2 answer: ' . solve_part_two($instructions) . "\n";
}
}
function solve_part_one(array $instructions): int
{
$parsed = parse_instructions($instructions);
$mask = '';
$mem = [];
foreach ($parsed as $instruction) {
if ($instruction[0] === 'mask')
$mask = $instruction[1];
else
$mem[$instruction[1]] = apply_mask($mask, $instruction[2]);
}
return array_sum($mem);
}
function solve_part_two(array $instructions): int
{
$parsed = parse_instructions($instructions);
$mask = '';
$mem = [];
foreach ($parsed as $instruction) {
if ($instruction[0] === 'mask')
$mask = $instruction[1];
else {
foreach (apply_mask_two($mask, $instruction[1]) as $address)
$mem[$address] = $instruction[2];
}
}
return array_sum($mem);
}
function apply_mask_two(string $mask, int $num): array
{
$addresses = [''];
$bin = str_pad(decbin($num), 36, '0', STR_PAD_LEFT);
for ($i = 0; $i < strlen($bin); $i++) {
switch ($mask[$i]) {
case '0':
$addresses = array_map(fn ($addr) => $addr . $bin[$i], $addresses);
break;
case '1':
$addresses = array_map(fn ($addr) => $addr . '1', $addresses);
break;
case 'X':
$new_addresses = [];
foreach ($addresses as $address) {
$new_addresses[] = $address . '0';
$new_addresses[] = $address . '1';
}
$addresses = $new_addresses;
break;
}
}
return array_map('bindec', $addresses);
}
function apply_mask(string $mask, int $num): int
{
$bin = str_pad(decbin($num), 36, '0', STR_PAD_LEFT);
for ($i = 0; $i < strlen($bin); $i++)
if ($mask[$i] != 'X')
$bin[$i] = $mask[$i];
return bindec($bin);
}
function parse_instructions(array $instructions): array
{
$parsed_instructions = [];
foreach ($instructions as $instruction) {
[$inst, $arg] = array_map('trim', explode(' = ', $instruction));
if ($inst === 'mask')
$parsed_instructions[] = [$inst, $arg];
else
$parsed_instructions[] = ['mem', substr($inst, 4, strlen($inst) - 5), $arg];
}
return $parsed_instructions;
}