Algorithm-X-DLX

 view release on metacpan or  search on metacpan

lib/Algorithm/X/LinkedMatrix.pm  view on Meta::CPAN

package Algorithm::X::LinkedMatrix;

use strict;
use warnings;

require 5.06.0;

use Carp;
use Algorithm::X::ExactCoverProblem;

sub new {
  my ($class, $problem) = @_;

  my $self = {
    col_ids => [],
    sizes   => [(0) x $problem->width()],
    nodes   => [],
  };
  bless $self, $class;

  my $root = $self->create_node(~0, ~0);
  croak "Root ID mismatch" unless $root == $self->root_id();

  for my $x (0 .. $problem->width() - 1) {
    my $id = $self->create_node($x, ~0);
    $self->{col_ids}[$x] = $id;
    if ($x >= $problem->secondary_columns()) {
      $self->{nodes}[$id]{r} = $root;
      $self->{nodes}[$id]{l} = $self->L($root);
      $self->{nodes}[$self->L($root)]->{r} = $id;
      $self->{nodes}[$root]->{l} = $id;
    }
  }

  for my $y (0 .. $#{$problem->rows()}) {
    $self->add_row($y, $problem->rows()->[$y]);
  }

  return $self;
}

sub add_row {
  my ($self, $y, $xs) = @_;

  my $first_id = 0;

  for my $x (@$xs) {
    my $id = $self->create_node($x, $y);
    $self->{nodes}[$id]{d} = $self->C($id);
    $self->{nodes}[$id]{u} = $self->U($self->C($id));
    $self->{nodes}[$self->U($self->C($id))]->{d} = $id;
    $self->{nodes}[$self->C($id)]->{u} = $id;
    $self->{sizes}[$x]++;

    if ($first_id == 0) {
      $first_id = $id;

    } else {
      $self->{nodes}[$id]{r} = $first_id;
      $self->{nodes}[$id]{l} = $self->L($first_id);
      $self->{nodes}[$self->L($first_id)]->{r} = $id;
      $self->{nodes}[$first_id]->{l} = $id;
    }
  }
}

sub cover_column {
  my ($self, $c) = @_;
  $c = $self->C($c);

  $self->{nodes}[$self->L($c)]->{r} = $self->R($c);
  $self->{nodes}[$self->R($c)]->{l} = $self->L($c);
  
  for (my $i = $self->D($c); $i != $c; $i = $self->D($i)) {
    for (my $j = $self->R($i); $j != $i; $j = $self->R($j)) {
      $self->{nodes}[$self->U($j)]->{d} = $self->D($j);
      $self->{nodes}[$self->D($j)]->{u} = $self->U($j);
      $self->{sizes}[$self->X($j)]--;
    }
  }
}

sub uncover_column {
  my ($self, $c) = @_;
  $c = $self->C($c);
  
  for (my $i = $self->U($c); $i != $c; $i = $self->U($i)) {



( run in 0.864 second using v1.01-cache-2.11-cpan-39bf76dae61 )