]> www.fi.muni.cz Git - aoc.git/blobdiff - 2016/49.pl
The rest of Year 2016
[aoc.git] / 2016 / 49.pl
diff --git a/2016/49.pl b/2016/49.pl
new file mode 100755 (executable)
index 0000000..52dabea
--- /dev/null
@@ -0,0 +1,68 @@
+#!/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++;
+       }
+}
+