]> www.fi.muni.cz Git - aoc.git/commitdiff
Day 17: slow and ineffective part 2
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 19 Dec 2024 07:29:03 +0000 (08:29 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 19 Dec 2024 07:29:03 +0000 (08:29 +0100)
2024/33.pl [new file with mode: 0755]
2024/34.pl [new file with mode: 0755]

diff --git a/2024/33.pl b/2024/33.pl
new file mode 100755 (executable)
index 0000000..81c215c
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+
+use v5.40;
+
+my @reg;
+push @reg, <> =~ /\d+/g for 1 .. 3;
++<>;
+my @prog = <> =~ /\d+/g;
+
+my $pc = 0;
+my @out;
+while ($pc < @prog) {
+       my ($opc, $arg) = @prog[$pc, $pc+1];
+       last if !defined $pc;
+       my $combo;
+       if ($arg < 4) {
+               $combo = $arg;
+       } elsif ($arg < 7) {
+               $combo = $reg[$arg-4];
+       } else {
+               die "Combo arg $arg";
+       }
+       if ($opc == 0) {
+               $reg[0] = int ($reg[0] / (1 << $combo));
+       } elsif ($opc == 1) {
+               $reg[1] ^= $arg;
+       } elsif ($opc == 2) {
+               $reg[1] = $combo & 0x7;
+       } elsif ($opc == 3) {
+               if ($reg[0]) {
+                       $pc = $arg - 2;
+               }
+       } elsif ($opc == 4) {
+               $reg[1] ^= $reg[2];
+       } elsif ($opc == 5) {
+               push @out, $combo & 0x7;
+       } elsif ($opc == 6) {
+               $reg[1] = int ($reg[0] / (1 << $combo));
+       } elsif ($opc == 7) {
+               $reg[2] = int ($reg[0] / (1 << $combo));
+       } else {
+               die "Unknown opcode $opc";
+       }
+       $pc += 2;
+}
+say join(',', @out);
diff --git a/2024/34.pl b/2024/34.pl
new file mode 100755 (executable)
index 0000000..976784f
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/perl -w
+
+use v5.40;
+use List::Util qw(min);
+
+my @reg;
+push @reg, <> =~ /\d+/g for 1 .. 3;
++<>;
+my @prog = <> =~ /\d+/g;
+
+sub run($m) {
+       my @out;
+       while ($m->{pc} < @{ $m->{prog} }) {
+               my ($opc, $arg) = @{ $m->{prog} }[$m->{pc}, $m->{pc}+1];
+               last if !defined $arg;
+               my $combo;
+               if ($arg < 4) {
+                       $combo = $arg;
+               } elsif ($arg < 7) {
+                       $combo = $m->{reg}->[$arg-4];
+               } else {
+                       die "Combo arg $arg";
+               }
+               if ($opc == 0) {
+                       $m->{reg}->[0] = $m->{reg}->[0] >> $combo;
+               } elsif ($opc == 1) {
+                       $m->{reg}->[1] ^= $arg;
+               } elsif ($opc == 2) {
+                       $m->{reg}->[1] = $combo & 0x7;
+               } elsif ($opc == 3) {
+                       if ($m->{reg}->[0]) {
+                               $m->{pc} = $arg - 2;
+                       }
+               } elsif ($opc == 4) {
+                       $m->{reg}->[1] ^= $m->{reg}->[2];
+               } elsif ($opc == 5) {
+                       my $val = $combo & 0x7;
+                       my $ex = shift @{ $m->{ex} };
+                       return undef if $val != $ex;
+                       return 1 if !@{ $m->{ex} };
+               } elsif ($opc == 6) {
+                       $m->{reg}->[1] = $m->{reg}->[0] >> $combo;
+               } elsif ($opc == 7) {
+                       $m->{reg}->[2] = $m->{reg}->[0] >> $combo;
+               } else {
+                       die "Unknown opcode $opc";
+               }
+
+               $m->{pc} += 2;
+       }
+       return @{ $m->{ex} } ? 0 : 1;
+}
+
+my @valid = (0);
+for my $l (0 .. $#prog) {
+       say "$l: ", join(',', @prog[0 .. $l]);
+       my @nv;
+       my %seen = ();
+       for my $i (0 .. 1023) {
+               my $ii = $i << (3*$l);
+               for my $v (@valid) {
+                       my $val = $v;
+                       $val ^= $ii;
+                       next if $seen{$val}++;
+                       my $rv = run({
+                               reg  => [ $val, 0, 0 ],
+                               prog => \@prog,
+                               pc   => 0,
+                               ex   => [ @prog[0 .. $l] ],
+                       });
+                       next if !$rv;
+                       push @nv, $val;
+               }
+       }
+       @valid = @nv;
+}
+say min @valid;