109 lines
2.3 KiB
PHP
109 lines
2.3 KiB
PHP
|
<?php
|
||
|
|
||
|
use JetBrains\PhpStorm\Pure;
|
||
|
|
||
|
$input_file = '../inputs/day8.txt';
|
||
|
if (file_exists($input_file)) {
|
||
|
$input = file_get_contents($input_file);
|
||
|
if ($input != null) {
|
||
|
$instructions = 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
|
||
|
{
|
||
|
return get_acc(parse_instructions($instructions));
|
||
|
}
|
||
|
|
||
|
function solve_part_two(array $instructions): int
|
||
|
{
|
||
|
$original_instructions = parse_instructions($instructions);
|
||
|
|
||
|
foreach ($original_instructions as $idx => $instruction) {
|
||
|
$altered_instructions = $original_instructions;
|
||
|
switch ($instruction[0]) {
|
||
|
case 'jmp':
|
||
|
$altered_instructions[$idx][0] = 'nop';
|
||
|
break;
|
||
|
case 'nop':
|
||
|
$altered_instructions[$idx][0] = 'jmp';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (terminates_correctly($altered_instructions))
|
||
|
return get_acc($altered_instructions);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#[Pure] function terminates_correctly(array $instructions): bool
|
||
|
{
|
||
|
$acc = 0;
|
||
|
$ip = 0;
|
||
|
$execution_count = [];
|
||
|
|
||
|
while ($ip < count($instructions)) {
|
||
|
if (array_key_exists($ip, $execution_count) && $execution_count[$ip] != 0)
|
||
|
return false;
|
||
|
$execution_count[$ip] = 1;
|
||
|
[$acc, $ip] = run_instruction($instructions[$ip], [$acc, $ip]);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#[Pure] function get_acc(array $instructions): int
|
||
|
{
|
||
|
$acc = 0;
|
||
|
$ip = 0;
|
||
|
$execution_count = [];
|
||
|
|
||
|
while ($ip < count($instructions)) {
|
||
|
if (array_key_exists($ip, $execution_count) && $execution_count[$ip] != 0)
|
||
|
return $acc;
|
||
|
$execution_count[$ip] = 1;
|
||
|
[$acc, $ip] = run_instruction($instructions[$ip], [$acc, $ip]);
|
||
|
}
|
||
|
|
||
|
return $acc;
|
||
|
}
|
||
|
|
||
|
function run_instruction(array $instruction, array $regs): array
|
||
|
{
|
||
|
[$inst, $arg] = $instruction;
|
||
|
[$acc, $ip] = $regs;
|
||
|
switch ($inst) {
|
||
|
case 'acc':
|
||
|
$acc += $arg;
|
||
|
$ip += 1;
|
||
|
break;
|
||
|
case 'jmp':
|
||
|
$ip += $arg;
|
||
|
break;
|
||
|
case 'nop':
|
||
|
$ip += 1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// print 'Executed ' . $inst . ', $acc = ' . $acc . ', $ip = ' . $ip . "\n";
|
||
|
|
||
|
return [$acc, $ip];
|
||
|
}
|
||
|
|
||
|
function parse_instructions(array $instructions): array
|
||
|
{
|
||
|
$parsed_instructions = [];
|
||
|
|
||
|
foreach ($instructions as $instruction) {
|
||
|
if (preg_match('/^(acc|jmp|nop) ([+\-\d]+)$/', trim($instruction), $matches)) {
|
||
|
[, $inst, $arg] = $matches;
|
||
|
$parsed_instructions[] = [$inst, $arg];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $parsed_instructions;
|
||
|
}
|