]> www.fi.muni.cz Git - aoc.git/blobdiff - 2018/32.pl
Year 2018
[aoc.git] / 2018 / 32.pl
diff --git a/2018/32.pl b/2018/32.pl
new file mode 100755 (executable)
index 0000000..6a1f2e4
--- /dev/null
@@ -0,0 +1,127 @@
+#!/usr/bin/perl -w
+
+use v5.30;
+use strict;
+
+local $/ = "\n\n";
+
+my @is_op = (65535) x 16;
+
+my $total = 0;
+while(<>) {
+       chomp;
+       last if !length;
+
+       my @nums = /(\d+)/g;
+       my @before = @nums[0..3];
+       my ($op, $a, $b, $c) = @nums[4..7];
+       my @after  = @nums[8..11];
+       my $match = 0;
+
+       print join(' ', @nums), "\n";
+       # addr
+       $is_op[$op] &= ~(1 << 0) unless ($before[$a] + $before[$b] == $after[$c]);
+       # addi
+       $is_op[$op] &= ~(1 << 1) unless ($before[$a] + $b == $after[$c]);
+       # mulr
+       $is_op[$op] &= ~(1 << 2) unless ($before[$a] * $before[$b] == $after[$c]);
+       # muli
+       $is_op[$op] &= ~(1 << 3) unless ($before[$a] * $b == $after[$c]);
+       # bandr
+       $is_op[$op] &= ~(1 << 4) unless (($before[$a] & $before[$b]) == $after[$c]);
+       # bandi
+       $is_op[$op] &= ~(1 << 5) unless (($before[$a] & $b) == $after[$c]);
+       # borr
+       $is_op[$op] &= ~(1 << 6) unless (($before[$a] | $before[$b]) == $after[$c]);
+       # bori
+       $is_op[$op] &= ~(1 << 7) unless (($before[$a] | $b) == $after[$c]);
+       # setr
+       $is_op[$op] &= ~(1 << 8) unless ($before[$a] == $after[$c]);
+       # seti
+       $is_op[$op] &= ~(1 << 9) unless ($a == $after[$c]);
+       # gtir
+       $is_op[$op] &= ~(1 << 10) unless (($a > $before[$b] ? 1 : 0) == $after[$c]);
+       # gtri
+       $is_op[$op] &= ~(1 << 11) unless (($before[$a] > $b ? 1 : 0) == $after[$c]);
+       # gtrr
+       $is_op[$op] &= ~(1 << 12) unless (($before[$a] > $before[$b] ? 1 : 0) == $after[$c]);
+       # eqir
+       $is_op[$op] &= ~(1 << 13) unless (($a == $before[$b] ? 1 : 0) == $after[$c]);
+       # eqri
+       $is_op[$op] &= ~(1 << 14) unless (($before[$a] == $b ? 1 : 0) == $after[$c]);
+       # eqrr
+       $is_op[$op] &= ~(1 << 15) unless (($before[$a] == $before[$b] ? 1 : 0) == $after[$c]);
+       print join(' ', map { sprintf("%04x", $_) } @is_op), "\n";
+}
+
+my %is_2n = map { (1 << $_) => 1 } 0 .. 15;
+
+my %done_2n;
+my $modified = 1;
+while ($modified) {
+       say join(" ", map { sprintf("%04x", $_) } @is_op);
+       $modified = 0;
+       for my $try (0 .. 15) {
+               next if $done_2n{$try};
+               next if !$is_2n{$is_op[$try]};
+               print "Unique: $try: $is_op[$try]\n";
+               $done_2n{$try} = 1;
+               $modified = 1;
+               for my $other (0 .. 15) {
+                       next if $done_2n{$other};
+                       $is_op[$other] &= ~$is_op[$try];
+               }
+       }
+}
+
+my @op_trans;
+for my $op (0 .. 15) {
+       for my $l (0 .. 15) {
+               next if (1 << $l) != $is_op[$op];
+               print "$op => $l\n";
+               $op_trans[$op] = $l;
+       }
+}
+
+local $/ = "\n";
+my @regs = (0) x 4;
+while (<>) {
+       my ($op, $a, $b, $c) = /(\d+)/g;
+       say "$op $a $b $c ", join(' ', @regs);
+
+       # addr
+       $regs[$c] = $regs[$a] + $regs[$b] if $op_trans[$op] == 0;
+       # addi
+       $regs[$c] = $regs[$a] + $b if $op_trans[$op] == 1;
+       # mulr
+       $regs[$c] = $regs[$a] * $regs[$b] if $op_trans[$op] == 2;
+       # muli
+       $regs[$c] = $regs[$a] * $b if $op_trans[$op] == 3;
+       # bandr
+       $regs[$c] = ($regs[$a] & $regs[$b]) if $op_trans[$op] == 4;
+       # bandi
+       $regs[$c] = ($regs[$a] & $b) if $op_trans[$op] == 5;
+       # borr
+       $regs[$c] = ($regs[$a] | $regs[$b]) if $op_trans[$op] == 6;
+       # bori
+       $regs[$c] = ($regs[$a] | $b) if $op_trans[$op] == 7;
+       # setr
+       $regs[$c] = $regs[$a] if $op_trans[$op] == 8;
+       # seti
+       $regs[$c] = $a if $op_trans[$op] == 9;
+       # gtir
+       $regs[$c] = ($a > $regs[$b] ? 1 : 0) if $op_trans[$op] == 10;
+       # gtri
+       $regs[$c] = ($regs[$a] > $b ? 1 : 0) if $op_trans[$op] == 11;
+       # gtrr
+       $regs[$c] = ($regs[$a] > $regs[$b] ? 1 : 0) if $op_trans[$op] == 12;
+       # eqir
+       $regs[$c] = ($a == $regs[$b] ? 1 : 0) if $op_trans[$op] == 13;
+       # eqri
+       $regs[$c] = ($regs[$a] == $b ? 1 : 0) if $op_trans[$op] == 14;
+       # eqrr
+       $regs[$c] = ($regs[$a] == $regs[$b] ? 1 : 0) if $op_trans[$op] == 15;
+}
+
+say $regs[0];
+