--- /dev/null
+#!/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, $_);
+}
+