このディレクトリの索引
http://hibari.2ch.net/test/read.cgi/tech/1308749241/456
#  [1] 授業単元:C言語 
#  [2] 問題文(含コード&リンク):http://codepad.org/dx3nSGGc 
#  
#  //盤面データ構造体
#  struct aa_t {
#    int cell[9][9];
#  };
#  
#  ・(r,c)に数字kは入らないとする関数
#  マス(r,c)に9ビットの状態数が与えられています。
#  たとえば110101110のとき、kが2なら、この関数によって110101100というようにします。
#  このとき、元から0であり変更がなかったなら0を、1を0に変更したら1を返すようにします。
#  int aa_del(struct aa_t *s, int r, int c, int k) {
#    if((s->cell[r][c] & (0001 << (k-1))) == 0000){return 0;}
#    else {s->cell[r][c] = (s->cell[r][c] & ( ~(0001 << (k-1)) ) );return 1;}
#  }
#  
#  ・横一列に同じ数字は入り得ないとする関数
#  (r,c)には1~9のいずれかの数字が入ります。
#  たとえば(r,c)のマスに3,6,9の数字が入る可能性がある事を100100100という状態数で表しています。
#  もし(r,c)の状態数が000000100となると、(r,c)に3が入ることが確定します。
#  このときc列に3が入る可能性を消す関数です。(もちろん(r,c)以外の)
#  そしてこの関数で実際に変更を受けたマスの数を戻り値として返すようにします。

'(r,c)に数字kは入らない'(_r,_c,_k,LL1,LL2,_b) :-
        findall(N,(
                    bit_n(M,N),
                    \+(M=_k)),
                L),
        sum(L,S),
        nth1(_r,LL1,L1),
        nth1(_c,L1,_b),
        _b2 is _B \/ S,
        '行列の置換'(_r,_c,_b2,LL1,LL2),!.

'横一列に同じ数字は入り得ない'(_r,_c,_k,LL1,LL2) :-
        'kを否定する為の数'(_k,S),
        転置して列のビット処理(LL1,_r,_c,_k,S,LL2).

'kを否定する為の数'(_k,S) :-
        findall(N,(
                    bit_n(M,N),
                    \+(M=_k)),
                L),
        sum(L,S),!.

転置して列のビット処理(LL1,_r,_c,_k,S,LL2) :-
        転置(LL1,LL3),
        行とカラムを得る(LL3,_c,_r,L3,_b),
        行全体のビットオフ(L3,S,L2),
        指定カラムだけビットオン(L2,_k,_b,_b3,L4),
        要素位置指定によるならびの置換(LL3,_c,L4,LL4),
        転置(LL4,LL2),!.

行とカラムを得る(LL,_r,_c,L,_b) :-
        nth1(_r,LL,L),
        nth1(_c,L,_b),!.

行全体のビットオフ(L3,S,L2) :-
        findall(_b2,(
                     member(I,L3),
                     _b2 is I /\ S),
                L2),!.

指定カラムだけビットオン(L2,_k,_b,_b3,L4) :-
        bit_n(_k,J),
        _b3 is _b \/ J,
        要素位置指定によるならびの置換(L2,_r,_b3,L4),!.

bit_n(0,0).
bit_n(1,1).
bit_n(2,2).
bit_n(3,4).
bit_n(4,8).
bit_n(5,16).
bit_n(6,32).
bit_n(7,64).
bit_n(8,128).
bit_n(9,256).