Given a N x N chessboard and the position of X bishops on it, the task is to calculate the count of pairs of bishops such that they attack each other. Note that while considering a pair of bishops, all the other bishops are not considered to be on the board.
Example:
Input: N = 5, bishops[][] = {{2, 1}, {3, 2}, {2, 3}}
Output: 2
Explanation: The bishops on the positions {2, 1} and {3, 2} and bishops on the positions {3, 2} and {2, 3} attack each other.Input: N = 10, bishops[][] = {{1, 1}, {1, 5}, {3, 3}, {5, 1}, {5, 5}}
Output: 6
Approach: The given problem can be solved using basic combinatorics. Since all the bishops that lie on the same diagonal will attack each other, all possible pairs of bishops that are on the same diagonal that can be formed will attack each other. Therefore, traverse the matrix for all diagonals in both left and right directions and count the number of bishops on the current diagonal in a variable cnt. Now for each diagonal, the number of attacking bishops will be cntC2.
Below is the implementation of the above approach:
#include <bits/stdc++.h>
using namespace std;
int board[20][20];
int countPairs(int N, vector<pair<int, int> > bishops)
{
// Set all bits to 0
memset(board, 0, sizeof(board));
// Set all the bits
// having bishop to 1
for (int i = 0; i < bishops.size(); i++) {
board[bishops[i].first][bishops[i].second] = 1;
}
// Stores the final answer
int ans = 0;
// Loop to traverse the matrix
// diagonally in left direction
for (int s = 2; s <= 2 * N; s++) {
// Stores count of bishop
// in the current diagonal
int cnt = 0;
for (int i = 1, j = s - i;
max(i, j) <= min(N, s - 1); i++, j--) {
if (board[j][i - j] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Loop to traverse the matrix
// diagonally in right direction
for (int s = 2; s <= 2 * N; s++) {
// Stores count of bishop
// in the current diagonal
int cnt = 0;
for (int i = 1, j = s - i;
max(i, j) <= min(N, s - 1); i++, j--) {
if (board[i][N - j + 1] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Return answer
return ans;
}
// Driver code
int main()
{
int N = 10;
vector<pair<int, int> > bishops = {
{ 1, 1 }, { 1, 5 }, { 3, 3 }, { 5, 1 }, { 5, 5 }
};
cout << countPairs(N, bishops);
return 0;
}
import java.util.*;
class GFG
{
static int [][]board = new int[20][20];
static int countPairs(int N, int[][] bishops)
{
// Set all the bits
// having bishop to 1
for (int i = 0; i < bishops.length; i++) {
board[bishops[i][0]][bishops[i][1]] = 1;
}
// Stores the final answer
int ans = 0;
// Loop to traverse the matrix
// diagonally in left direction
for (int s = 2; s <= 2 * N; s++) {
// Stores count of bishop
// in the current diagonal
int cnt = 0;
for (int i = 1, j = s - i;
Math.max(i, j) <= Math.min(N, s - 1)&&i-j>0; i++, j--) {
if (board[j][i - j] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Loop to traverse the matrix
// diagonally in right direction
for (int s = 2; s <= 2 * N; s++) {
// Stores count of bishop
// in the current diagonal
int cnt = 0;
for (int i = 1, j = s - i;
Math.max(i, j) <= Math.min(N, s - 1); i++, j--) {
if (board[i][N - j + 1] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Return answer
return ans;
}
// Driver code
public static void main(String[] args)
{
int N = 10;
int[][] bishops = {
{ 1, 1 }, { 1, 5 }, { 3, 3 }, { 5, 1 }, { 5, 5 }
};
System.out.print(countPairs(N, bishops));
}
}
// This code is contributed by 29AjayKumar
# Python program for above approach
board = [[0 for i in range(20)] for j in range(20)]
def countPairs(N, bishops):
# Set all the bits
# having bishop to 1
for i in range(len(bishops)):
board[bishops[i][0]][bishops[i][1]] = 1
# Stores the final answer
ans = 0
# Loop to traverse the matrix
# diagonally in left direction
for s in range(2, (2 * N) + 1):
# Stores count of bishop
# in the current diagonal
cnt = 0
i = 1
j = s - i
while(max(i, j) <= min(N, s - 1)):
if (board[j][i - j] == 1):
# Update cnt
cnt += 1
i += 1
j -= 1
# Update the answer
if (cnt > 1):
ans += ((cnt + 1) * cnt) // 2
# Loop to traverse the matrix
# diagonally in right direction
for s in range(2, (2 * N) + 1):
# Stores count of bishop
# in the current diagonal
cnt = 0
i = 1
j = s - i
while(max(i, j) <= min(N, s - 1)):
if (board[i][N - j + 1] == 1):
# Update cnt
cnt += 1
i += 1
j -= 1
# Update the answer
if (cnt > 1):
ans += ((cnt + 1) * cnt) // 2
# Return answer
return ans
# Driver code
N = 10
bishops = [[1, 1], [1, 5], [3, 3], [5, 1], [5, 5]]
print(countPairs(N, bishops))
# This code is contributed by gfgking
using System;
class GFG
{
static int[,] board = new int[20,20];
static int countPairs(int N, int[,] bishops)
{
// Set all the bits
// having bishop to 1
for (int i = 0; i < bishops.GetLength(0); i++)
{
board[bishops[i,0], bishops[i,1]] = 1;
}
// Stores the final answer
int ans = 0;
// Loop to traverse the matrix
// diagonally in left direction
for (int s = 2; s <= 2 * N; s++)
{
// Stores count of bishop
// in the current diagonal
int cnt = 0;
for (int i = 1, j = s - i;
Math.Max(i, j) <= Math.Min(N, s - 1) && i - j > 0; i++, j--)
{
if (board[j,i - j] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Loop to traverse the matrix
// diagonally in right direction
for (int s = 2; s <= 2 * N; s++)
{
// Stores count of bishop
// in the current diagonal
int cnt = 0;
for (int i = 1, j = s - i;
Math.Max(i, j) <= Math.Min(N, s - 1); i++, j--)
{
if (board[i,N - j + 1] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Return answer
return ans;
}
// Driver code
public static void Main()
{
int N = 10;
int[,] bishops = new int[5, 2]{{ 1, 1 }, { 1, 5 }, { 3, 3 }, { 5, 1 }, { 5, 5 }};
Console.Write(countPairs(N, bishops));
}
}
// This code is contributed by Saurabh Jaiswal
<script>
// JavaScript program for above approach
let board = new Array(20).fill(0).map(() => new Array(20).fill(0));
const countPairs = (N, bishops) => {
// Set all the bits
// having bishop to 1
for (let i = 0; i < bishops.length; i++) {
board[bishops[i][0]][bishops[i][1]] = 1;
}
// Stores the final answer
let ans = 0;
// Loop to traverse the matrix
// diagonally in left direction
for (let s = 2; s <= 2 * N; s++) {
// Stores count of bishop
// in the current diagonal
let cnt = 0;
for (let i = 1, j = s - i;
Math.max(i, j) <= Math.min(N, s - 1); i++, j--) {
if (board[j][i - j] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Loop to traverse the matrix
// diagonally in right direction
for (let s = 2; s <= 2 * N; s++) {
// Stores count of bishop
// in the current diagonal
let cnt = 0;
for (let i = 1, j = s - i;
Math.max(i, j) <= Math.min(N, s - 1); i++, j--) {
if (board[i][N - j + 1] == 1)
// Update cnt
cnt++;
}
// Update the answer
if (cnt > 1)
ans += ((cnt + 1) * cnt) / 2;
}
// Return answer
return ans;
}
// Driver code
let N = 10;
let bishops = [
[1, 1], [1, 5], [3, 3], [5, 1], [5, 5]
];
document.write(countPairs(N, bishops));
// This code is contributed by rakeshsahni
</script>
Output
6
Time Complexity: O(N * N)
Auxiliary Space: O(N * N)
Approach: Optimized Diagonal Counting with Dictionary
To determine the number of bishop pairs that can attack each other on a chessboard, we can optimize the count by focusing on the bishops' positions directly rather than iterating over the entire board. Since bishops attack each other if they lie on the same diagonal, we can utilize two hash maps (or dictionaries in Python) to count bishops on each diagonal efficiently.
Steps:
- Two Diagonal Categories: Diagonals on a chessboard can be categorized into those running from the top-left to bottom-right (/ shaped) and those from the top-right to bottom-left (\ shaped).
- Diagonal Representation:
- For /(right diagonal) shaped diagonals, use i + j as a unique identifier for diagonals.
- For \(left diagonal) shaped diagonals, use i - j as a unique identifier for diagonals.
- Count Bishops per Diagonal: Use dictionaries to keep track of how many bishops are on each unique diagonal.
- Calculate Pairs Using Combinatorics: If k bishops are on the same diagonal, the number of ways to choose two bishops (pairs) from them is given by the combination formula C(k, 2) = k * (k - 1) / 2.
#include <iostream>
#include <unordered_map>
#include <vector>
// Function to calculate pairs from n items
int countPairs(int n)
{
if (n < 2)
return 0;
return (n * (n - 1)) / 2;
}
// Function to count the number of pairs of bishops that can
// attack each other
int countAttackingBishopPairs(
int N, const std::vector<std::pair<int, int> >& bishops)
{
std::unordered_map<int, int>
diag1; // Hash map to count bishops on (i + j)
// diagonals
std::unordered_map<int, int>
diag2; // Hash map to count bishops on (i - j)
// diagonals
// Populate the hash maps with bishop counts on each
// diagonal
for (const auto& bishop : bishops) {
int x = bishop.first;
int y = bishop.second;
diag1[x + y]++;
diag2[x - y]++;
}
int ans = 0;
// Sum the number of attacking pairs on each (i + j)
// diagonal
for (const auto& p : diag1) {
ans += countPairs(p.second);
}
// Sum the number of attacking pairs on each (i - j)
// diagonal
for (const auto& p : diag2) {
ans += countPairs(p.second);
}
return ans;
}
// Example usage
int main()
{
std::vector<std::pair<int, int> > bishops = {
{ 1, 1 }, { 1, 5 }, { 3, 3 }, { 5, 1 }, { 5, 5 }
};
int N = 10;
std::cout << countAttackingBishopPairs(N, bishops)
<< std::endl; // Output: 6
return 0;
}
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Main {
// Function to calculate pairs from n items
static int countPairs(int n)
{
if (n < 2)
return 0;
return (n * (n - 1)) / 2;
}
// Function to count the number of pairs of bishops that
// can attack each other
static int countAttackingBishopPairs(
int N, List<Map.Entry<Integer, Integer> > bishops)
{
Map<Integer, Integer> diag1
= new HashMap<>(); // Hash map to count bishops
// on (i + j) diagonals
Map<Integer, Integer> diag2
= new HashMap<>(); // Hash map to count bishops
// on (i - j) diagonals
// Populate the hash maps with bishop counts on each
// diagonal
for (Map.Entry<Integer, Integer> bishop : bishops) {
int x = bishop.getKey();
int y = bishop.getValue();
diag1.put(x + y,
diag1.getOrDefault(x + y, 0) + 1);
diag2.put(x - y,
diag2.getOrDefault(x - y, 0) + 1);
}
int ans = 0;
// Sum the number of attacking pairs on each (i + j)
// diagonal
for (int count : diag1.values()) {
ans += countPairs(count);
}
// Sum the number of attacking pairs on each (i - j)
// diagonal
for (int count : diag2.values()) {
ans += countPairs(count);
}
return ans;
}
// Example usage
public static void main(String[] args)
{
List<Map.Entry<Integer, Integer> > bishops
= List.of(Map.entry(1, 1), Map.entry(1, 5),
Map.entry(3, 3), Map.entry(5, 1),
Map.entry(5, 5));
int N = 10;
System.out.println(countAttackingBishopPairs(
N, bishops)); // Output: 6
}
}
def countPairs(N, bishops):
# Dictionaries for diagonals
diag1 = {} # i + j
diag2 = {} # i - j
# Count bishops on each diagonal
for x, y in bishops:
if (x + y) not in diag1:
diag1[x + y] = 0
if (x - y) not in diag2:
diag2[x - y] = 0
diag1[x + y] += 1
diag2[x - y] += 1
# Function to calculate pairs in n items
def count_pairs(n):
if n < 2:
return 0
return (n * (n - 1)) // 2
# Calculate pairs of bishops that can attack each other
ans = sum(count_pairs(count) for count in diag1.values()) + \
sum(count_pairs(count) for count in diag2.values())
return ans
# Example usage
N = 10
bishops = [[1, 1], [1, 5], [3, 3], [5, 1], [5, 5]]
print(countPairs(N, bishops)) # Output: 6
// Function to calculate pairs from n items
function countPairs(n) {
if (n < 2)
return 0;
return (n * (n - 1)) / 2;
}
// Function to count the number of pairs of bishops that
// can attack each other
function countAttackingBishopPairs(N, bishops) {
const diag1 = new Map(); // Map to count bishops on (i + j) diagonals
const diag2 = new Map(); // Map to count bishops on (i - j) diagonals
// Populate the maps with bishop counts on each diagonal
for (const [x, y] of bishops) {
diag1.set(x + y, (diag1.get(x + y) || 0) + 1);
diag2.set(x - y, (diag2.get(x - y) || 0) + 1);
}
let ans = 0;
// Sum the number of attacking pairs on each (i + j) diagonal
for (const count of diag1.values()) {
ans += countPairs(count);
}
// Sum the number of attacking pairs on each (i - j) diagonal
for (const count of diag2.values()) {
ans += countPairs(count);
}
return ans;
}
// Example usage
const bishops = [
[1, 1],
[1, 5],
[3, 3],
[5, 1],
[5, 5]
];
const N = 10;
console.log(countAttackingBishopPairs(N, bishops)); // Output: 6
Output
6
Time Complexity: O(X), where X is the number of bishops. The computation directly depends on the number of bishops and not on the size of the board N.
Auxilary Space: O(X), where X is the number of bishops. This accounts for the space used by the dictionaries to track bishops on each diagonal.