142 lines
3.2 KiB
PHP
142 lines
3.2 KiB
PHP
|
<?php
|
||
|
$input_file = '../inputs/day12.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
|
||
|
{
|
||
|
$state = new day12_state();
|
||
|
|
||
|
foreach (parse_instructions($instructions) as $instruction) {
|
||
|
$state = move($instruction, $state);
|
||
|
}
|
||
|
|
||
|
return abs($state->v_pos) + abs($state->h_pos);
|
||
|
}
|
||
|
|
||
|
function solve_part_two(array $instructions): int
|
||
|
{
|
||
|
$state = new day12_state();
|
||
|
|
||
|
foreach (parse_instructions($instructions) as $instruction)
|
||
|
$state = move_with_waypoint($instruction, $state);
|
||
|
|
||
|
return abs($state->v_pos) + abs($state->h_pos);
|
||
|
}
|
||
|
|
||
|
function move(array $instruction, day12_state $state): day12_state
|
||
|
{
|
||
|
switch ($instruction[0]) {
|
||
|
case 'N':
|
||
|
$state->v_pos += $instruction[1];
|
||
|
break;
|
||
|
case 'S':
|
||
|
$state->v_pos -= +$instruction[1];
|
||
|
break;
|
||
|
case 'E':
|
||
|
$state->h_pos += $instruction[1];
|
||
|
break;
|
||
|
case 'W':
|
||
|
$state->h_pos -= $instruction[1];
|
||
|
break;
|
||
|
case 'F':
|
||
|
switch ($state->facing_direction % 4) {
|
||
|
case 0:
|
||
|
$state->v_pos += $instruction[1];
|
||
|
break;
|
||
|
case 1:
|
||
|
$state->h_pos += $instruction[1];
|
||
|
break;
|
||
|
case 2:
|
||
|
$state->v_pos -= $instruction[1];
|
||
|
break;
|
||
|
case 3:
|
||
|
$state->h_pos -= $instruction[1];
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case 'R':
|
||
|
$state->facing_direction += ($instruction[1] / 90);
|
||
|
break;
|
||
|
case 'L':
|
||
|
$state->facing_direction -= ($instruction[1] / 90);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ($state->facing_direction < 0)
|
||
|
$state->facing_direction += 4; // NOT THAT EASY, need to wrap around 0
|
||
|
|
||
|
return $state;
|
||
|
}
|
||
|
|
||
|
function move_with_waypoint(array $instruction, day12_state $state): day12_state
|
||
|
{
|
||
|
switch ($instruction[0]) {
|
||
|
case 'N':
|
||
|
$state->w_v_pos += $instruction[1];
|
||
|
break;
|
||
|
case 'S':
|
||
|
$state->w_v_pos -= +$instruction[1];
|
||
|
break;
|
||
|
case 'E':
|
||
|
$state->w_h_pos += $instruction[1];
|
||
|
break;
|
||
|
case 'W':
|
||
|
$state->w_h_pos -= $instruction[1];
|
||
|
break;
|
||
|
case 'F':
|
||
|
for ($i = 0; $i < $instruction[1]; $i++) {
|
||
|
$state->v_pos += $state->w_v_pos;
|
||
|
$state->h_pos += $state->w_h_pos;
|
||
|
}
|
||
|
break;
|
||
|
case 'R':
|
||
|
for ($i = 0; $i < $instruction[1] / 90; $i++) {
|
||
|
$new_v_pos = -$state->w_h_pos;
|
||
|
$new_h_pos = $state->w_v_pos;
|
||
|
$state->w_v_pos = $new_v_pos;
|
||
|
$state->w_h_pos = $new_h_pos;
|
||
|
}
|
||
|
break;
|
||
|
case 'L':
|
||
|
for ($i = 0; $i < $instruction[1] / 90; $i++) {
|
||
|
$new_v_pos = $state->w_h_pos;
|
||
|
$new_h_pos = -$state->w_v_pos;
|
||
|
$state->w_v_pos = $new_v_pos;
|
||
|
$state->w_h_pos = $new_h_pos;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return $state;
|
||
|
}
|
||
|
|
||
|
function parse_instructions(array $instructions): array
|
||
|
{
|
||
|
$parsed_instructions = [];
|
||
|
|
||
|
foreach ($instructions as $instruction) {
|
||
|
if (preg_match('/^([NSEWLRF])(\d+)$/', trim($instruction), $matches)) {
|
||
|
[, $inst, $arg] = $matches;
|
||
|
$parsed_instructions[] = [$inst, $arg];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $parsed_instructions;
|
||
|
}
|
||
|
|
||
|
class day12_state
|
||
|
{
|
||
|
public int $v_pos = 0;
|
||
|
public int $h_pos = 0;
|
||
|
public int $w_v_pos = 1;
|
||
|
public int $w_h_pos = 10;
|
||
|
public int $facing_direction = 1; // N = 0, E = 1, S = 2, W = 3
|
||
|
}
|