---
# System prepended metadata

title: Bitwise N-Queens
tags: [C LANGUAGE]

---

# Bitwise N-Queens 
###### tags: `C LANGUAGE`

:::success
Bitwise Operator 一直是自己不太熟悉的一個部份，藉由閱讀`jgpettibone` 的 Bitwise N-Queens，並且將其內容做成筆記方便日後複習。
:::
[jgpettibone的文章](http://jgpettibone.github.io/bitwise-n-queens)

---
## N-Queens
N-Queens 這個問題早是由 8-Queens 問題延伸而來。在西洋棋的規則中 Queen 能夠吃掉在同 Column 跟同 Row 還有在其左右對角線的棋子。

而 8-Queees 問題就是在，8x8 的棋盤上有多少解是能夠讓8個皇后同時生存，而這個問題是 Backtracking 演算法的一個相當經典的應用。

#### BackingTracking (回溯法)
簡單介紹就是在無窮枚舉遞迴的過程中，在遞迴下去前檢查答案是否是自己要的，如果不是就不在往下跑，這樣就能減少所多無意義的運算，有點類似 Branch and Bound。

### Bitwise Implement
接下來就直接進入主題，看看 `jgpettibone` 是如何 Implement。

#### Board Position
取代利用陣列來表示 Queen 的位置，這邊利用二進位的1來表示目前的位置， 例如如果是一個4x4的棋盤，我們用1、2、4、8的二進位來表示位置，然後在用 Left shift `<<`來作 Queen 位置的操作。
:::info
0001    1 這代表 Queen 目前在最後一位。
0010    2
0100    4
1000    8 

這樣的方法，可以利用 `AND` 來判斷 Queen 是否有在同 Column 的狀況。
:::

#### Conflicts 處理
因為我們是用二的倍數來操作所以不用擔心 Row 是否有 Conflict 的問題，要注意的是 Column 跟左右對角線。
:::success
0010 目前 Queen 要放的位置
0100 Queen 跟右下角衝突
0001 與下面對角線衝突
0010 與第一個 Column 衝突
:::
從上面的例子可以看到`0010`這個位置有兩種 Conflict 分別是與右下角衝突跟 Column 衝突，那要怎找到一個適合的位置？
:::success
0100
0001
1000 
一一一
1101 
:::
可以發現原本的 Queens 存在的位置做過 `OR` operator 之後，會得到1101，這個時候從簡單的4x4中可以觀察到在0010是唯一能夠放 Queen 的地方，如果我們將1101跟0010做 `AND` operator 之後。
:::success
1101
0010
一一一
0000
:::
可以得到0000，那就代表已存在的所有 Queens 做 `OR` 後得到的值再跟欲放入 Queen 的位置做 `AND` 如果得到的值都為0就代表此位置是可行。

#### 實際作法
Step One: 初始化三個變數分別代表左對角線、右對角線、Column 會遇到 Conflict 的位置。

Step Two: 將這三個變數做 OR operator 之後，就可以利用這個去對新的位置用 `AND` operator 判斷是否有 Conflict。

Step Three: 根據新進來的Row來變更那三個變數。

:::success
左對角線
0001 上一個左對角線參數
1000 現在進來的 Row
一一一
1001 作 OR operation
0100(1) 然後向右 shift 一個 bit
這樣就可以得到下一個 Row 進來是否有 Conflict 的判斷。
:::

:::info
右對角線
0100 上一個右對角線參數
1000 現在進來的 Row
一一一
1100 作 OR operation
(1)1000 然後向左 shift 一個 bit
這樣就可以得到下一個 Row 進來是否有 Conflict 的判斷。
:::

:::danger
Column
0010 上一個 Column 參數
1000 現在進來的 Row
一一一
1010 作 OR operation
這樣就可以得到下一個 Row 進來是否有 Conflict 的判斷。
:::

以上就是 Bitwise N-Queens 簡單的方法介紹，以下會附上 Implement 的 Code

```clike
#include <stdio.h>
#include <stdlib.h>

//this struct record the conflict information
typedef struct quene_propety
{
    int minDiagnoalConflict;
    int maxDiagnoalConflictm;
    int ColConflict;
    int n_number;
} quene_pro;



void quene_count(int current_row ,quene_pro *quene, int *solution_count)
{
    //the current initial is zero
    //if the current row past the n_number mean find the one solution
    //solution_count plus one which mean the solution number  
    if (current_row == quene->n_number){
        (*solution_count)++;
        free(quene);
        return;
    }

    int conflicts = quene->maxDiagnoalConflictm | quene->minDiagnoalConflict  | quene->ColConflict;

    // first iteration is 1 and multiple 2 to the next bit 
    // if n = 4 , (1 << 4) = 10000 is 16 so the most left bit is 1000 = 8
    // the quene position = 1000 [0100 = 4 0010 = 2 0001 = 1] 
    for (int quene_position = 1; quene_position < (1 << quene->n_number); quene_position *= 2){
        if (!(conflicts & quene_position)){
           quene_pro *q_new = malloc(sizeof(quene_pro));
           q_new->maxDiagnoalConflictm = (quene->maxDiagnoalConflictm | quene_position) >> 1;
           q_new->minDiagnoalConflict  = (quene->minDiagnoalConflict  | quene_position) << 1;
           q_new->ColConflict = quene->ColConflict | quene_position;
           q_new->n_number = quene->n_number;
           quene_count(current_row + 1 ,q_new, solution_count);
        }       
    }
}

int quene_cross(int *number)
{
    int solution_count = 0;
    quene_pro p = {0, 0, 0,  *number};
    quene_count(0, &p, &solution_count);
    return solution_count;

}

int main()
{
    int n_number = 0;
    int counts = 0;
    scanf("%d", &n_number);
    counts = quene_cross(&n_number);
    printf("%d Solutions\n", counts);
    return 0;
}
```