use strict;
-local $/ = "\n\n";
+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 invbits {
- my ($in) = @_;
- return (($in & 1) << 9)
- | (($in & 2) << 7)
- | (($in & 4) << 5)
- | (($in & 8) << 3)
- | (($in & 16) << 1)
- | (($in & 32) >> 1)
- | (($in & 64) >> 3)
- | (($in & 128) >> 5)
- | (($in & 256) >> 7)
- | (($in & 512) >> 9);
+sub rotate_or_flip {
+ my ($str, $count) = @_;
+ return $count == 4 ? flip($str) : rotate($str);
}
-my %tiles;
-my %sides;
-my %side2tiles;
+sub top_side {
+ $_[0] =~ /\A(.*?)\n/xms;
+ return $1;
+}
+
+my %top2tile;
+
+local $/ = "\n\n";
+
while (<>) {
- my ($id, @rows) = split /\n/;
- $id =~ s/Tile //;
- $id =~ s/://;
- @rows = map { y/#./10/; oct "0b$_" } @rows;
- $tiles{$id} = \@rows;
- $sides{$id} = [
- $rows[0],
- (($rows[0] & 1) << 9)
- | (($rows[1] & 1) << 8)
- | (($rows[2] & 1) << 7)
- | (($rows[3] & 1) << 6)
- | (($rows[4] & 1) << 5)
- | (($rows[5] & 1) << 4)
- | (($rows[6] & 1) << 3)
- | (($rows[7] & 1) << 2)
- | (($rows[8] & 1) << 1)
- | (($rows[9] & 1) << 0),
- $rows[9],
- (($rows[0] & 512) >> 0)
- | (($rows[1] & 512) >> 1)
- | (($rows[2] & 512) >> 2)
- | (($rows[3] & 512) >> 3)
- | (($rows[4] & 512) >> 4)
- | (($rows[5] & 512) >> 5)
- | (($rows[6] & 512) >> 6)
- | (($rows[7] & 512) >> 7)
- | (($rows[8] & 512) >> 8)
- | (($rows[9] & 512) >> 9),
- ];
- print "Tile <$id> sides ", join(',', @{ $sides{$id} }), "\n";
- for my $side (@{ $sides{$id} }) {
- push @{ $side2tiles{$side} }, $id;
- push @{ $side2tiles{invbits($side)} }, $id;
+ my ($id, $data) = /\ATile\s+(\d+):\n(.*?\n)\n?\z/xms;
+ for (1 .. 8) {
+ push @{ $top2tile{top_side($data)} }, $id;
+ $data = rotate_or_flip($data, $_);
}
}
my %single_ids;
-for my $side (keys %side2tiles) {
- print "side $side: ", join(',', @{ $side2tiles{$side} }), "\n";
- # print "inv ", invbits($side), "\n";
- if (scalar @{ $side2tiles{$side} } == 1
- && scalar @{ $side2tiles{invbits($side)} } == 1) {
- print "side $side of tile $side2tiles{$side}->[0] is single\n";
- $single_ids{$side2tiles{$side}->[0]}++;
- }
-
+for my $row (keys %top2tile) {
+ next if @{ $top2tile{$row} } != 1;
+ $single_ids{ $top2tile{$row}->[0] }++;
}
my @corners = grep { $single_ids{$_} == 4 } keys %single_ids;
-print join('*', @corners), '=', eval join('*', @corners), "\n"
-
+print join('*', @corners), '=', eval join('*', @corners), "\n";