Algorithm-X-DLX

 view release on metacpan or  search on metacpan

examples/t/sudoku/01-sudoku.t  view on Meta::CPAN

  is(join('',
    "..|.4\n",
    "2.|..\n",
    "--|--\n",
    ".1|..\n",
    "..|1.\n"
  ), $sudoku->to_string_format($format), 'to_string_format');
};
subtest 'from_string' => sub {
  plan tests => 26;
  throws_ok { Sudoku->new("") } qr/Got empty string/i, 'needs char';
  lives_ok { Sudoku->new(".") } 'empty cell suffices';
  lives_ok { Sudoku->new("0") } '1 cell suffices';
  lives_ok { Sudoku->new("1") } '1 cell suffices';
  lives_ok { Sudoku->new("( 1 )") } '1 cell suffices';

  lives_ok { Sudoku->new("2") } '1 cell suffices';
  lives_ok { Sudoku->new("A") } '1 cell suffices';
  lives_ok { Sudoku->new("z") } '1 cell suffices';

  throws_ok { Sudoku->new("ABCD .... .... ...E") } qr/Too many different labels/i, 'labels exceed n';
  lives_ok { Sudoku->new("ABCD .... .... ...A") } 'labels == n';

  my $sudoku = Sudoku->new(join '', 
    "1.|..",
    "..|.2",
    "-----",
    ".1|..",
    "..|3."
  );
  is( 1, $sudoku->get_value(0) );

examples/t/sudoku/02-sudokutype.t  view on Meta::CPAN

  plan tests => 12;
	is(1,  SudokuType->new(1)->n(), '1x1 field width');
	is(1,  SudokuType->new(1)->size(), '1x1 field size');
	is(4,  SudokuType->new(4)->n(), '4x4 fields width');
	is(16,  SudokuType->new(4)->size(), '4x4 fields size');
	is(9,  SudokuType->new(9)->n(), '9x9 fields width');
	is(81,  SudokuType->new(9)->size(), '9x9 fields size');
	is(16,  SudokuType->new(16)->n(), '16x16 fields width');
	is(256,  SudokuType->new(16)->size(), '16x16 fields size');

	throws_ok { SudokuType->new(0) }    qr/Sudoku must have non-zero size/i, 'invalid size param';
	throws_ok { SudokuType->new(3) }    qr/Not a square/i, 'invalid size param';
	throws_ok { SudokuType->new(5) }    qr/Not a square/i, 'invalid size param';
	throws_ok { SudokuType->new(8) }    qr/Not a square/i, 'invalid size param';
};

subtest 'creator nxm region' => sub {
  plan tests => 9;
	throws_ok { SudokuType->new(0, 5) }    qr/Sudoku must have non-zero/i, 'invalid width param';
	throws_ok { SudokuType->new(5, 0) }    qr/Sudoku must have non-zero/i, 'invalid height param';

	is(1,  SudokuType->new(1, 1)->n(), '1x1 field width');
	is(2,  SudokuType->new(1, 2)->n(), '1x1 field size');
	is(2,  SudokuType->new(2, 1)->n(), '4x4 fields width');
	is(9,  SudokuType->new(1, 9)->n(), '4x4 fields size');

	is(6,  SudokuType->new(2, 3)->n(), '9x9 fields width');
	is(8,  SudokuType->new(2, 4)->n(), '9x9 fields size');
	is(10,  SudokuType->new(2, 5)->n(), '16x16 fields width');
};

subtest 'creator custom region' => sub {
  plan tests => 10;
	throws_ok { SudokuType->new([]) }    qr/Sudoku must have non-zero/i, 'not a square';
	throws_ok { SudokuType->new([0, 1]) }    qr/Not a square/i, 'not a square';

	throws_ok { SudokuType->new([0, 0, 0, 1]) }    qr/Region has wrong size/i, 'invalid region';
	throws_ok { SudokuType->new([0, 0, 1, 2]) }    qr/Too many regions/i, 'invalid region';

	lives_ok { SudokuType->new([0]) } 'valid type';
	lives_ok { SudokuType->new([1]) } 'valid type';
	lives_ok { SudokuType->new([999]) } 'valid type';
	lives_ok { SudokuType->new([0, 0, 1, 1]) } 'valid type';
	lives_ok { SudokuType->new([0, 1, 1, 0]) } 'valid type';

	is_deeply(SudokuType->new([0, 0, 1, 1]),  SudokuType->new([6, 6, 2, 2]), 'same custom type');
};

subtest 'guess type nxn regions' => sub {
  plan tests => 7;
	throws_ok { SudokuType::guess(join '',
    "....",
    "....",
    "....",
    "..."
  ) } qr/Not a square/i, 'corrupt lines';
	throws_ok { SudokuType::guess(join '',
    "....",
    "....",
    "....",
    "....."
  ) } qr/Not a square/i, 'corrupt lines';
	is_deeply(SudokuType->new(1),  SudokuType::guess(join '',
    "+-+\n",
    "|.|\n",
    "+-+\n"
  ), 'same custom type');

examples/t/sudoku/03-sudokusolver.t  view on Meta::CPAN

    "| -----   |   |\n",
    "|5 6|2 4 3|7 1|\n",
    "|   |   ----- |\n",
    "|1 7|6 5|2 3|4|\n",
    "| -------   --|\n",
    "|3|4 7 2|5 1 6|\n",
    "| |     ---   |\n",
    "|2|5 1 3 6|4 7|\n",
    "---------------\n"
  );
  throws_ok { SudokuSolver::solve($puzzle1) } qr/No solution/i, 'impossible regions';
  is_deeply( $solved2, SudokuSolver::solve($puzzle2), 'correct solution');
};

subtest 'no solution' => sub {
  plan tests => 1;
  throws_ok { SudokuSolver::solve(Sudoku->new(join '',
    "12|3.",
    "..|..",
    "-----",
    "23|1.",
    "..|.."
  )) } qr/No solution/i, 'give up';
};

subtest 'multiple solutions' => sub {
  plan tests => 2;
  lives_ok { SudokuSolver::solve(Sudoku->new(join '',
    "12|34",
    ".3|21",
    "-----",
    "..|12",
    "21|43"
  )) } 'passes';
  throws_ok { SudokuSolver::solve(Sudoku->new(join '',
    "12|34",
    "..|21",
    "-----",
    "..|12",
    "21|43"
  )) } qr/Multiple solutions/i, 'give up';
};

done_testing();

t/02-exactcoverproblem.t  view on Meta::CPAN


use Test::More tests => 2;
use Test::Exception;

use Algorithm::X::ExactCoverProblem;

# Tests

subtest 'constructor' => sub {
  plan tests => 7;
  throws_ok { Algorithm::X::ExactCoverProblem->new(0, [[0]]) }    qr/column out of range/i, 'size mismatch';
  throws_ok { Algorithm::X::ExactCoverProblem->new(1, [[1]]) }    qr/column out of range/i, 'size mismatch';
  throws_ok { Algorithm::X::ExactCoverProblem->new(5, [[5]]) }    qr/column out of range/i, 'size mismatch';
  throws_ok { Algorithm::X::ExactCoverProblem->new(1, [[0, 0]]) } qr/duplicate columns/i, 'duplicate columns';

  lives_ok { Algorithm::X::ExactCoverProblem->new(1, [[0]]) } 'size matches';
  lives_ok { Algorithm::X::ExactCoverProblem->new(2, [[1]]) } 'size matches';
  lives_ok { Algorithm::X::ExactCoverProblem->new(6, [[5]]) } 'size matches';
};

subtest 'dense matrix' => sub {
  plan tests => 9;
  throws_ok { Algorithm::X::ExactCoverProblem->dense([[0], []]) }    qr/rows have different lengths/i, 'row size mismatch';
  throws_ok { Algorithm::X::ExactCoverProblem->dense([[2]]) }    qr/dense matrix must contain only 0s and 1s/i, 'non boolean content';
  throws_ok { Algorithm::X::ExactCoverProblem->dense([[0], 2]) }    qr/Can't use string \("2"\) as an ARRAY ref/i, 'corrupted matrix';

  lives_ok { Algorithm::X::ExactCoverProblem->dense([]) } 'size matches';
  lives_ok { Algorithm::X::ExactCoverProblem->dense([[], []]) } 'size matches';
  lives_ok { Algorithm::X::ExactCoverProblem->dense([[0], [1]]) } 'size matches';
  lives_ok { Algorithm::X::ExactCoverProblem->dense([[0]], 1) } 'size matches';

  is 0, Algorithm::X::ExactCoverProblem->dense([[]])->width(), 'empty matrix width';
  is 2, Algorithm::X::ExactCoverProblem->dense([[0, 0]])->width(), 'column count';
};



( run in 0.382 second using v1.01-cache-2.11-cpan-496ff517765 )