Skip to content

Commit

Permalink
day5part2
Browse files Browse the repository at this point in the history
  • Loading branch information
Hamish Wright committed Dec 21, 2019
1 parent 8de33ab commit 5dbed61
Show file tree
Hide file tree
Showing 15 changed files with 365 additions and 0 deletions.
1 change: 1 addition & 0 deletions inputs/day5/part2/0
@@ -0,0 +1 @@
3,9,8,9,10,9,4,9,99,-1,8
1 change: 1 addition & 0 deletions inputs/day5/part2/1
@@ -0,0 +1 @@
3,9,8,9,10,9,4,9,99,-1,8
1 change: 1 addition & 0 deletions inputs/day5/part2/10
@@ -0,0 +1 @@
3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99
1 change: 1 addition & 0 deletions inputs/day5/part2/11
@@ -0,0 +1 @@
3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99
1 change: 1 addition & 0 deletions inputs/day5/part2/2
@@ -0,0 +1 @@
3,9,8,9,10,9,4,9,99,-1,8
1 change: 1 addition & 0 deletions inputs/day5/part2/3
@@ -0,0 +1 @@
3,9,7,9,10,9,4,9,99,-1,8
1 change: 1 addition & 0 deletions inputs/day5/part2/4
@@ -0,0 +1 @@
3,9,7,9,10,9,4,9,99,-1,8
1 change: 1 addition & 0 deletions inputs/day5/part2/5
@@ -0,0 +1 @@
3,3,1108,-1,8,3,4,3,99
1 change: 1 addition & 0 deletions inputs/day5/part2/6
@@ -0,0 +1 @@
3,3,1108,-1,8,3,4,3,99
1 change: 1 addition & 0 deletions inputs/day5/part2/7
@@ -0,0 +1 @@
3,3,1107,-1,8,3,4,3,99
1 change: 1 addition & 0 deletions inputs/day5/part2/8
@@ -0,0 +1 @@
3,3,1107,-1,8,3,4,3,99
1 change: 1 addition & 0 deletions inputs/day5/part2/9
@@ -0,0 +1 @@
3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99
178 changes: 178 additions & 0 deletions src/day5/ElfComputer3.php
@@ -0,0 +1,178 @@
<?php

namespace PuzzleSolvers\Day5;

use PuzzleSolvers\PuzzleSolver;

class ElfComputer3 extends PuzzleSolver
{
public $program;
public $position;
public $input;
public $outputs;
public $parameterMode;
public $instructionLength = 4;

public function initialise()
{
$this->position = 0;
$this->program = array_map('intval', explode(',', $this->inputs[0]));
$this->outputs = [];
}

public function run()
{
while ($this->position < $this->getProgramSize()) {
$instruction = $this->parseInstruction($this->readMemory());
$this->execute($instruction);
}

$this->output = implode(',', $this->program);
}

public function parseInstruction($instruction)
{
$parsedInstuction = [];
$parsedInstuction['opcode'] = (int) substr($instruction, -2, 2);
$parsedInstuction['mode1'] = (strlen($instruction) > 2) ? (int) substr($instruction, -3, 1) : 0;
$parsedInstuction['mode2'] = (strlen($instruction) > 3) ? (int) substr($instruction, -4, 1) : 0;
$parsedInstuction['mode3'] = (strlen($instruction) > 4) ? (int) substr($instruction, -5, 1) : 0;

return $parsedInstuction;
}

public function getParameter(int $offset, int $mode)
{
$parameter = $this->readMemoryOffset($offset);
if ($mode == 0) {
$parameter = $this->readMemory($parameter);
}

return $parameter;
}

public function execute($instruction)
{
$opcode = $instruction['opcode'];

if ($opcode === 1) {
$parameter1 = $this->getParameter(1, $instruction['mode1']);
$parameter2 = $this->getParameter(2, $instruction['mode2']);
$parameter3 = $this->readMemoryOffset(3);
$value = $parameter1 + $parameter2;
$this->writeMemory($value, $parameter3);
$this->position += 4;
}

else if ($opcode === 2) {
$parameter1 = $this->getParameter(1, $instruction['mode1']);
$parameter2 = $this->getParameter(2, $instruction['mode2']);
$parameter3 = $this->readMemoryOffset(3);
$value = $parameter1 * $parameter2;
$this->writeMemory($value, $parameter3);
$this->position += 4;
}

else if ($opcode == 3) {
$this->writeMemory($this->input, $this->readMemoryOffset(1));
$this->position += 2;
}

else if ($opcode == 4) {
$parameter1 = $this->getParameter(1, $instruction['mode1']);
$this->outputs[] = $parameter1;
$this->position += 2;
}

else if ($opcode == 5) {
$parameter1 = $this->getParameter(1, $instruction['mode1']);
$parameter2 = $this->getParameter(2, $instruction['mode2']);
if ($parameter1 != 0) {
$this->position = $parameter2;
} else {
$this->position += 3;
}
}

else if ($opcode == 6) {
$parameter1 = $this->getParameter(1, $instruction['mode1']);
$parameter2 = $this->getParameter(2, $instruction['mode2']);
if ($parameter1 == 0) {
$this->position = $parameter2;
} else {
$this->position += 3;
}
}

else if ($opcode == 7) {
$parameter1 = $this->getParameter(1, $instruction['mode1']);
$parameter2 = $this->getParameter(2, $instruction['mode2']);
$parameter3 = $this->readMemoryOffset(3);
$value = ($parameter1 < $parameter2) ? 1 : 0;
$this->writeMemory($value, $parameter3);
$this->position += 4;
}

else if ($opcode == 8) {
$parameter1 = $this->getParameter(1, $instruction['mode1']);
$parameter2 = $this->getParameter(2, $instruction['mode2']);
$parameter3 = $this->readMemoryOffset(3);
$value = ($parameter1 == $parameter2) ? 1 : 0;
$this->writeMemory($value, $parameter3);
$this->position += 4;
}

else if ($opcode === 99) {
$this->position = $this->getProgramSize();
} else {
$this->position += 1;
}
}

public function getProgramSize(): int
{
return count($this->program);
}

public function readMemory($position = null)
{
if (is_null($position)) {
$position = $this->position;
}

return $this->program[$position];
}

public function readMemoryOffset($offset = 0)
{
return $this->program[$this->position + $offset];
}

public function writeMemoryOffset(int $value, $offset = 0)
{
$this->program[$this->position + $offset] = $value;
}

public function writeMemory(int $value, $position = null)
{
if (is_null($position)) {
$position = $this->position;
}
$this->program[$position] = $value;
}

public function getProgram(): array
{
return $this->program ?: [];
}

public function getPosition(): int
{
return $this->position ?: 0;
}

public function setPosition(int $position): void
{
$this->position = $position;
}
}
9 changes: 9 additions & 0 deletions src/day5/solve.php
Expand Up @@ -3,6 +3,7 @@
require_once __DIR__ . '/../../vendor/autoload.php';

use PuzzleSolvers\Day5\ElfComputer2;
use PuzzleSolvers\Day5\ElfComputer3;

$elfComputer = new ElfComputer2('day5/part1/input');
$elfComputer->initialise();
Expand All @@ -11,3 +12,11 @@
$outputs = $elfComputer->outputs;

echo "Day 5 Part 1 answer: " . end($outputs) . "\n";

$elfComputer = new ElfComputer3('day5/part1/input');
$elfComputer->initialise();
$elfComputer->input = 5;
$elfComputer->run();
$outputs = $elfComputer->outputs;

echo "Day 5 Part 2 answer: " . end($outputs) . "\n";
166 changes: 166 additions & 0 deletions tests/Day5Part2Test.php
@@ -0,0 +1,166 @@
<?php

use PHPUnit\Framework\TestCase;
use PuzzleSolvers\Day5\ElfComputer3;

final class Day5Part2Test extends TestCase
{
public function testDay2EndToEnd(): void
{
$outputs = [
'3500,9,10,70,2,3,11,0,99,30,40,50',
'2,0,0,0,99',
'2,3,0,6,99',
'2,4,4,5,99,9801',
'30,1,1,4,2,5,6,0,99',
];
foreach ($outputs as $inputFileNumber => $output) {
$puzzleSolver = new ElfComputer3('day2/part1/' . $inputFileNumber);
$puzzleSolver->initialise();
$puzzleSolver->run();
$this->assertSame($output, $puzzleSolver->getOutput());
}
}

public function testInitialiseLoadsInputToProgramAndSetsPositionTo0(): void
{
$elfComputer = new ElfComputer3('day2/part1/0');

$elfComputer->initialise();

$this->assertSame([1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50], $elfComputer->getProgram());
$this->assertSame(0, $elfComputer->getPosition());
}

public function testPart1EndToEnd()
{
$outputs = [
[42, 0, 4, 0, 99],
[1002, 4, 3, 4, 99],
[1101, 100, -1, 4, 99],
];
$programOutput = [
[42],
[],
[],
];
foreach ($outputs as $inputFileNumber => $output) {
$elfComputer = new ElfComputer3('day5/part1/' . $inputFileNumber);
$elfComputer->initialise();
$elfComputer->input = 42;
$elfComputer->run();

$this->assertSame($programOutput[$inputFileNumber], $elfComputer->outputs);
$this->assertSame($outputs[$inputFileNumber], $elfComputer->program);
}
}

public function testEndToEnd()
{
$outputs = [
[0],
[1],
[0],
[0],
[1],
[0],
[1],
[0],
[1],
[999],
[1000],
[1001],
];
$inputs = [
7,
8,
9,
8,
7,
55,
8,
8,
7,
7,
8,
9,
];
foreach ($outputs as $inputFileNumber => $output) {
\PuzzleDebugger::print('TESTING FILE: ' . $inputFileNumber);
$elfComputer = new ElfComputer3('day5/part2/' . $inputFileNumber);
$elfComputer->initialise();
$elfComputer->input = $inputs[$inputFileNumber];
$elfComputer->run();

$this->assertSame($outputs[$inputFileNumber], $elfComputer->outputs);
}
}

public function testReadMemory(): void
{
$elfComputer = new ElfComputer3('day2/part1/0');
$elfComputer->initialise();
$elfComputer->setPosition(1);

$value0 = $elfComputer->readMemory(0);
$this->assertSame(1, $value0);

$value1 = $elfComputer->readMemory();
$this->assertSame(9, $value1);

$value2 = $elfComputer->readMemory(2);
$this->assertSame(10, $value2);
}

public function testReadMemoryOffset(): void
{
$elfComputer = new ElfComputer3('day2/part1/0');
$elfComputer->initialise();
$elfComputer->setPosition(1);

$value1 = $elfComputer->readMemoryOffset(0);
$this->assertSame(9, $value1);

$value3 = $elfComputer->readMemoryOffset(2);
$this->assertSame(3, $value3);
}

public function testWriteMemory(): void
{
$elfComputer = new ElfComputer3('day2/part1/0');
$elfComputer->initialise();
$elfComputer->setPosition(1);

$elfComputer->writeMemory(5, 0);
$elfComputer->writeMemory(42);

$program = $elfComputer->getProgram();
$this->assertSame(5, $program[0]);
$this->assertSame(42, $program[1]);
}

public function testWriteMemoryOffset(): void
{
$elfComputer = new ElfComputer3('day2/part1/0');
$elfComputer->initialise();
$elfComputer->setPosition(1);

$elfComputer->writeMemoryOffset(5, 2);
$elfComputer->writeMemoryOffset(42);

$program = $elfComputer->getProgram();
$this->assertSame(5, $program[3]);
$this->assertSame(42, $program[1]);
}

public function testParseInstruction()
{
$elfComputer = new ElfComputer3('day5/part1/0');
$parsedInstruction = $elfComputer->parseInstruction('1002');

$this->assertSame(2, $parsedInstruction['opcode']);
$this->assertSame(0, $parsedInstruction['mode1']);
$this->assertSame(1, $parsedInstruction['mode2']);
$this->assertSame(0, $parsedInstruction['mode3']);
}
}

0 comments on commit 5dbed61

Please sign in to comment.