数独暴力遍历代码

数独暴力遍历代码

还是递归大法好。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define CELL_DEEP        3
#define MATRIX_DEEP      9
#define MATRIX_NUM      (MATRIX_DEEP*MATRIX_DEEP)
#define FULL_BITMAP     0x1FF


#define TEST_BITMAP(bitmap, bit)       (bitmap) & (1 << (bit))

int GET_BIT_NUM(int bitmap, int *last_bit)
{
    int bit_num = 0;
    int i;
    
    for(i = 0; i < MATRIX_DEEP; i++) 
    {
        if(TEST_BITMAP(bitmap, i)) 
        {
            if(NULL != last_bit) *last_bit = i;
            bit_num++;
        }
    }
    
    return bit_num;
}

int BITMAP_TO_STR(int bitmap, char *buffer)
{
    int i, j;
    
    if(NULL == buffer) return -1;

    for(i = 0, j = 0; i < MATRIX_DEEP; i++) {
        if(TEST_BITMAP(bitmap, i)) {
            buffer[j++] = '1' + i;
        }
    }
    buffer[j] = 0;

    return 0;
}

#define CLEAR_BITMAP(node, bit)   (node.bitmap) &= ~(1 << (bit)) //0-8
        
#define CHECK_BITMAP(node) 
    do { 
        int last_bit; 
        if(GET_BIT_NUM(node.bitmap, &last_bit) == 1) 
        node.value = last_bit + 1; 
    }while(0)

int my_init_data1[] = 
{
    0, 6, 0, 0, 0, 3, 0, 7, 0,
    0, 0, 0, 0, 1, 5, 0, 0, 3,
    0, 7, 9, 0, 2, 0, 0, 5, 0,
    0, 0, 3, 8, 0, 2, 0, 0, 7,
    4, 0, 8, 0, 3, 0, 5, 0, 2,
    6, 0, 0, 5, 0, 1, 9, 0, 0,
    0, 5, 0, 0, 6, 0, 7, 8, 0,
    7, 0, 0, 1, 5, 0, 0, 0, 0,
    0, 3, 0, 2, 0, 0, 0, 4, 0
};

int my_init_data2[] = 
{
    0, 7, 0, 0, 5, 0, 0, 6, 0,
    4, 0, 0, 9, 0, 3, 0, 0, 1,
    0, 0, 8, 0, 0, 0, 3, 0, 0,
    0, 5, 0, 0, 0, 0, 0, 4, 0,
    1, 0, 0, 0, 0, 0, 0, 0, 9,
    0, 2, 0, 0, 0, 0, 0, 1, 0,
    0, 0, 4, 0, 0, 0, 7, 0, 0,
    9, 0, 0, 1, 0, 7, 0, 0, 6,
    0, 8, 0, 0, 3, 0, 0, 5, 0
};

int my_init_data3[] = 
{
    0, 0, 0, 0, 0, 0, 0, 2, 0,
    0, 3, 0, 0, 0, 9, 0, 0, 6,
    0, 0, 1, 0, 4, 7, 0, 0, 0,
    0, 0, 0, 1, 0, 0, 4, 7, 0,
    0, 0, 5, 0, 0, 0, 3, 0, 0,
    0, 2, 7, 0, 0, 8, 0, 0, 0,
    0, 0, 0, 5, 3, 0, 8, 0, 0,
    8, 0, 0, 2, 0, 0, 0, 6, 0,
    0, 1, 0, 0, 0, 0, 0, 0, 0,
};

int my_init_data[] = 
{
    0, 0, 0, 0, 0, 0, 2, 5, 0,
    0, 0, 0, 0, 8, 9, 0, 0, 7,
    0, 0, 0, 2, 0, 0, 0, 0, 8,
    0, 0, 4, 0, 6, 0, 0, 1, 0,
    0, 6, 0, 9, 0, 4, 0, 3, 0,
    0, 7, 0, 0, 2, 0, 5, 0, 0,
    2, 0, 0, 0, 0, 6, 0, 0, 0,
    3, 0, 0, 5, 1, 0, 0, 0, 0,
    0, 8, 9, 0, 0, 0, 0, 0, 0,
};


typedef struct tagNODE_INFO_ST
{
    int value; // 0 means not sure
    int bitmap;
}NODE_INFO_ST;

NODE_INFO_ST my_node_db[MATRIX_NUM];

#if 1 // common
int get_init_data()
{
    int  i;
    char ch;
    
    printf("
 input initial data(y/n): ");
    scanf("%c", &ch);
    if ( ch != 'y' ) return 0;

INPUT_REP:  
    for(i = 0; i < MATRIX_DEEP; i++) {
        printf("line %d: ", i + 1);
        scanf("%d %d %d %d %d %d %d %d %d", 
            &my_init_data[i*MATRIX_DEEP], &my_init_data[i*MATRIX_DEEP+1], &my_init_data[i*MATRIX_DEEP+2],
            &my_init_data[i*MATRIX_DEEP+3], &my_init_data[i*MATRIX_DEEP+4], &my_init_data[i*MATRIX_DEEP+5],
            &my_init_data[i*MATRIX_DEEP+6], &my_init_data[i*MATRIX_DEEP+7], &my_init_data[i*MATRIX_DEEP+8]);
    }
    
    for(i = 0; i < MATRIX_NUM; i++) {
        if(my_init_data[i] < 0 || my_init_data[i] > MATRIX_DEEP) {
            printf("illegal data of %d, try again
", i);
            goto INPUT_REP;
        }
    }
    
    return 0;
}

int init_node_db(NODE_INFO_ST *node_db, int *init_data)
{
    int i;
    
    assert(node_db != NULL);
    assert(init_data != NULL);
    
    for(i=0; i < MATRIX_NUM; i++) {
        if (init_data[i] > MATRIX_DEEP || init_data[i] < 0) return -2;
        
        if(init_data[i] > 0) {
            node_db[i].value = init_data[i];
            node_db[i].bitmap = 1 << (init_data[i] - 1);
        } else {
            node_db[i].value = 0;
            node_db[i].bitmap = FULL_BITMAP;
        }
    }
    
    return 0;
}

int show_init_data(int *init_data)
{
    int i;
    
    assert(init_data != NULL);
    
    printf("init data: 
");
    for(i = 0; i < MATRIX_NUM; i++) {
        printf("%d ", init_data[i]);
        if((i+1)%MATRIX_DEEP == 0)printf("
");
    }
    return 0;    
}

int get_all_checked_num(NODE_INFO_ST *node_db)
{
    int checked_num = 0;
    int i;
    
    assert(node_db != NULL);
    
    for(i = 0; i < MATRIX_NUM; i++) {
        if (node_db[i].value > 0) {
            checked_num++;
        }        
    }
    
    return checked_num;    
}

int get_all_bit_num(NODE_INFO_ST *node_db)
{
    int bit_num = 0;
    int i;
    
    assert(node_db != NULL);
    
    for(i = 0; i < MATRIX_NUM; i++) {
        bit_num += GET_BIT_NUM(node_db[i].bitmap, NULL);
    }
    
    return bit_num;    
}

int show_sub_node_db(int line, NODE_INFO_ST *node_db)
{
    int i;
    char buffer[16];
    
    assert(node_db != NULL);
    
    printf("sub node db: ", line);
    for(i = 0; i < MATRIX_DEEP; i++) {
        if (node_db[i].value > 0) {
            printf("<==%d==> ", node_db[i].value);
       } else {
            BITMAP_TO_STR(node_db[i].bitmap, buffer);
            printf("%7s ", buffer);
        }
    }
    printf("
");
    
    return 0;
}


int show_node_db(int line, NODE_INFO_ST *node_db)
{
    int i;
    char buffer[16];
    
    assert(node_db != NULL);
    
    printf("node db: line(%d) checked(%d)
", line, get_all_checked_num(node_db));
    for(i = 0; i < MATRIX_NUM; i++) {
        if (node_db[i].value > 0) {
            printf("<==%d==> ", node_db[i].value);
       } else {
            BITMAP_TO_STR(node_db[i].bitmap, buffer);
            printf("%7s ", buffer);
        }
        if((i+1)%MATRIX_DEEP == 0)printf("
");
    }
    
    return 0;
}


int load_sub_node_db(int mode, NODE_INFO_ST *node_db, int i, NODE_INFO_ST* sub_list)
{
    int j, k, row;
    int cell_x, cell_y;
    
    assert(node_db != NULL);
    assert(sub_list != NULL);

    if(mode == 1) // row(i)
    {
        for (j = i*MATRIX_DEEP, k = 0; j < i*MATRIX_DEEP + MATRIX_DEEP; j++) {
            memcpy(&sub_list[k++], &node_db[j], sizeof(NODE_INFO_ST));
        }    
    }
    else if (mode == 2) // col(i)
    {
        for (j = i, k = 0; j < MATRIX_NUM; j+= MATRIX_DEEP) {
            memcpy(&sub_list[k++], &node_db[j], sizeof(NODE_INFO_ST));
        }
    }
    else if (mode == 3) // cell(i)
    {
        cell_x = (i/CELL_DEEP)*CELL_DEEP;
        cell_y = (i%CELL_DEEP)*CELL_DEEP;
        for(row = 0, k = 0; row < CELL_DEEP; row++) {
                for (j = (cell_x + row)*MATRIX_DEEP + cell_y; j < (cell_x + row)*MATRIX_DEEP + cell_y + CELL_DEEP; j++) {
                    memcpy(&sub_list[k++], &node_db[j], sizeof(NODE_INFO_ST));
                }
            }        
    }

    return 0;        
}

int restore_sub_node_db(int mode, NODE_INFO_ST *node_db, int i, NODE_INFO_ST* sub_list)
{
    int j, k, row;
    int cell_x, cell_y;
    
    assert(node_db != NULL);
    assert(sub_list != NULL);

    if(mode == 1) // row(i)
    {
        for (j = i*MATRIX_DEEP, k = 0; j < i*MATRIX_DEEP + MATRIX_DEEP; j++) {
            memcpy(&node_db[j], &sub_list[k++], sizeof(NODE_INFO_ST));
        }    
    }
    else if (mode == 2) // col(i)
    {
        for (j = i, k = 0; j < MATRIX_NUM; j+= MATRIX_DEEP) {
            memcpy(&node_db[j], &sub_list[k++], sizeof(NODE_INFO_ST));
        }
    }
    else if (mode == 3) // cell(i)
    {
        cell_x = (i/CELL_DEEP)*CELL_DEEP;
        cell_y = (i%CELL_DEEP)*CELL_DEEP;
        for(row = 0, k = 0; row < CELL_DEEP; row++) {
                for (j = (cell_x + row)*MATRIX_DEEP + cell_y; j < (cell_x + row)*MATRIX_DEEP + cell_y + CELL_DEEP; j++) {
                    memcpy(&node_db[j], &sub_list[k++], sizeof(NODE_INFO_ST));
                }
            }        
    }

    return 0;        
}
#endif

#if 1 // try 
int check_sub_node_db(NODE_INFO_ST* sub_list)
{
    int i, j;
    
    assert(sub_list != NULL);
    
    // 检查是否存在节点取值冲突
    for(i = 0; i < MATRIX_DEEP; i++) {
        for (j = 0; j < MATRIX_DEEP; j++) {
            if(j != i && sub_list[i].value > 0 && sub_list[i].value == sub_list[j].value) 
                return 1;
        }
    }

    return 0;
}

int check_node_db(NODE_INFO_ST *node_db)
{
    int i, ret = 0;
    NODE_INFO_ST sub_node_db[MATRIX_DEEP];
    
    assert(node_db != NULL);
    
    for(i = 0; i < MATRIX_DEEP; i++) 
    {
        load_sub_node_db(1, node_db, i, sub_node_db);
        ret = check_sub_node_db(sub_node_db);
        restore_sub_node_db(1, node_db, i, sub_node_db);
        if (ret != 0) return ret;
    }

    for(i = 0; i < MATRIX_DEEP; i++) 
    {
        load_sub_node_db(2, node_db, i, sub_node_db);
        ret = check_sub_node_db(sub_node_db);
        restore_sub_node_db(2, node_db, i, sub_node_db);
        if (ret != 0) return ret;
    }

    for(i = 0; i < MATRIX_DEEP; i++) 
    {
        load_sub_node_db(3, node_db, i, sub_node_db);
        ret = check_sub_node_db(sub_node_db);
        restore_sub_node_db(3, node_db, i, sub_node_db);
        if (ret != 0) return ret;
    }    

    return 0;
}


int try_node_db(int index, NODE_INFO_ST *node_db)
{
    int i;
    int bitmap_bak;
    NODE_INFO_ST new_node_db[MATRIX_NUM];
    
    assert(node_db != NULL);
    if (index >= MATRIX_NUM) return 0;
    
    if (node_db[index].value > 0) 
        return try_node_db(index + 1, node_db);

    bitmap_bak = node_db[index].bitmap;
    for(i = 0; i < MATRIX_DEEP; i++)
    {
        if ( TEST_BITMAP(bitmap_bak, i) )
        {
            //printf("try node %d with value %d 
", index + 1, i + 1);
            memcpy(new_node_db, node_db, MATRIX_NUM*sizeof(NODE_INFO_ST));
            new_node_db[index].bitmap = 1 << i;
            new_node_db[index].value = i + 1;

            //check if conflict
            if ( check_node_db(new_node_db) > 0 ) 
            {
                continue; //not good
            } 
            else
            {
                if (get_all_checked_num(new_node_db) == MATRIX_NUM) {
                    printf("try success
");
                    memcpy(my_node_db, new_node_db, MATRIX_NUM*sizeof(NODE_INFO_ST));
                    return 0;
                }

                if ( 0 == try_node_db(index + 1, new_node_db) )
                    return 0;
            }
        }
    }
    
    return 1;
}


#endif

int main()
{
    int i,j;
    int temp[MATRIX_DEEP];
    
    // get init data
    get_init_data();
    show_init_data(my_init_data);

    // generate node db
    init_node_db(my_node_db, my_init_data);
    show_node_db(__LINE__, my_node_db);

#if 0
    // scan 
    printf("scan...
");
    scan_node_db_rep(my_node_db);
    show_node_db(__LINE__, my_node_db);
    if (get_all_checked_num(my_node_db) == MATRIX_NUM) 
        goto PASS_CHECK;
#endif

    // try
    printf("try...
");
    try_node_db(0, my_node_db);
    show_node_db(__LINE__, my_node_db);

PASS_CHECK:
    if (check_node_db(my_node_db) == 0)  printf("DONE.
"); 
    else printf("ERROR.
");
    
    return 0;
}