const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'input N from N Queen /> ',
});
rl.prompt();
rl.on('line', (input) => {
if (input === 'exit') rl.close();
const inputNumber = +input;
if (isNaN(inputNumber)) {
console.log('숫자를 입력하세요!');
rl.prompt();
} else {
chessMain(inputNumber);
rl.prompt();
}
}).on('close', () => {
console.log('exit');
process.exit(0);
});
function chessMain(inputNumber) {
console.time('queen');
let chessMap = chessInit(inputNumber);
let queenQueue = searchEmpties(chessMap, true);
let possibleCaseNumber = [0];
let possibleCases = [];
queenQueue.forEach((queenCoord) => {
const tempchessMap = chessInit(inputNumber);
const [X, Y] = queenCoord;
searchPossibles(
tempchessMap,
X,
Y,
inputNumber,
possibleCaseNumber,
possibleCases
);
});
console.log(possibleCaseNumber);
console.timeEnd('queen');
}
function searchPossibles(chessMap, x, y, N, possibleCaseNumber, possibleCases) {
placeQueen(chessMap, x, y);
N -= 1;
if (N === 0) {
if (checkExist(chessMap, possibleCases)) {
return;
}
possibleCases.push(chessMap);
possibleCaseNumber[0] = possibleCaseNumber[0] + 1;
console.log(chessMap);
console.log('--------------------------------');
return;
}
const emptyNumber = getEmptyNumber(chessMap);
if (emptyNumber === 0) {
return;
}
const empties = searchEmpties(chessMap);
empties.forEach((coords) => {
const tempChessMap = JSON.parse(JSON.stringify(chessMap));
const [X, Y] = coords;
return searchPossibles(
tempChessMap,
X,
Y,
N,
possibleCaseNumber,
possibleCases
);
});
}
function checkExist(chessMap, possibleCases) {
let result;
possibleCases.forEach((eachCase) => {
if (JSON.stringify(eachCase) === JSON.stringify(chessMap)) {
return (result = true);
}
});
return result;
}
function getEmptyNumber(chessMap) {
const length = chessMap.length;
let emptyNumber = 0;
for (let i = 0; i < length; i++) {
for (let j = 0; j < length; j++) {
if (chessMap[i][j] === ' ') {
emptyNumber += 1;
}
}
}
return emptyNumber;
}
function chessInit(N) {
let chessMap = [];
for (let i = 0; i < N; i++) {
chessMap.push(Array(N).fill(' '));
}
return chessMap;
}
function placeQueen(chessMap, x, y) {
chessMap[y][x] = 'Q';
queenEffect(chessMap, x, y);
}
function queenEffect(chessMap, x, y) {
const N = chessMap.length;
let effectX = x;
let effectY = y;
while (effectX - 1 >= 0) {
chessMap[effectY][effectX - 1] = 'X';
effectX -= 1;
}
effectX = x;
while (effectX + 1 < N) {
chessMap[effectY][effectX + 1] = 'X';
effectX += 1;
}
effectX = x;
while (effectY - 1 >= 0) {
chessMap[effectY - 1][effectX] = 'X';
effectY -= 1;
}
effectY = y;
while (effectY + 1 < N) {
chessMap[effectY + 1][effectX] = 'X';
effectY += 1;
}
effectY = y;
while (effectX - 1 >= 0 && effectY - 1 >= 0) {
chessMap[effectY - 1][effectX - 1] = 'X';
effectY -= 1;
effectX -= 1;
}
effectX = x;
effectY = y;
while (effectX + 1 < N && effectY - 1 >= 0) {
chessMap[effectY - 1][effectX + 1] = 'X';
effectY -= 1;
effectX += 1;
}
effectX = x;
effectY = y;
while (effectX - 1 >= 0 && effectY + 1 < N) {
chessMap[effectY + 1][effectX - 1] = 'X';
effectY += 1;
effectX -= 1;
}
effectX = x;
effectY = y;
while (effectX + 1 < N && effectY + 1 < N) {
chessMap[effectY + 1][effectX + 1] = 'X';
effectY += 1;
effectX += 1;
}
effectX = x;
effectY = y;
}
function searchEmpties(chessMap, isInit) {
const empties = [];
const N = chessMap.length;
let Delta = 0;
let deltaX = Delta % N;
let deltaY = Math.floor(Delta / N);
const lastDelta = N * N - 1;
if (isInit === true) {
const isOdd = N % 2 === 1;
const halfN = Math.floor(N / 2);
const quarterLastDelta = Math.floor((N * N) / 4) - 1;
while (Delta <= quarterLastDelta) {
deltaX = Delta % halfN;
deltaY = Math.floor(Delta / halfN);
if (chessMap[deltaY][deltaX] === ' ') {
empties.push([deltaX, deltaY]);
}
Delta += 1;
}
if (isOdd) {
let oddX = halfN;
let oddY = 0;
while (oddY <= halfN) {
empties.push([oddX, oddY++]);
}
}
} else {
while (Delta <= lastDelta) {
deltaX = Delta % N;
deltaY = Math.floor(Delta / N);
if (chessMap[deltaY][deltaX] === ' ') {
empties.push([deltaX, deltaY]);
}
Delta += 1;
}
}
return empties;
}
function rotateMapClockwise(chessMap) {
return rotatedChessmap;
}