--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+use v5.16;
+
+my @code = map { chomp; [ split /\s+/ ] } <>;
+
+my $start = -1;
+STARTVAL:
+while (1) {
+ my %regs = (a => ++$start, b => 0, c => 0, d => 0);
+
+ say "Trying $start";
+
+ my $ip = 0;
+ my %state;
+
+ my $debug = 0;
+ my $nouts = 0;
+
+ while ($ip < @code) {
+ say join(' ', $ip, @{ $code[$ip] }, map { "$_=$regs{$_}" } sort keys %regs)
+ if $debug;
+ my $key = join(',', $ip, map { $regs{$_} } qw(a b c d));
+ if (defined $state{$key} && $nouts > $state{$key}
+ && ($nouts - $state{$key}) % 2 == 0) {
+ say $start;
+ exit 0;
+ }
+ $state{$key} = $nouts;
+ $debug = 0;
+ my @ins = @{ $code[$ip] };
+ if ($ins[0] eq 'cpy') {
+ my $val = $ins[1];
+ my $reg = $ins[2];
+ $val = $regs{$val} if $val =~ /[a-z]/;
+ $regs{$reg} = $val;
+ } elsif ($ins[0] eq 'inc') {
+ $regs{$ins[1]}++;
+ } elsif ($ins[0] eq 'dec') {
+ $regs{$ins[1]}--;
+ } elsif ($ins[0] eq 'jnz') {
+ my ($reg, $val) = @ins[1..2];
+ if ($val eq '-2' && $ip >= 2 && $code[$ip-1][0] eq 'dec'
+ && $code[$ip-2][0] eq 'inc'
+ && $code[$ip-1][1] eq $reg) {
+ $regs{$code[$ip-2][1]} += $regs{$reg};
+ $regs{$reg} = 0;
+ }
+ $val = $regs{$val} if $val =~ /[a-z]/;
+ $reg = $regs{$reg} if $reg =~ /[a-z]/;
+ if ($reg) {
+ $ip += $val - 1;
+ }
+ } elsif ($ins[0] eq 'out') {
+ my $val = $ins[1];
+ $val = $regs{$val} if $val =~ /[a-z]/;
+ if ($val != ($nouts & 1)) {
+ next STARTVAL;
+ }
+ $nouts++;
+ } else {
+ say "Unknown instrution: $_";
+ }
+ $ip++;
+ }
+}
+