--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.40;
+
+my @reg;
+push @reg, <> =~ /\d+/g for 1 .. 3;
++<>;
+my @prog = <> =~ /\d+/g;
+
+my $pc = 0;
+my @out;
+while ($pc < @prog) {
+ my ($opc, $arg) = @prog[$pc, $pc+1];
+ last if !defined $pc;
+ my $combo;
+ if ($arg < 4) {
+ $combo = $arg;
+ } elsif ($arg < 7) {
+ $combo = $reg[$arg-4];
+ } else {
+ die "Combo arg $arg";
+ }
+ if ($opc == 0) {
+ $reg[0] = int ($reg[0] / (1 << $combo));
+ } elsif ($opc == 1) {
+ $reg[1] ^= $arg;
+ } elsif ($opc == 2) {
+ $reg[1] = $combo & 0x7;
+ } elsif ($opc == 3) {
+ if ($reg[0]) {
+ $pc = $arg - 2;
+ }
+ } elsif ($opc == 4) {
+ $reg[1] ^= $reg[2];
+ } elsif ($opc == 5) {
+ push @out, $combo & 0x7;
+ } elsif ($opc == 6) {
+ $reg[1] = int ($reg[0] / (1 << $combo));
+ } elsif ($opc == 7) {
+ $reg[2] = int ($reg[0] / (1 << $combo));
+ } else {
+ die "Unknown opcode $opc";
+ }
+ $pc += 2;
+}
+say join(',', @out);
--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.40;
+use List::Util qw(min);
+
+my @reg;
+push @reg, <> =~ /\d+/g for 1 .. 3;
++<>;
+my @prog = <> =~ /\d+/g;
+
+sub run($m) {
+ my @out;
+ while ($m->{pc} < @{ $m->{prog} }) {
+ my ($opc, $arg) = @{ $m->{prog} }[$m->{pc}, $m->{pc}+1];
+ last if !defined $arg;
+ my $combo;
+ if ($arg < 4) {
+ $combo = $arg;
+ } elsif ($arg < 7) {
+ $combo = $m->{reg}->[$arg-4];
+ } else {
+ die "Combo arg $arg";
+ }
+ if ($opc == 0) {
+ $m->{reg}->[0] = $m->{reg}->[0] >> $combo;
+ } elsif ($opc == 1) {
+ $m->{reg}->[1] ^= $arg;
+ } elsif ($opc == 2) {
+ $m->{reg}->[1] = $combo & 0x7;
+ } elsif ($opc == 3) {
+ if ($m->{reg}->[0]) {
+ $m->{pc} = $arg - 2;
+ }
+ } elsif ($opc == 4) {
+ $m->{reg}->[1] ^= $m->{reg}->[2];
+ } elsif ($opc == 5) {
+ my $val = $combo & 0x7;
+ my $ex = shift @{ $m->{ex} };
+ return undef if $val != $ex;
+ return 1 if !@{ $m->{ex} };
+ } elsif ($opc == 6) {
+ $m->{reg}->[1] = $m->{reg}->[0] >> $combo;
+ } elsif ($opc == 7) {
+ $m->{reg}->[2] = $m->{reg}->[0] >> $combo;
+ } else {
+ die "Unknown opcode $opc";
+ }
+
+ $m->{pc} += 2;
+ }
+ return @{ $m->{ex} } ? 0 : 1;
+}
+
+my @valid = (0);
+for my $l (0 .. $#prog) {
+ say "$l: ", join(',', @prog[0 .. $l]);
+ my @nv;
+ my %seen = ();
+ for my $i (0 .. 1023) {
+ my $ii = $i << (3*$l);
+ for my $v (@valid) {
+ my $val = $v;
+ $val ^= $ii;
+ next if $seen{$val}++;
+ my $rv = run({
+ reg => [ $val, 0, 0 ],
+ prog => \@prog,
+ pc => 0,
+ ex => [ @prog[0 .. $l] ],
+ });
+ next if !$rv;
+ push @nv, $val;
+ }
+ }
+ @valid = @nv;
+}
+say min @valid;