2008年2月9日 星期六

Assignment review: N queens in Prolog

/*
Generate a list [1, 2, ..., N] to L.
Permute L to Board.
Check Board if it is safe.
*/

queens( N, Board ) :- !,
                      range( N, L ),
                      permutation( L, Board ),
                      safe( Board ).

range( N, L ) :- decrease( N, Temp ),
                 reverse( Temp, L ).                                             % Generate a increasing list.
decrease( 0, [] ) :- !.
decrease( N, [H | L] ) :- N = H,
                              Next is N - 1,
                              decrease( Next, L ).

safe( [_] ) :- !.                                                                % Check if all queens are safe.
safe( [Queen | Others] ) :- !,
                            nohit( Queen, 1, Others ),
                            safe( Others ).
nohit( _, _, [] ) :- !.                                                          % Check if queens could not attack each other.
nohit( Column, Row_D, [Queen | Others] ) :- !,
                                            nohit( Column, Row_D, Queen ),
                                            Row_D_Next is Row_D + 1,
                                            nohit( Column, Row_D_Next, Others ).
nohit( Column, Row_D, Target ) :- !,
                                  Diag1 is Column + Row_D,
                                  Diag1 =\= Target,
                                  Diag2 is Column - Row_D,
                                  Diag2 =\= Target.

之後只要用queens( 4, B ).就可以列出當棋盤大小為四佾時,四個皇后不會互相攻擊的縱座標或橫座標[?]
以四佾來說,它會印出:
B = [2,4,1,3]
B = [3,1,4,2]
意即第一組解為(1,2)(2,4)(3,1)(4,3)和第二組解為(1,3)(2,1)(3,4)(4,2)。
引數的數字可以依棋盤大小任意更改。由於Prolog是採DFS的方式搜尋,太大的棋盤會跑很久。

沒有留言:

張貼留言