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

