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

109 lines
2.3 KiB
PHP
Raw Normal View History

2024-02-08 09:55:40 +01:00
<?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;
}