]> www.fi.muni.cz Git - aoc.git/blob - 2018/32.pl
Day 25: examining the input
[aoc.git] / 2018 / 32.pl
1 #!/usr/bin/perl -w
2
3 use v5.30;
4 use strict;
5
6 local $/ = "\n\n";
7
8 my @is_op = (65535) x 16;
9
10 my $total = 0;
11 while(<>) {
12         chomp;
13         last if !length;
14
15         my @nums = /(\d+)/g;
16         my @before = @nums[0..3];
17         my ($op, $a, $b, $c) = @nums[4..7];
18         my @after  = @nums[8..11];
19         my $match = 0;
20
21         print join(' ', @nums), "\n";
22         # addr
23         $is_op[$op] &= ~(1 << 0) unless ($before[$a] + $before[$b] == $after[$c]);
24         # addi
25         $is_op[$op] &= ~(1 << 1) unless ($before[$a] + $b == $after[$c]);
26         # mulr
27         $is_op[$op] &= ~(1 << 2) unless ($before[$a] * $before[$b] == $after[$c]);
28         # muli
29         $is_op[$op] &= ~(1 << 3) unless ($before[$a] * $b == $after[$c]);
30         # bandr
31         $is_op[$op] &= ~(1 << 4) unless (($before[$a] & $before[$b]) == $after[$c]);
32         # bandi
33         $is_op[$op] &= ~(1 << 5) unless (($before[$a] & $b) == $after[$c]);
34         # borr
35         $is_op[$op] &= ~(1 << 6) unless (($before[$a] | $before[$b]) == $after[$c]);
36         # bori
37         $is_op[$op] &= ~(1 << 7) unless (($before[$a] | $b) == $after[$c]);
38         # setr
39         $is_op[$op] &= ~(1 << 8) unless ($before[$a] == $after[$c]);
40         # seti
41         $is_op[$op] &= ~(1 << 9) unless ($a == $after[$c]);
42         # gtir
43         $is_op[$op] &= ~(1 << 10) unless (($a > $before[$b] ? 1 : 0) == $after[$c]);
44         # gtri
45         $is_op[$op] &= ~(1 << 11) unless (($before[$a] > $b ? 1 : 0) == $after[$c]);
46         # gtrr
47         $is_op[$op] &= ~(1 << 12) unless (($before[$a] > $before[$b] ? 1 : 0) == $after[$c]);
48         # eqir
49         $is_op[$op] &= ~(1 << 13) unless (($a == $before[$b] ? 1 : 0) == $after[$c]);
50         # eqri
51         $is_op[$op] &= ~(1 << 14) unless (($before[$a] == $b ? 1 : 0) == $after[$c]);
52         # eqrr
53         $is_op[$op] &= ~(1 << 15) unless (($before[$a] == $before[$b] ? 1 : 0) == $after[$c]);
54         print join(' ', map { sprintf("%04x", $_) } @is_op), "\n";
55 }
56
57 my %is_2n = map { (1 << $_) => 1 } 0 .. 15;
58
59 my %done_2n;
60 my $modified = 1;
61 while ($modified) {
62         say join(" ", map { sprintf("%04x", $_) } @is_op);
63         $modified = 0;
64         for my $try (0 .. 15) {
65                 next if $done_2n{$try};
66                 next if !$is_2n{$is_op[$try]};
67                 print "Unique: $try: $is_op[$try]\n";
68                 $done_2n{$try} = 1;
69                 $modified = 1;
70                 for my $other (0 .. 15) {
71                         next if $done_2n{$other};
72                         $is_op[$other] &= ~$is_op[$try];
73                 }
74         }
75 }
76
77 my @op_trans;
78 for my $op (0 .. 15) {
79         for my $l (0 .. 15) {
80                 next if (1 << $l) != $is_op[$op];
81                 print "$op => $l\n";
82                 $op_trans[$op] = $l;
83         }
84 }
85
86 local $/ = "\n";
87 my @regs = (0) x 4;
88 while (<>) {
89         my ($op, $a, $b, $c) = /(\d+)/g;
90         say "$op $a $b $c ", join(' ', @regs);
91
92         # addr
93         $regs[$c] = $regs[$a] + $regs[$b] if $op_trans[$op] == 0;
94         # addi
95         $regs[$c] = $regs[$a] + $b if $op_trans[$op] == 1;
96         # mulr
97         $regs[$c] = $regs[$a] * $regs[$b] if $op_trans[$op] == 2;
98         # muli
99         $regs[$c] = $regs[$a] * $b if $op_trans[$op] == 3;
100         # bandr
101         $regs[$c] = ($regs[$a] & $regs[$b]) if $op_trans[$op] == 4;
102         # bandi
103         $regs[$c] = ($regs[$a] & $b) if $op_trans[$op] == 5;
104         # borr
105         $regs[$c] = ($regs[$a] | $regs[$b]) if $op_trans[$op] == 6;
106         # bori
107         $regs[$c] = ($regs[$a] | $b) if $op_trans[$op] == 7;
108         # setr
109         $regs[$c] = $regs[$a] if $op_trans[$op] == 8;
110         # seti
111         $regs[$c] = $a if $op_trans[$op] == 9;
112         # gtir
113         $regs[$c] = ($a > $regs[$b] ? 1 : 0) if $op_trans[$op] == 10;
114         # gtri
115         $regs[$c] = ($regs[$a] > $b ? 1 : 0) if $op_trans[$op] == 11;
116         # gtrr
117         $regs[$c] = ($regs[$a] > $regs[$b] ? 1 : 0) if $op_trans[$op] == 12;
118         # eqir
119         $regs[$c] = ($a == $regs[$b] ? 1 : 0) if $op_trans[$op] == 13;
120         # eqri
121         $regs[$c] = ($regs[$a] == $b ? 1 : 0) if $op_trans[$op] == 14;
122         # eqrr
123         $regs[$c] = ($regs[$a] == $regs[$b] ? 1 : 0) if $op_trans[$op] == 15;
124 }
125
126 say $regs[0];
127