]> www.fi.muni.cz Git - aoc.git/commitdiff
Day 22: cube
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sat, 24 Dec 2022 06:23:56 +0000 (07:23 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sat, 24 Dec 2022 06:23:56 +0000 (07:23 +0100)
2022/43.pl [new file with mode: 0755]
2022/44.pl [new file with mode: 0755]

diff --git a/2022/43.pl b/2022/43.pl
new file mode 100755 (executable)
index 0000000..ee6ade3
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/perl -w
+
+use v5.36;
+use strict;
+
+local $/ = "\n\n";
+my @map = map { chomp; [ split // ] } split /\n/, scalar <>;
+my $ymax = $#map;
+
+local $/ = "\n";
+chomp (my $list = <>);
+
+my $dir = 0;
+my $dim;
+my ($x, $y) = (0, 0);
+$x++ while $map[$y][$x] eq ' ';
+
+my %face_ndir = (
+       A => [ 1, 1, 1, 3],
+       B => [ 0, 0, 0, 0],
+       C => [ 0, 1, 2, 3],
+       D => [ 2, 2, 2, 2],
+       E => [ 3, 1, 3, 3],
+       F => [ 2, 1, 0, 3],
+);
+my %face_next = (
+       A => [ qw(D C B F) ],
+       B => [ qw(C E F A) ],
+       C => [ qw(D E B A) ],
+       D => [ qw(F E C A) ],
+       E => [ qw(D F B C) ],
+       F => [ qw(D A B E) ],
+);
+
+my %face_of;
+my %face_dir;
+if ($Y::AoC::Task::in_test) {
+       $dim = 4;
+       %face_of = (
+               '20' => 'A',
+               '11' => 'B',
+               '21' => 'C',
+               '32' => 'D',
+               '22' => 'E',
+               '01' => 'F',
+       );
+       %face_dir = (
+               A => 0,
+               B => 0,
+               C => 0,
+               D => 1,
+               E => 0,
+               F => 2,
+       );
+} else {
+       $dim = 50;
+       %face_of = (
+               '10' => 'A',
+               '02' => 'B',
+               '11' => 'C',
+               '20' => 'D',
+               '12' => 'E',
+               '03' => 'F',
+       );
+       %face_dir = (
+               A => 0,
+               B => 3,
+               C => 0,
+               D => 3,
+               E => 0,
+               F => 1,
+       );
+}
+
+
+my %pos_of = reverse %face_of;
+sub pos_of($face) {
+       return map { $dim * $_ } split //, $pos_of{$face};
+}
+
+sub face_of($x, $y) {
+       return undef if $x < 0 || $y < 0;
+       my $fx = int($x/$dim);
+       my $fy = int($y/$dim);
+       return $face_of{"$fx$fy"};
+}
+
+sub move($sx, $sy, $dir) {
+       my $f1 = face_of($sx, $sy);
+       my ($dx, $dy) = ($sx, $sy);
+       if ($dir == 0) {
+               $dx++;
+       } elsif ($dir == 1) {
+               $dy++;
+       } elsif ($dir == 2) {
+               $dx--;
+       } elsif ($dir == 3) {
+               $dy--;
+       }
+       my $f2 = face_of($dx, $dy);
+       if (defined($f2) && $f2 eq $f1) {
+               return ($dx, $dy, $dir);
+       }
+       my $ndir;
+       say "moving from $f1 $dir";
+       my $rdir = ($dir - $face_dir{$f1}) % 4;
+       say "rdir = $rdir";
+       $f2 = $face_next{$f1}[$rdir];
+       my $rdir2 = $face_ndir{$f1}[$rdir];
+       say "rdir2 = $rdir";
+       $ndir = ($rdir2 + $face_dir{$f2}) % 4;
+       my ($nx, $ny) = ($dx % $dim, $dy % $dim);
+       my $rot = ($ndir - $dir) % 4;
+       say "$sx,$sy $nx,$ny $f1 -> $f2 r$rot $dir -> $ndir";
+       while ($rot--) {
+               # ($nx, $ny) = ($ny, (-$nx % $dim));
+               ($nx, $ny) = ((($dim-1-$ny) % $dim), $nx);
+               say "rot -> $nx,$ny";
+       }
+       say " -> $nx $ny $ndir";
+       my ($ox, $oy) = pos_of($f2);
+       $nx += $ox;
+       $ny += $oy;
+       say " -> $nx $ny";
+       say "FACE $sx,$sy,$dir $f1 -> $nx,$ny,$ndir $f2";
+       die if $map[$ny][$nx] eq ' ';
+       return ($nx, $ny, $ndir);
+}
+
+while (length $list) {
+       $list =~ s/^(\d+|[LR])//;
+       my $move = $1;
+       say "$x $y $dir $move";
+       if ($move =~ /\d+/) {
+               while ($move) {
+                       my ($dx, $dy, $ddir) = move($x, $y, $dir);
+                       last if $map[$dy][$dx] eq '#';
+                       $x = $dx; $y = $dy; $dir = $ddir;
+                       say "   $x $y $dir $move";
+                       $move--;
+               }
+       } elsif ($move eq 'L') {
+               $dir = 3 if --$dir < 0;
+       } elsif ($move eq 'R') {
+               $dir = 0 if ++$dir > 3;
+       }
+}
+
+say 1000*($y+1) + 4*($x+1) + $dir;
diff --git a/2022/44.pl b/2022/44.pl
new file mode 100755 (executable)
index 0000000..ee6ade3
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/perl -w
+
+use v5.36;
+use strict;
+
+local $/ = "\n\n";
+my @map = map { chomp; [ split // ] } split /\n/, scalar <>;
+my $ymax = $#map;
+
+local $/ = "\n";
+chomp (my $list = <>);
+
+my $dir = 0;
+my $dim;
+my ($x, $y) = (0, 0);
+$x++ while $map[$y][$x] eq ' ';
+
+my %face_ndir = (
+       A => [ 1, 1, 1, 3],
+       B => [ 0, 0, 0, 0],
+       C => [ 0, 1, 2, 3],
+       D => [ 2, 2, 2, 2],
+       E => [ 3, 1, 3, 3],
+       F => [ 2, 1, 0, 3],
+);
+my %face_next = (
+       A => [ qw(D C B F) ],
+       B => [ qw(C E F A) ],
+       C => [ qw(D E B A) ],
+       D => [ qw(F E C A) ],
+       E => [ qw(D F B C) ],
+       F => [ qw(D A B E) ],
+);
+
+my %face_of;
+my %face_dir;
+if ($Y::AoC::Task::in_test) {
+       $dim = 4;
+       %face_of = (
+               '20' => 'A',
+               '11' => 'B',
+               '21' => 'C',
+               '32' => 'D',
+               '22' => 'E',
+               '01' => 'F',
+       );
+       %face_dir = (
+               A => 0,
+               B => 0,
+               C => 0,
+               D => 1,
+               E => 0,
+               F => 2,
+       );
+} else {
+       $dim = 50;
+       %face_of = (
+               '10' => 'A',
+               '02' => 'B',
+               '11' => 'C',
+               '20' => 'D',
+               '12' => 'E',
+               '03' => 'F',
+       );
+       %face_dir = (
+               A => 0,
+               B => 3,
+               C => 0,
+               D => 3,
+               E => 0,
+               F => 1,
+       );
+}
+
+
+my %pos_of = reverse %face_of;
+sub pos_of($face) {
+       return map { $dim * $_ } split //, $pos_of{$face};
+}
+
+sub face_of($x, $y) {
+       return undef if $x < 0 || $y < 0;
+       my $fx = int($x/$dim);
+       my $fy = int($y/$dim);
+       return $face_of{"$fx$fy"};
+}
+
+sub move($sx, $sy, $dir) {
+       my $f1 = face_of($sx, $sy);
+       my ($dx, $dy) = ($sx, $sy);
+       if ($dir == 0) {
+               $dx++;
+       } elsif ($dir == 1) {
+               $dy++;
+       } elsif ($dir == 2) {
+               $dx--;
+       } elsif ($dir == 3) {
+               $dy--;
+       }
+       my $f2 = face_of($dx, $dy);
+       if (defined($f2) && $f2 eq $f1) {
+               return ($dx, $dy, $dir);
+       }
+       my $ndir;
+       say "moving from $f1 $dir";
+       my $rdir = ($dir - $face_dir{$f1}) % 4;
+       say "rdir = $rdir";
+       $f2 = $face_next{$f1}[$rdir];
+       my $rdir2 = $face_ndir{$f1}[$rdir];
+       say "rdir2 = $rdir";
+       $ndir = ($rdir2 + $face_dir{$f2}) % 4;
+       my ($nx, $ny) = ($dx % $dim, $dy % $dim);
+       my $rot = ($ndir - $dir) % 4;
+       say "$sx,$sy $nx,$ny $f1 -> $f2 r$rot $dir -> $ndir";
+       while ($rot--) {
+               # ($nx, $ny) = ($ny, (-$nx % $dim));
+               ($nx, $ny) = ((($dim-1-$ny) % $dim), $nx);
+               say "rot -> $nx,$ny";
+       }
+       say " -> $nx $ny $ndir";
+       my ($ox, $oy) = pos_of($f2);
+       $nx += $ox;
+       $ny += $oy;
+       say " -> $nx $ny";
+       say "FACE $sx,$sy,$dir $f1 -> $nx,$ny,$ndir $f2";
+       die if $map[$ny][$nx] eq ' ';
+       return ($nx, $ny, $ndir);
+}
+
+while (length $list) {
+       $list =~ s/^(\d+|[LR])//;
+       my $move = $1;
+       say "$x $y $dir $move";
+       if ($move =~ /\d+/) {
+               while ($move) {
+                       my ($dx, $dy, $ddir) = move($x, $y, $dir);
+                       last if $map[$dy][$dx] eq '#';
+                       $x = $dx; $y = $dy; $dir = $ddir;
+                       say "   $x $y $dir $move";
+                       $move--;
+               }
+       } elsif ($move eq 'L') {
+               $dir = 3 if --$dir < 0;
+       } elsif ($move eq 'R') {
+               $dir = 0 if ++$dir > 3;
+       }
+}
+
+say 1000*($y+1) + 4*($x+1) + $dir;