Javascript: Stuck On Diagonal Validation Of Two Queens And If They Can Attack Each Other
Solution 1:
In continuation from comments, this solution treats "position" as an integer between 0 and 63, where row and column can be derived from that using "arithmetic progression" logic. A row can be derived by the floor part on division by 8. A column can be derived from modulus on 8.
In this way only two loops are needed. A double loop is used so that each Queen1 (Q1) position is compared to Q2's position. Like your alg specifies, a condition is there to exclude when both Q1 and Q2 occupies the same square. The rest of the logic is explained in code comments.
On notable difference from your algorithm, is that this solution tries to solve for when an attack can be made. The return value must handle when positions can't be made, by deduction.
Disclaimer: This may not be the solution since OP doesn't know the correct return value beforehand. This is just a code attempt.
// What is the total number of positions that two queens can exist on a chess board where they cannot attack each other?functionanswer() {
varQ1;
varQ2;
var cnt = 0; // count of when they can attack each otherfor (Q1 = 0; Q1 < 64; Q1++) {
//console.log(Q1);let Q1_y = Math.floor(Q1 / 8); // 0..7 ~ 0, 8..15 ~ 1, and so onlet Q1_x = Q1 % 8;
// console.log(Q1_x + ", " + Q1_y);for (Q2 = 0; Q2 < 64; Q2++) {
let Q2_y = Math.floor(Q2 / 8); // 0..7 ~ 0, 8..15 ~ 1, and so onlet Q2_x = Q2 % 8;
if (Q1 != Q2) {
// rule out both on same squarelet canAttack = false;
// Now determine if on same Xif (Q1_x == Q2_x) {
canAttack = true;
}
// Now determine if on same Yif (Q1_y == Q2_y) {
canAttack = true;
}
// Now determine if on same diagnoallet diag = (Math.abs(Q1_x - Q2_x) / Math.abs(Q1_y - Q2_y)) == 1;
if (diag) {
canAttack = true;
}
// Update count for this square comboif (canAttack) {
cnt++;
}
}
}
}
// console.log (cnt);return ((64 * 64) - 64) - cnt; // 64*64 total space pairs, minus the 64 times they are on same square, minus the number of times they *can* attack
}
console.log (answer());
Solution 2:
For the fun of it, here's another take on the problem..
In this case, the standard means of using bitboards for chess programming is employed to represent the possible movement of the pieces. That is, a Uint64 number is used as a bit mask to represent the possible moves of a rook, bishop, or queen. Since there are 64 squares on the board, there is a need for 64 of these Uint64 bit masks, to represent the possible moves for the piece on each square.
To help visualize this, the script below prints out the rook, bishop, and queen bitboard for square 'd3' (which is the 19th of the 64 squares in the piece array).
Once the bit boards are built, the effort to determine whether two queens attack each other is trivial, as it is simply a matter of logically ANDing the first queen's movement bitboard with the bitboard representing the square that the second queen sits on, and if the result is 0, then they are not attacking each other.
As an aside, this method arrives at 2576 combinations of a pair of queens not attacking each other...
// Establish array with each bitboard representing the square on the board// that the bitboard index represents.let squares = newBigUint64Array( 64 ).map( ( v , i ) =>1n << BigInt( i ) );
// Generate possible moves for Rooks and Bishops for each square// that they can occupy.let rookMoves = newBigUint64Array( 64 );
let bishopMoves = newBigUint64Array( 64 );
for ( pieceRank = 0; pieceRank < 8; pieceRank++ ) {
for ( pieceFile = 0; pieceFile < 8; pieceFile++ ) {
let squareIndex = pieceRank * 8 + pieceFile;
let rookMap = 0n;
let bishopMap = 0n;
for ( let r = 0; r < 8; r++ ) {
for ( let f = 0; f < 8; f++ ) {
let rf = r * 8 + f;
if ( ( r === pieceRank || f === pieceFile ) && rf !== squareIndex ) {
rookMap |= squares[ rf ];
}
if ( ( Math.abs( r - pieceRank ) === Math.abs( f - pieceFile ) ) && rf !== squareIndex ) {
bishopMap |= squares[ rf ];
}
}
}
rookMoves[ squareIndex ] = rookMap;
bishopMoves[ squareIndex ] = bishopMap;
}
}
// Generate the possible moves for Queens for each square that// they can occupy. This is done my looping through the Rook// moves and simply ORing with the bishop moves.let queenMoves = rookMoves.map( ( v, i ) => v | bishopMoves[ i ] );
// Helper function to print out the bitmap as a board, where 'X' // represents a bit that is set to 1 and '-' a bit that is set to '0'.functionprintBitMap( bitBoard ) {
let bm = '';
for ( rank = 7; 0 <= rank; rank-- ) {
for ( file = 0; file < 8; file++ ) {
bm += bitBoard & squares[ rank * 8 + file ] ? ' X ' : ' - ';
}
bm += '\n';
}
return bm + '\n';
}
// Let's print the bitmaps for the rook, bishop, and queen at square d3,// which is rank 2 ( range 0 - 7 ) file 3, or 2 * 8 + 3 which is square// index 19.console.log( 'Rook, Bishop, and Queen moves from square d3:' );
console.log( printBitMap( rookMoves[ 19 ] ) );
console.log( printBitMap( bishopMoves[ 19 ] ) );
console.log( printBitMap( queenMoves[ 19 ] ) );
// Now that the bitmaps are set up, the effort is simple... Loop through// all combinations of two queens on the board...let nonIntersectCount = 0;
for ( let Q1square = 0; Q1square < 64; Q1square++ ) {
for ( let Q2square = 0; Q2square < 64; Q2square++ ) {
// ...and if the queens are not on the same square and the intersection of// the possible moves for Q1 with the Q2 square is 0 bits, then we have// a situation where the queens are not attacking each other... if ( Q1square !== Q2square && ( queenMoves[ Q1square ] & squares[ Q2square ] ) === 0n ) {
nonIntersectCount++;
}
}
}
console.log( 'For every combination of 2 queens on a board, the number of combinations where they do not attack each other is:' );
console.log( nonIntersectCount );
Note also that BigUint64Array as of Jan 2021 has wide browser support, except for Safari. That being the case, and if Safari support is critical to the problem at hand, then one might want to consider reworking this solution using Uint32Array...
Post a Comment for "Javascript: Stuck On Diagonal Validation Of Two Queens And If They Can Attack Each Other"