1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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;
|