In how many different ways can two knights and two rooks be placed on $6\times 6$ chessboard so that no one attacks the others?
what is your formula for this question
3
$\begingroup$
combinatorics
-
0What is your formula so far? – 2017-01-23
-
0I doubt that there's a "formula". The rooks cover two rows and two columns, but the count of knight placements will depend on which two. It's not hard to write a program to enumerate the possibilities. – 2017-01-23
-
0i dont know program but i want to learn answers and solutions :) – 2017-01-23
-
0Start by putting the first rook. THanks to the symmetry, you have, essentially, only $6$ possible places. Then put the second and so on... – 2017-01-23
1 Answers
0
I don't have a formula, but I brute forced it for you, using the same script I provided in your question on an other website.
setX($x);
$this->setY($y);
}
/**
* @return int
*/
public function getX()
{
return $this->x;
}
/**
* @param $x
* @return $this
*/
public function setX($x)
{
$this->x = $x;
return $this;
}
/**
* @return int
*/
public function getY()
{
return $this->y;
}
/**
* @param $y
*/
public function setY($y)
{
$this->y = $y;
}
/**
* @param Point $p
* @return bool
*/
public function equals(Point $p)
{
return ($this->getX() == $p->getX() && $this->getY() == $p->getY());
}
/**
* used for debugging
*
* @return string
*/
public function __toString()
{
return '('.$this->x.', '.$this->y.')';
}
}
interface PieceInterface
{
/**
* @param Point $p
* @return bool
*/
public function attack(Point $p);
}
abstract class Piece implements PieceInterface
{
/**
* @var Point
*/
protected $position;
/**
* @var string
*/
protected $notation = '';
/**
* Piece constructor.
* @param Point|null $position
*/
public function __construct(Point $position = null)
{
$this->position = $position;
}
/**
* @return Point
*/
public function getPosition()
{
return $this->position;
}
/**
* @return mixed
*/
public function getNotation()
{
return $this->notation;
}
/**
* @param Point $position
*/
public function setPosition($position)
{
$this->position = $position;
}
/**
* used for debugging
* @return string
*/
public function __toString()
{
return $this->notation.$this->getPosition();
}
public abstract function attack(Point $p);
}
class Rook extends Piece implements PieceInterface
{
/**
* @var string
*/
protected $notation = 'R';
/**
* @param Point $p
* @return bool
*/
public function attack(Point $p)
{
if (!$this->position) {
return false;
}
return ($this->getPosition()->getX() == $p->getX() || $this->getPosition()->getY() == $p->getY());
}
}
class Knight extends Piece implements PieceInterface
{
/**
* @var string
*/
protected $notation = 'K';
/**
* @param Point $p
* @return bool
*/
public function attack(Point $p)
{
if (!$this->position) {
return false;
}
$thisX = $this->getPosition()->getX();
$thisY = $this->getPosition()->getY();
$pointX = $p->getX();
$pointY = $p->getY();
if (abs($thisX - $pointX) == 2 && abs($thisY - $pointY) == 1) {
return true;
}
if (abs($thisX - $pointX) == 1 && abs($thisY - $pointY) == 2) {
return true;
}
return false;
}
}
class App
{
/**
* board X size
* @var int
*/
private $boardX;
/**
* board Y size
* @var int
*/
private $boardY;
/**
* pieces to add on the table
* @var Piece[]
*/
protected $piecesToAdd = array();
/**
* all solutions
* @var string[]
*/
protected $solutions = array();
/**
* already added pieces
* @var Piece[]
*/
private $pieces = array();
/**
* App constructor.
* @param $boardX
* @param null $boardY
* @param $piecesToAdd
*/
public function __construct($piecesToAdd, $boardX, $boardY = null)
{
if (is_null($boardY)) {
$boardY = $boardX;
}
$this->boardX = $boardX;
$this->boardY = $boardY;
$this->piecesToAdd = $piecesToAdd;
}
/**
* add a piece on the board
* @param Piece $p
* @param Point $point
* @return bool
*/
public function addPiece(Piece $p, Point $point)
{
$p->setPosition($point);
$canPlace = true;
//check of the piece does not attack the other set pieces or if it's not attacked by one
foreach ($this->pieces as $piece) {
if (
$p->getPosition()->equals($piece->getPosition())
|| $p->attack($piece->getPosition()) ||
$piece->attack($p->getPosition())
) {
$canPlace = false;
}
}
if ($canPlace) {
$this->pieces[] = $p;
$this->pieces = array_values($this->pieces);
return true;
} else {
//if a piece cannot be added, move to the next position
$nextPoint = $this->incrementPoint($point);
if ($nextPoint) {
return $this->addPiece($p, $nextPoint);
}
}
//if there is no valid position return false
return false;
}
/**
* get the next position where you can add a piece if you need to move one
* @return bool|Point
*/
private function getNextPosition()
{
$nextPosition = false;
while (!$nextPosition) {
//remove last piece and increment the position for the previous one.
$piece = end($this->pieces);
if (!$piece) {
throw new ReachedEndException();
}
$position = clone $piece->getPosition();
$nextPosition = $this->incrementPoint($position);
$this->removePiece(count($this->pieces) - 1);
}
return $nextPosition;
}
/**
* do the dew
* @return App
*/
public function execute()
{
$currentPosition = new Point(0, 0);
$added = true;
while (true) {
while ($added && !$this->isBoardFilled()) {
$pieceToAdd = $this->piecesToAdd[count($this->pieces)];
$added = $this->addPiece($pieceToAdd, $currentPosition);
//if a piece was added start the next one from top left corner
if ($added) {
$currentPosition = new Point(0, 0);
}
}
//if we cannot add a piece, remove the last one(s) and check the next valid position
if (!$added) {
try {
$currentPosition = $this->getNextPosition();
} catch (ReachedEndException $e) {
//it means we cannot move anything arround anymore
return $this;
}
$added = true;
} elseif ($this->isBoardFilled()) {
//if the board is in a valid position save the state
$solution = $this->printBoardState();
//remember a hash of the position to avoid duplicates
$hash = sha1($solution);
$this->solutions[$hash] = $solution;
try {
$currentPosition = $this->getNextPosition();
} catch (ReachedEndException $e) {
//it means we are done
return $this;
}
} else {
$added = true;
//start over
$currentPosition = new Point(0, 0);
}
}
return $this;
}
/**
* form a readable string with the solutions
* @return string
*/
public function printSolutions()
{
$string = '';
$increment = 1;
foreach ($this->solutions as $solution) {
$string .= 'Solution '.$increment++.'
'.$solution.'
';
}
return $string;
}
/**
* remove a piece
* @param $index
* @return App
*/
private function removePiece($index)
{
unset($this->pieces[$index]);
return $this;
}
/**
* check if all pieces are on the board
* @return bool
*/
public function isBoardFilled()
{
return count($this->pieces) == count($this->piecesToAdd);
}
/**
* generate the board configuration string
* @param string $positionSeparator
* @param string $blank
* @param string $lineSeparator
* @return string
*/
private function printBoardState($positionSeparator = '|', $blank = '--', $lineSeparator = '
')
{
$board = array();
$text = '';
foreach ($this->pieces as $piece) {
$position = $piece->getPosition();
$board[$position->getX()][$position->getY()] = $piece->getNotation();
}
for ($i = 0;$i<$this->boardX; $i++) {
$text .= $positionSeparator;
for ($j = 0;$j<$this->boardY; $j++) {
if (isset($board[$i][$j])) {
$text .= $board[$i][$j];
} else {
$text .= $blank;
}
$text .= $positionSeparator;
}
$text .= $lineSeparator;
}
return $text;
}
/**
* get the next valid point
* @param Point $p
* @return bool|Point
*/
private function incrementPoint(Point $p)
{
if ($p->getX() == $this->boardX - 1) {
if ($p->getY() == $this->boardY - 1) {
return false; //reached the end
}
return new Point(0, $p->getY() + 1);
}
return new Point($p->getX()+1, $p->getY());
}
/**
* take a whild guess
* @return string
*/
public function debug()
{
$string = "state: ";
foreach ($this->pieces as $piece) {
$string.= ' '.$piece.'--';
}
return $string.'
';
}
}
//configure the pieces to be added
$pieces = array(
new Rook(),
new Rook(),
new Knight(),
new Knight()
);
$boardSize = 6;
$app = new App($pieces, $boardSize);
//run it
$app->execute();
//see if it worked
echo $app->printSolutions();
and got 22248 results (including rotations and symmetrical positions).
The script is far from optimal, but it seams to work. You can try it yourself on http://phpfiddle.org/