8.3 ハッシュ関数の実装 |
本節では、前節定義したハッシュ関数の実装を行います。
修正するファイルは"board.c"です。
最初にBoardクラスにメンバ変数を追加します。
追加する変数はハッシュ値の差分(マスの状態に応じてハッシュ値とのXORをとる値)です。
Board構造体の定義は以下のようになります。
struct _Board { int Disk[NUM_DISK]; int Stack[NUM_STACK]; int *Sp; int DiskNum[3]; int Pattern[NUM_PATTERN_ID]; int PatternID[NUM_DISK][NUM_PATTERN_DIFF]; int PatternDiff[NUM_DISK][NUM_PATTERN_DIFF]; HashValue HashDiffBlack[NUM_DISK]; HashValue HashDiffWhite[NUM_DISK]; HashValue HashDiffTurn; };
乱数を生成するマクロget_rand()を追加します。
他のファイルにも定義されていませすが、以下の定義を"board.h"にも追加します。
0〜(in_max-1)までの整数をランダムに返します。
#define get_rand(in_max) ((int)((double)(in_max) * rand() / (RAND_MAX + 1.0)))
ハッシュ値の差分を初期化する関数Board_InitializeHashDiff()を追加します。
関数の内部は以下のようになっています。
static void Board_InitializeHashDiff(Board *self) { int i; self->HashDiffTurn.Low = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) | ((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);; self->HashDiffTurn.High = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) | ((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);; for (i = 0; i < NUM_DISK; i++) { self->HashDiffBlack[i].Low = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) | ((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24); self->HashDiffBlack[i].High = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) | ((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24); self->HashDiffWhite[i].Low = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) | ((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24); self->HashDiffWhite[i].High = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) | ((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24); } }
差分毎に乱数を割り当てています。
またBoardクラスの生成関数でBoard_InitializeHashDiff()を呼ぶようにします。
Board *Board_New(void) { Board *self; self = malloc(sizeof(Board)); if (self) { Board_InitializePatternDiff(self); Board_InitializeHashDiff(self); Board_Clear(self); } return self; }
最後にハッシュ関数Board_HashValue()を実装します。
void Board_HashValue(Board *self, int in_color, HashValue *out_value) { int i; out_value->Low = 0; out_value->High = 0; for (i = 0; i < NUM_DISK; i++) { switch (self->Disk[i]) { case BLACK: out_value->Low ^= self->HashDiffBlack[i].Low; out_value->High ^= self->HashDiffBlack[i].High; break; case WHITE: out_value->Low ^= self->HashDiffWhite[i].Low; out_value->High ^= self->HashDiffWhite[i].High; break; default: break; } } if (in_color == WHITE) { out_value->Low ^= self->HashDiffTurn.Low; out_value->High ^= self->HashDiffTurn.High; } }
各マスの状態を調べ、XORをとっているだけです。
また白番のときにはHashDiffTurnとのXORもとるようにします。
次節からは置換表の実装を行います。