]> www.fi.muni.cz Git - aoc.git/blobdiff - 2020/40.pl
Moved 2020 to a subdir
[aoc.git] / 2020 / 40.pl
diff --git a/2020/40.pl b/2020/40.pl
new file mode 100755 (executable)
index 0000000..074e561
--- /dev/null
@@ -0,0 +1,124 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+sub rows2str {
+       my (@rows) = @_;
+       return join("\n", @rows) . "\n";
+}
+
+sub rotate {
+       my ($str) = (@_);
+       my $dim =()= $str =~ /(\n)/g;
+       my $newstr = '';
+       for my $y (0 .. $dim-1) {
+               for my $x (0 .. $dim-1) {
+                       $newstr .= substr($str, $y + ($dim+1)*($dim - $x - 1), 1);
+               }
+               $newstr .= "\n";
+       }
+       return $newstr;
+}
+
+sub flip {
+       my ($str) = @_;
+       return rows2str(map { join('', reverse split //) } split /\n/, $str);
+}
+
+sub rotate_or_flip {
+       my ($str, $count) = @_;
+       return $count == 4 ? flip($str) : rotate($str);
+}
+
+sub trim {
+       my ($str) = @_;
+       my @rows = split /\n/, $str;
+       shift @rows;
+       pop @rows;
+       return map { s/\A.//; s/.\z//; $_ } @rows;
+}
+
+sub top_side {
+       $_[0] =~ /\A(.*?)\n/xms;
+       return $1;
+}
+
+sub bottom_side {
+       $_[0] =~ /\A.*\n(.*?)\n\z/xms;
+       return $1;
+}
+
+sub left_side {
+       return join('', map { substr($_, 0, 1) } split /\n/, $_[0]);
+}
+
+sub right_side {
+       return join('', map { substr($_, -1, 1) } split /\n/, $_[0]);
+}
+
+my (%top2tile, %left2tile);
+
+local $/ = "\n\n";
+
+while (<>) {
+       my ($id, $data) = /\ATile\s+(\d+):\n(.*?\n)\n?\z/xms;
+       for (1 .. 8) {
+               push @{ $top2tile{top_side($data)} }, [ $id, $data ];
+               push @{ $left2tile{left_side($data)} }, [ $id, $data ];
+               $data = rotate_or_flip($data, $_);
+       }
+}
+
+# computed in 39.pl
+my $dim = 12;
+my $top_row = '###.#.#...';
+
+# my $dim = 3;
+# my $top_row = '#...##.#..';
+
+my $top_id = -1;
+my @map_rows;
+my $data;
+
+for my $y (0 .. $dim-1) {
+       my ($id)  = grep { $_->[0] != $top_id } @{ $top2tile{$top_row} };
+       ($top_id, $data) = @$id;
+       $top_row = bottom_side($data);
+
+       push @map_rows, trim($data);
+
+       my $right_id = $top_id;
+       my $right_row = right_side($data);
+
+       for my $x (1 .. $dim-1) {
+               my ($id) = grep { $_->[0] != $right_id } @{ $left2tile{$right_row} };
+               ($right_id, $data) = @$id;
+               $right_row = right_side($data);
+
+               my $i = @map_rows - 8;
+               for (trim($data)) {
+                       $map_rows[$i++] .= $_;
+               }
+       }
+}
+
+my $map = rows2str(@map_rows);
+my $hashes =()= $map =~ /#/g;
+
+my $monster = '.(?='
+       . join('[\.#\n]' x ($dim * 8 - 20 + 1),
+               map { my $a=$_; $a=~ s/\./[\.#]/g; $a }
+                '..................#.',
+               '#....##....##....###',
+               '.#..#..#..#..#..#...'
+       ) . ')';
+
+for (1 .. 8) {
+       if (my $count =()= $map =~ /($monster)/g) {
+               print "$count matches\n";
+               print "$hashes-$count*15=", $hashes-$count*15, "\n";
+               exit 0;
+       }
+       $map = rotate_or_flip($map, $_);
+}
+