--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.16;
+
+package IntComp;
+use bigint;
+
+sub new {
+ my ($class, $mem, $inputs) = @_;
+ my $self = {
+ mem => [ @$mem ],
+ pc => 0,
+ want_input => undef,
+ base => 0,
+ };
+ $self->{inputs} = [ @$inputs ]
+ if defined $inputs;
+ bless $self, $class;
+}
+
+sub clone {
+ my ($class, $other) = @_;
+ my $self = {
+ mem => [ @{ $other->{mem} } ],
+ pc => $other->{pc},
+ want_input => undef,
+ base => $other->{base},
+ inputs => [ ],
+ };
+ bless $self, $class;
+}
+
+sub m2val {
+ my ($self, $off, $mode) = @_;
+ if ($mode == 0) {
+ return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off] ] // 0;
+ } elsif ($mode == 1) {
+ return $self->{mem}->[$self->{pc} + $off] // 0;
+ } elsif ($mode == 2) {
+ return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off ] + $self->{base} ] // 0;
+ }
+}
+
+sub m2pos {
+ my ($self, $off, $mode) = @_;
+ if ($mode == 0) {
+ return $self->{mem}->[$self->{pc} + $off];
+ } elsif ($mode == 2) {
+ return $self->{mem}->[$self->{pc} + $off] + $self->{base};
+ }
+}
+
+sub input {
+ my ($self, @input) = @_;
+ push @{ $self->{inputs} }, @input;
+}
+
+sub run {
+ my ($self, @input) = @_;
+ my $mem = $self->{mem};
+
+ push @{ $self->{inputs} }, @input;
+ if (defined $self->{want_input}) {
+ $mem->[$self->{want_input}] = shift @{ $self->{inputs} };
+ $self->{want_input} = undef;
+ }
+
+ while (1) {
+ my $opcode = $mem->[$self->{pc}];
+ # say "pc=", $self->{pc}, " opcode=$opcode";
+ # say "mem=", join(',', map { $_ // '_' } @{ $self->{mem} });
+ my $op = int($opcode % 100);
+ my $m1 = int($opcode / 100) % 10;
+ my $m2 = int($opcode / 1000) % 10;
+ my $m3 = int($opcode / 10000) % 10;
+ if ($op == 1) {
+ $mem->[ m2pos($self, 3, $m3) ]
+ = m2val($self, 1, $m1)
+ + m2val($self, 2, $m2);
+ $self->{pc} += 4;
+ } elsif ($op == 2) {
+ $mem->[ m2pos($self, 3, $m3) ]
+ = m2val($self, 1, $m1)
+ * m2val($self, 2, $m2);
+ $self->{pc} += 4;
+ } elsif ($op == 3) {
+ if (@{ $self->{inputs} }) {
+ $mem->[ m2pos($self, 1, $m1) ]
+ = shift @{ $self->{inputs} };
+ $self->{pc} += 2;
+ } else {
+ $self->{want_input} = m2pos($self, 1, $m1);
+ $self->{pc} += 2;
+ return undef;
+ }
+ } elsif ($op == 4) {
+ my $val = m2val($self, 1, $m1);
+ $self->{pc} += 2;
+ return $val;
+ } elsif ($op == 5) {
+ if (m2val($self, 1, $m1)) {
+ $self->{pc} = m2val($self, 2, $m2);
+ } else {
+ $self->{pc} += 3;
+ }
+ } elsif ($op == 6) {
+ if (!m2val($self, 1, $m1)) {
+ $self->{pc} = m2val($self, 2, $m2);
+ } else {
+ $self->{pc} += 3;
+ }
+ } elsif ($op == 7) {
+ $mem->[ m2pos($self, 3, $m3) ] =
+ m2val($self, 1, $m1)
+ < m2val($self, 2, $m2) ? 1 : 0;
+ $self->{pc} += 4;
+ } elsif ($op == 8) {
+ $mem->[ m2pos($self, 3, $m3) ] =
+ m2val($self, 1, $m1)
+ == m2val($self, 2, $m2) ? 1 : 0;
+ $self->{pc} += 4;
+ } elsif ($op == 9) {
+ $self->{base} += m2val($self, 1, $m1);
+ $self->{pc} += 2;
+ } elsif ($op == 99) {
+ return undef;
+ }
+ }
+}
+
+package main;
+
+chomp (my @mem = split /,/, <>);
+
+$; = ',';
+
+my $sum;
+
+for my $x (0 .. 49) {
+for my $y (0 .. 49) {
+ my $comp = IntComp->new(\@mem, [ $x, $y ]);
+ my $rv = $comp->run;
+ $sum++ if $rv;
+ print $rv ? '#' : '.';
+}
+print "\n";
+}
+
+say $sum;
--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.16;
+
+package IntComp;
+use bigint;
+
+sub new {
+ my ($class, $mem, $inputs) = @_;
+ my $self = {
+ mem => [ @$mem ],
+ pc => 0,
+ want_input => undef,
+ base => 0,
+ };
+ $self->{inputs} = [ @$inputs ]
+ if defined $inputs;
+ bless $self, $class;
+}
+
+sub clone {
+ my ($class, $other) = @_;
+ my $self = {
+ mem => [ @{ $other->{mem} } ],
+ pc => $other->{pc},
+ want_input => undef,
+ base => $other->{base},
+ inputs => [ ],
+ };
+ bless $self, $class;
+}
+
+sub m2val {
+ my ($self, $off, $mode) = @_;
+ if ($mode == 0) {
+ return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off] ] // 0;
+ } elsif ($mode == 1) {
+ return $self->{mem}->[$self->{pc} + $off] // 0;
+ } elsif ($mode == 2) {
+ return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off ] + $self->{base} ] // 0;
+ }
+}
+
+sub m2pos {
+ my ($self, $off, $mode) = @_;
+ if ($mode == 0) {
+ return $self->{mem}->[$self->{pc} + $off];
+ } elsif ($mode == 2) {
+ return $self->{mem}->[$self->{pc} + $off] + $self->{base};
+ }
+}
+
+sub input {
+ my ($self, @input) = @_;
+ push @{ $self->{inputs} }, @input;
+}
+
+sub run {
+ my ($self, @input) = @_;
+ my $mem = $self->{mem};
+
+ push @{ $self->{inputs} }, @input;
+ if (defined $self->{want_input}) {
+ $mem->[$self->{want_input}] = shift @{ $self->{inputs} };
+ $self->{want_input} = undef;
+ }
+
+ while (1) {
+ my $opcode = $mem->[$self->{pc}];
+ # say "pc=", $self->{pc}, " opcode=$opcode";
+ # say "mem=", join(',', map { $_ // '_' } @{ $self->{mem} });
+ my $op = int($opcode % 100);
+ my $m1 = int($opcode / 100) % 10;
+ my $m2 = int($opcode / 1000) % 10;
+ my $m3 = int($opcode / 10000) % 10;
+ if ($op == 1) {
+ $mem->[ m2pos($self, 3, $m3) ]
+ = m2val($self, 1, $m1)
+ + m2val($self, 2, $m2);
+ $self->{pc} += 4;
+ } elsif ($op == 2) {
+ $mem->[ m2pos($self, 3, $m3) ]
+ = m2val($self, 1, $m1)
+ * m2val($self, 2, $m2);
+ $self->{pc} += 4;
+ } elsif ($op == 3) {
+ if (@{ $self->{inputs} }) {
+ $mem->[ m2pos($self, 1, $m1) ]
+ = shift @{ $self->{inputs} };
+ $self->{pc} += 2;
+ } else {
+ $self->{want_input} = m2pos($self, 1, $m1);
+ $self->{pc} += 2;
+ return undef;
+ }
+ } elsif ($op == 4) {
+ my $val = m2val($self, 1, $m1);
+ $self->{pc} += 2;
+ return $val;
+ } elsif ($op == 5) {
+ if (m2val($self, 1, $m1)) {
+ $self->{pc} = m2val($self, 2, $m2);
+ } else {
+ $self->{pc} += 3;
+ }
+ } elsif ($op == 6) {
+ if (!m2val($self, 1, $m1)) {
+ $self->{pc} = m2val($self, 2, $m2);
+ } else {
+ $self->{pc} += 3;
+ }
+ } elsif ($op == 7) {
+ $mem->[ m2pos($self, 3, $m3) ] =
+ m2val($self, 1, $m1)
+ < m2val($self, 2, $m2) ? 1 : 0;
+ $self->{pc} += 4;
+ } elsif ($op == 8) {
+ $mem->[ m2pos($self, 3, $m3) ] =
+ m2val($self, 1, $m1)
+ == m2val($self, 2, $m2) ? 1 : 0;
+ $self->{pc} += 4;
+ } elsif ($op == 9) {
+ $self->{base} += m2val($self, 1, $m1);
+ $self->{pc} += 2;
+ } elsif ($op == 99) {
+ return undef;
+ }
+ }
+}
+
+package main;
+
+chomp (my @mem = split /,/, <>);
+
+$; = ',';
+
+my $sum;
+
+sub getpos { return IntComp->new(\@mem, [ @_ ])->run; }
+
+my ($first, $last) = (0, 0);
+my $y = 10;
+
+my @ends;
+while (1) {
+ $y++;
+ $first++ while !getpos($first, $y);
+ $last = $first if $last < $first;
+ $last++ while getpos($last, $y);
+ say "$y $first..$last-1 (", $last - $first, ")";
+ push @ends, $last;
+ if (@ends >= 100) {
+ my $end = shift @ends;
+ if ($end - $first >= 100) {
+ say "found at $first $y-99, ", 10000*$first+($y-99);
+ last;
+ }
+ }
+}