89 lines
2.2 KiB
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;
|
|
}
|