about summary refs log tree commit diff
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;