]> www.fi.muni.cz Git - aoc.git/blob - 2016/49.pl
The rest of Year 2016
[aoc.git] / 2016 / 49.pl
1 #!/usr/bin/perl -w
2
3 use strict;
4 use v5.16;
5
6 my @code = map { chomp; [ split /\s+/ ] } <>;
7
8 my $start = -1;
9 STARTVAL:
10 while (1) {
11         my %regs = (a => ++$start, b => 0, c => 0, d => 0);
12         
13         say "Trying $start";
14
15         my $ip = 0;
16         my %state;
17
18         my $debug = 0;
19         my $nouts = 0;
20
21         while ($ip < @code) {
22                 say join(' ', $ip, @{ $code[$ip] }, map { "$_=$regs{$_}" } sort keys %regs)
23                         if $debug;
24                 my $key = join(',', $ip, map { $regs{$_} } qw(a b c d));
25                 if (defined $state{$key} && $nouts > $state{$key}
26                         && ($nouts - $state{$key}) % 2 == 0) {
27                         say $start;
28                         exit 0;
29                 }
30                 $state{$key} = $nouts;
31                 $debug = 0;
32                 my @ins = @{ $code[$ip] };
33                 if ($ins[0] eq 'cpy') {
34                         my $val = $ins[1];
35                         my $reg = $ins[2];
36                         $val = $regs{$val} if $val =~ /[a-z]/;
37                         $regs{$reg} = $val;
38                 } elsif ($ins[0] eq 'inc') {
39                         $regs{$ins[1]}++;
40                 } elsif ($ins[0] eq 'dec') {
41                         $regs{$ins[1]}--;
42                 } elsif ($ins[0] eq 'jnz') {
43                         my ($reg, $val) = @ins[1..2];
44                         if ($val eq '-2' && $ip >= 2 && $code[$ip-1][0] eq 'dec'
45                                 && $code[$ip-2][0] eq 'inc'
46                                 && $code[$ip-1][1] eq $reg) {
47                                 $regs{$code[$ip-2][1]} += $regs{$reg};
48                                 $regs{$reg} = 0;
49                         }
50                         $val = $regs{$val} if $val =~ /[a-z]/;
51                         $reg = $regs{$reg} if $reg =~ /[a-z]/;
52                         if ($reg) {
53                                 $ip += $val - 1;
54                         }
55                 } elsif ($ins[0] eq 'out') {
56                         my $val = $ins[1];
57                         $val = $regs{$val} if $val =~ /[a-z]/;
58                         if ($val != ($nouts & 1)) {
59                                 next STARTVAL;
60                         }
61                         $nouts++;
62                 } else {
63                         say "Unknown instrution: $_";
64                 }
65                 $ip++;
66         }
67 }
68