]> www.fi.muni.cz Git - aoc.git/blob - 2017/36.pl
Day 25: examining the input
[aoc.git] / 2017 / 36.pl
1 #!/usr/bin/perl
2
3 use v5.30;
4 use strict;
5
6 my @code = map { chomp; [ split /\s+/ ] } <>;
7
8 sub execute {
9         my ($regs, $pc, $qsnd, $qrecv, $nsnd) = @_;
10         while ($$pc < @code) {
11                 my ($ins, $a1, $a2) = @{ $code[$$pc] };
12                 my $v1 = $a1 =~ /[a-z]/ ? $regs->{$a1} : $a1
13                         if defined $a1;
14                 my $v2 = $a2 =~ /[a-z]/ ? $regs->{$a2} : $a2
15                         if defined $a2;
16                 if ($ins eq 'snd') {
17                         push @$qsnd, $v1;
18                         $$nsnd++ if defined $nsnd;
19                         $$pc++;
20                         return 0;
21                 } elsif ($ins eq 'set') {
22                         $regs->{$a1} = $v2;
23                 } elsif ($ins eq 'add') {
24                         $regs->{$a1} += $v2;
25                 } elsif ($ins eq 'mul') {
26                         $regs->{$a1} *= $v2;
27                 } elsif ($ins eq 'mod') {
28                         $regs->{$a1} %= $v2;
29                 } elsif ($ins eq 'rcv') {
30                         if (@$qrecv) {
31                                 $regs->{$a1} = shift @$qrecv;
32                         } else {
33                                 return 1;
34                         }
35                 } elsif ($ins eq 'jgz') {
36                         $$pc += $v2-1 if $v1 > 0;
37                 } else {
38                         die "unknown insn $ins";
39                 }
40                 $$pc++;
41         }
42         return 2;
43 }
44
45 my (@q0to1, @q1to0);
46 my %regs0 = (p => 0);
47 my %regs1 = (p => 1);
48 my ($pc0, $pc1) = (0, 0);
49 my ($s0, $s1) = (0, 0);
50 my $nsnd = 0;
51 while (1) {
52         if ($s0 == 0 || ($s0 == 1 && @q1to0)) {
53                 $s0 = execute(\%regs0, \$pc0, \@q0to1, \@q1to0);
54                 # say "p0 state $s0 at $pc0";
55         }
56         if ($s1 == 0 || ($s1 == 1 && @q0to1)) {
57                 $s1 = execute(\%regs1, \$pc1, \@q1to0, \@q0to1, \$nsnd);
58                 # say "p1 state $s1 at $pc1";
59         }
60         last if ($s0 >= 1 && $s1 >= 1);
61 }
62
63 say $nsnd;