--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.16;
+
+chomp (my @mem = split /,/, <>);
+
+sub m2val {
+ my ($mref, $addr, $mode) = @_;
+ if ($mode == 0) {
+ return $mref->[ $mref->[$addr] ];
+ } elsif ($mode == 1) {
+ return $mref->[$addr];
+ }
+}
+
+sub run {
+ my ($mref, $iref) = @_;
+ my @mem = @$mref;
+ my @inputs = @$iref;
+ my $pc = 0;
+ my @out;
+ while (1) {
+ my $opcode = $mem[$pc];
+ my $op = int($opcode % 100);
+ my $m1 = int($opcode / 100) % 10;
+ my $m2 = int($opcode / 1000) % 10;
+ if ($op == 1) {
+ $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1)
+ + m2val(\@mem, $pc+2, $m2);
+ $pc += 4;
+ } elsif ($op == 2) {
+ $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1)
+ * m2val(\@mem, $pc+2, $m2);
+ $pc += 4;
+ } elsif ($op == 3) {
+ $mem[ $mem[$pc+1] ] = shift @inputs;
+ $pc += 2;
+ } elsif ($op == 4) {
+ push @out, m2val(\@mem, $pc+1, $m1);
+ $pc += 2;
+ } elsif ($op == 5) {
+ if (m2val(\@mem, $pc+1, $m1)) {
+ $pc = m2val(\@mem, $pc+2, $m2);
+ } else {
+ $pc += 3;
+ }
+ } elsif ($op == 6) {
+ if (!m2val(\@mem, $pc+1, $m1)) {
+ $pc = m2val(\@mem, $pc+2, $m2);
+ } else {
+ $pc += 3;
+ }
+ } elsif ($op == 7) {
+ $mem[ $mem[$pc+3] ] =
+ m2val(\@mem, $pc+1, $m1)
+ < m2val(\@mem, $pc+2, $m2) ? 1 : 0;
+ $pc += 4;
+ } elsif ($op == 8) {
+ $mem[ $mem[$pc+3] ] =
+ m2val(\@mem, $pc+1, $m1)
+ == m2val(\@mem, $pc+2, $m2) ? 1 : 0;
+ $pc += 4;
+ } elsif ($op == 99) {
+ last;
+ }
+ }
+ return @out;
+}
+
+my $max = 0;
+sub permute {
+ my ($remaining, $input) = @_;
+ for my $i (0 .. $#$remaining) {
+ my @nr = @$remaining;
+ my @in = ($nr[$i], @$input);
+ say "running with ", join(',', @in);
+ splice(@nr, $i, 1);
+ my @rv = run(\@mem, \@in);
+ if (@nr) {
+ permute(\@nr, \@rv);
+ } else {
+ say @rv;
+ $max = $rv[0] if $max < $rv[0];
+ }
+ }
+}
+
+permute([ 0 .. 4 ], [0]);
+
+say $max;
+