aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2019-12-11 22:01:47 +0100
committerLeah Neukirchen <leah@vuxu.org>2019-12-11 22:01:47 +0100
commitd87d35be738179dadcade23563c39e812507573d (patch)
treee388937a764c5c314c362b6611097a00d875a9cc
parentef1d5ae6393bc198ab7b8dd5ef339fb3619427cb (diff)
downloadadventofcode2019-d87d35be738179dadcade23563c39e812507573d.tar.gz
adventofcode2019-d87d35be738179dadcade23563c39e812507573d.tar.xz
adventofcode2019-d87d35be738179dadcade23563c39e812507573d.zip
day09
-rw-r--r--day09.pl90
1 files changed, 90 insertions, 0 deletions
diff --git a/day09.pl b/day09.pl
new file mode 100644
index 0000000..d295b6a
--- /dev/null
+++ b/day09.pl
@@ -0,0 +1,90 @@
+#!/usr/bin/perl -w
+use v5.16;
+
+say IntCode->new('day09')->run(1); # 3063082071
+say IntCode->new('day09')->run(2); # 81348
+
+
+package IntCode;
+
+use Class::Tiny qw( input output code ip base );
+use File::Slurper 'read_text';
+
+sub BUILDARGS {
+ my $class = shift;
+ return { input => [],
+ output => [],
+ code => [ split ",", read_text(shift) ],
+ ip => 0,
+ base => 0 };
+};
+
+sub done {
+ my $self = shift;
+ $self->code->[$self->ip] == 99;
+}
+
+sub pipe {
+ my ($self, $other) = @_;
+ $self->{output} = $other->{input};
+ $self;
+}
+
+sub push {
+ my $self = shift;
+ push @{$self->{input}}, @_;
+ $self;
+}
+
+sub run {
+ my $self = shift;
+ $self->{input} = [ @_ ];
+ until ($self->done) {
+ $self->step;
+ }
+ @{$self->output};
+}
+
+sub step {
+ my $self = shift;
+
+ no warnings 'uninitialized';
+
+ my ($pm3, $pm2, $pm1, $op1, $op2) =
+ split '', sprintf("%05d", $self->code->[$self->ip]);
+ my $op = $op1 . $op2;
+ my $p1 = $pm1 == 0 ? $self->code->[$self->code->[$self->ip + 1]]
+ : $pm1 == 1 ? $self->code->[$self->ip + 1]
+ : $pm1 == 2 ? $self->code->[$self->code->[$self->ip + 1] +
+ $self->base]
+ : undef;
+ my $p2 = $pm2 == 0 ? $self->code->[$self->code->[$self->ip + 2]]
+ : $pm2 == 1 ? $self->code->[$self->ip + 2]
+ : $pm2 == 2 ? $self->code->[$self->code->[$self->ip + 2] +
+ $self->base]
+ : undef;
+ my $p3 = $pm3 == 0 ? $self->code->[$self->code->[$self->ip + 3]]
+ : $pm3 == 1 ? $self->code->[$self->ip + 3]
+ : $pm3 == 2 ? $self->code->[$self->code->[$self->ip + 3] +
+ $self->base]
+ : undef;
+ my $w3 = $self->code->[$self->ip+3] + ($pm3 == 2 ? $self->base : 0);
+ if ($op == 1) { $self->code->[$w3] = $p1 + $p2; $self->{ip} += 4; }
+ elsif ($op == 2) { $self->code->[$w3] = $p1 * $p2; $self->{ip} += 4; }
+ elsif ($op == 3) { return unless (@{$self->{input}}); # stall
+ $self->code->[$self->code->[$self->ip+1] +
+ ($pm1 == 2 ? $self->base : 0)] =
+ shift @{$self->{input}};
+ $self->{ip} += 2; }
+ elsif ($op == 4) { CORE::push @{$self->{output}}, $p1; $self->{ip} += 2; }
+ elsif ($op == 5) { $self->{ip} = $p1 ? $p2 : $self->ip + 3; }
+ elsif ($op == 6) { $self->{ip} = !$p1 ? $p2 : $self->ip + 3; }
+ elsif ($op == 7) { $self->code->[$w3] = $p1 < $p2; $self->{ip} += 4; }
+ elsif ($op == 8) { $self->code->[$w3] = $p1 == $p2; $self->{ip} += 4; }
+ elsif ($op == 9) { $self->{base} += $p1; $self->{ip} += 2; }
+ else { say "INVALID OP"; }
+
+ $self;
+}
+
+1;