Algorithm-X-DLX

 view release on metacpan or  search on metacpan

examples/polyomino/Shape.pm  view on Meta::CPAN

package Shape;
use strict;
use warnings;

use List::Util qw(reduce);
use Carp;

sub new {
  my ($class, $name, $bits) = @_;
  # Handle different constructor calls 
  if (!defined $name) {
    #return bless { name => '#', bits => [], width => 0, height => 0 }, $class;
    $name = '#';
    $bits = [];
  } elsif (ref($name) eq 'ARRAY') {
    #return bless { name => '#', bits => $name, width => @{$name ? $name->[0] : []}, height => scalar @$name }, $class;
    $bits = $name;
    $name = '#';
  }
  my $self = {
    name => $name,
    bits => $bits,
    width => (@$bits ? scalar @{$bits->[0]} : 0),
    height => scalar @$bits,
  };
  # Assert that all rows have the same width
  $self->{content} = '';
  for my $row (@$bits) {
    croak "Row width mismatch" unless @$row == $self->{width};
    $self->{content} .= join('', @$row) . ',';
  }
  return bless $self, $class;
}

sub pentominoes {
  return (
    Shape->new('I', [[1, 1, 1, 1, 1]]),
    Shape->new('N', [[1, 1, 1, 0], [0, 0, 1, 1]]),
    Shape->new('L', [[1, 1, 1, 1], [1, 0, 0, 0]]),
    Shape->new('Y', [[1, 1, 1, 1], [0, 1, 0, 0]]),
    Shape->new('P', [[1, 1, 1], [1, 1, 0]]),
    Shape->new('C', [[1, 1, 1], [1, 0, 1]]),
    Shape->new('V', [[1, 1, 1], [1, 0, 0], [1, 0, 0]]),
    Shape->new('T', [[1, 1, 1], [0, 1, 0], [0, 1, 0]]),
    Shape->new('F', [[1, 1, 0], [0, 1, 1], [0, 1, 0]]),
    Shape->new('Z', [[1, 1, 0], [0, 1, 0], [0, 1, 1]]),
    Shape->new('W', [[1, 1, 0], [0, 1, 1], [0, 0, 1]]),
    Shape->new('X', [[0, 1, 0], [1, 1, 1], [0, 1, 0]]),
  );
}

sub rotate {
  my ($self) = @_;
  my @rows = map { [(undef) x $self->{height}] } (1 .. $self->{width});
  for my $y (0 .. $self->{height} - 1) {
    for my $x (0 .. $self->{width} - 1) {
      $rows[$x][$self->{height} - $y - 1] = $self->{bits}[$y][$x];
    }
  }
  return Shape->new($self->{name}, \@rows);
}

sub reflect {
  my ($self) = @_;
  my @rows = map { [reverse @$_] } @{$self->{bits}};
  return Shape->new($self->{name}, \@rows);
}

sub rotations {
  my ($self) = @_;
  my @result = ($self);
  my $shape = $self->rotate();
#TODO: compare shapes
  while ($shape->not_equals($result[0])) {
    push @result, $shape;
    $shape = $shape->rotate();
  }
  return @result;
}

sub reflections {
  my ($self) = @_;
  my @refl = ($self->reflect());
  for my $rot ($self->rotations()) {
#TODO: compare shapes
    return ($self) if $rot->equals($refl[0]);
  }
  return ($self, @refl);
}

sub variations {
  my ($self) = @_;



( run in 2.047 seconds using v1.01-cache-2.11-cpan-d7f47b0818f )