软件工程基础个人项目

PSP

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)
Planning 计划  10  10
·Estimate ·估计这个任务需要多长时间 10 20
Development 开发    
·Analysis ·需求分析(包括学习新技术) 60 120
·Design Spec ·生成设计文档 300 120
·Design Review ·设计复审(和同事审核设计文档) / /
·Coding Standard ·代码规范(为目前的开发制定合适的规范) 120 180
·Design ·具体设计 120 180
·Coding ·具体编码 1080 1200
·Code Review ·代码复审 300 60
·Test ·测试(自我测试,修改代码,提交修改) 300 960
Reporting 报告    
·Test Report ·测试报告 60 60
·Size Measurement ·计算工作量 30 30
·Postmortem & Process Improvement Plan ·事后总结,并提出过程改进计划 180 120
  合计 2570 3060

 

github地址

https://github.com/sh0116/sudoku-solver/tree/sh0116-patch-1

 

代码

我们看一下这个规则,会发现一个规律,就是第一行有数x后不能再有x,它一定会依次出现在后面的行,同理列也一样,然后其他数也是这样。那么我们如果按数字顺序在第一个小方格内填入1,然后再在第二行某个格填入1,依次类推直到填完9种数,到这里有人会说这样迟早会产生冲突,出现不符合规则的局面,没错,的确会这样,那么我们就从试不了的地方开始回溯,换个数继续试,直到满足位置,这里有时候会回溯好几步才能成功,不过计算机比较快,尤其是用递归实现起来还是相当快的了。

 

 

 

board code
#include "board.hpp"
#include "bitUtils.hpp"
#include "io.hpp"

void Board::process_single(int square, int digit) {
    digit_at[square] = digit;
    squares_solved.set_square(square);
    houses_solved[digit][RANK_HOUSE[square]] = true;
    houses_solved[digit][FILE_HOUSE[square]] = true;
    houses_solved[digit][BLOCK_HOUSE[square]] = true;

    for (int d = 0; d < 9; ++d) {
        if (d != digit) {
            digit_bit_boards[d].unset_square(square);
        } else {
            digit_bit_boards[digit].set_square(square);
        }
    }

    digit_bit_boards[digit] &= SQUARE_TRUCE_MASKS[square];
}

int process_naked_singles(Board &b) {
    BitBoard81 at_least_once = BB81_ALL_ZERO;
    BitBoard81 more_than_once = BB81_ALL_ZERO;
    BitBoard81 mask;

    for (int d = 0; d < 9; ++d) {
        mask = b.digit_bit_boards[d];
        more_than_once |= at_least_once & mask;
        at_least_once |= mask;
    }

    BitBoard81 naked_singles =
        (at_least_once & ~more_than_once) & ~b.squares_solved;

    int count = 0;

    while (naked_singles) {
        int square = pop_bit_81(&naked_singles);

        int digit = DIGIT_NONE;

        for (int d = 0; d < 9; ++d) {
            if (b.digit_bit_boards[d].is_square_set(square)) {
                digit = d;
                break;
            }
        }

        b.process_single(square, digit);

        count += 1;
    }

    return count;
}

int process_hidden_singles(Board &b) {
    int count = 0;
    for (int d = 0; d < 9; ++d) {
        for (int h = 0; h < 27; ++h) {
            if (!b.houses_solved[d][h]) {
                BitBoard81 mask = HOUSE_MASKS[h] & b.digit_bit_boards[d];
                if (1 == count_bits_81(mask)) {
                    int square = pop_bit_81(&mask);
                    b.process_single(square, d);

                    count += 1;
                }
            }
        }
    }

    return count;
}

void solve_singles(Board &board) {
    while (process_naked_singles(board) || process_hidden_singles(board)) {
    }
}

void calculate_digit_state_list(Board &board, int digit, BitBoard81 &mask,
                                int rank) {
    if (rank == DIGIT_COUNT) {
        board.digit_state_lists[digit].add_state_node(
            new StateNode(mask, digit));
    } else {
        BitBoard81 rank_bb =
            mask & HOUSE_MASKS[rank] & board.digit_bit_boards[digit];

        while (rank_bb) {
            int square = pop_bit_81(&rank_bb);

            BitBoard81 undo_mask = mask & ~SQUARE_TRUCE_MASKS[square];

            mask &= SQUARE_TRUCE_MASKS[square];

            calculate_digit_state_list(board, digit, mask, rank + 1);

            mask |= undo_mask;
        }
    }
}

void calculate_state_lists(Board &board) {
    for (int d = ONE; d <= NINE; ++d) {
        BitBoard81 mask = {0x7FFFFFF, 0x7FFFFFF, 0x7FFFFFF};
        calculate_digit_state_list(board, d, mask, 0);
    }
}

void reset_board(Board &board) {
    for (int d = ONE; d <= NINE; ++d) {
        board.digit_state_lists[d].reset();
    }
}

void write_sol(StateNode *sol_states[], Board &board) {
    BitBoard32 last_digit_mask = 0x1ff;
    BitBoard81 last_digit_state_mask;

    for (int i = 0; i < DIGIT_COUNT - 1; ++i) {
        BitBoard81 state_mask = sol_states[i]->state;

        while (state_mask) {
            int square = pop_bit_81(&state_mask);
            board.digit_at[square] = sol_states[i]->digit;
        }

        last_digit_mask ^= (1UL << (sol_states[i]->digit));
        last_digit_state_mask ^= sol_states[i]->state;
    }

    int last_digit = pop_bit_32(&last_digit_mask);

    while (last_digit_state_mask) {
        int square = pop_bit_81(&last_digit_state_mask);
        board.digit_at[square] = last_digit;
    }
}

void solve(Board &board, SolveOutput *output, Option *opt) {
    int sol_count = 0;
    int nodes_searched = 0;
    bool stop_search = false;

    StateListPartitioned lists_p[DIGIT_COUNT];

    for (int i = 0; i < DIGIT_COUNT; ++i) {
        lists_p[i].set_first_part(board.digit_state_lists + i);
    }

    StateNode *sol_states[DIGIT_COUNT - 1];

    flip_min_size_part(lists_p, 0);
    for (sol_states[0] = lists_p[0].parts[0]->beg;
         sol_states[0] != nullptr && !stop_search;
         sol_states[0] = sol_states[0]->next) {
        partition(sol_states[0], lists_p, 1);
        flip_min_size_part(lists_p, 1);

        for (sol_states[1] = lists_p[1].parts[0]->beg;
             sol_states[1] != nullptr && !stop_search;
             sol_states[1] = sol_states[1]->next) {
            partition(sol_states[1], lists_p, 2);
            flip_min_size_part(lists_p, 2);

            for (sol_states[2] = lists_p[2].parts[0]->beg;
                 sol_states[2] != nullptr && !stop_search;
                 sol_states[2] = sol_states[2]->next) {
                partition(sol_states[2], lists_p, 3);
                flip_min_size_part(lists_p, 3);

                for (sol_states[3] = lists_p[3].parts[0]->beg;
                     sol_states[3] != nullptr && !stop_search;
                     sol_states[3] = sol_states[3]->next) {
                    partition(sol_states[3], lists_p, 4);
                    flip_min_size_part(lists_p, 4);

                    for (sol_states[4] = lists_p[4].parts[0]->beg;
                         sol_states[4] != nullptr && !stop_search;
                         sol_states[4] = sol_states[4]->next) {
                        partition(sol_states[4], lists_p, 5);
                        flip_min_size_part(lists_p, 5);

                        for (sol_states[5] = lists_p[5].parts[0]->beg;
                             sol_states[5] != nullptr && !stop_search;
                             sol_states[5] = sol_states[5]->next) {
                            partition(sol_states[5], lists_p, 6);
                            flip_min_size_part(lists_p, 6);

                            for (sol_states[6] = lists_p[6].parts[0]->beg;
                                 sol_states[6] != nullptr && !stop_search;
                                 sol_states[6] = sol_states[6]->next) {
                                partition(sol_states[6], lists_p, 7);
                                flip_min_size_part(lists_p, 7);

                                for (sol_states[7] = lists_p[7].parts[0]->beg;
                                     sol_states[7] != nullptr && !stop_search;
                                     sol_states[7] = sol_states[7]->next) {
                                    // solution found
                                    sol_count += 1;
                                    nodes_searched += 1;

                                    if (opt->list_sol) {
                                        write_sol(sol_states, board);
                                        printf("%s\n",
                                               get_string_notation(board));
                                    }

                                    if (sol_count >= opt->max_sol) {
                                        stop_search = true;
                                    }
                                }

                                attach(lists_p, 7);
                                nodes_searched += 1;
                            }

                            attach(lists_p, 6);
                            nodes_searched += 1;
                        }

                        attach(lists_p, 5);
                        nodes_searched += 1;
                    }

                    attach(lists_p, 4);
                    nodes_searched += 1;
                }

                attach(lists_p, 3);
                nodes_searched += 1;
            }

            attach(lists_p, 2);
            nodes_searched += 1;
        }

        attach(lists_p, 1);
        nodes_searched += 1;
    }

    if (opt->count_sol) {
        printf("solution count: %d\n", sol_count);
    }

    if (opt->list_sol || opt->count_sol) {
        printf("\n");
    }

    output->sol_count = sol_count;
    output->nodes_searched = nodes_searched;

    for (int i = 0; i < DIGIT_COUNT; ++i) {
        lists_p[i].reset();
    }
}

  

 

main code
#include <iostream>
#include <stdio.h>
#include <string.h>

#include "board.hpp"
#include "io.hpp"
#include "misc.hpp"
#include "option.hpp"

using namespace std;

int main(int argc, char *argv[]) {
    int buffer_size = 1024;
    char buffer[buffer_size];

    SolveOutput solve_output[1];
    Option option[1];

    if (!parse_command_line(argc, argv, option)) {
        return 1;
    }

    if (option->help) {
        return 0;
    }

    int count = 0;
    int count_one_sol = 0, count_multi_sol = 0, count_no_sol = 0;
    int start_time_ms = get_time_ms();

    while (fgets(buffer, buffer_size, option->fd) != nullptr) {
        if (strlen(buffer) < BOARD_SQUARE_COUNT) {
            continue;
        }

        Board board = buffer;

        solve_singles(board);
        calculate_state_lists(board);

        solve(board, solve_output, option);

        switch (solve_output->sol_count) {
        case 1:
            count_one_sol += 1;
            break;
        case 0:
            count_no_sol += 1;
            break;
        default:
            count_multi_sol += 1;
            break;
        }

        count += 1;
    }

    int time_taken_ms = get_time_ms() - start_time_ms;

    if (time_taken_ms < 1) {
        time_taken_ms = 1;
    }

    printf("   input puzzles > %d\n", count);
    printf(
        " puzzles by type > exactly one solution: %d, muliple solutions: %d, "
        "no solutions: %d\n",
        count_one_sol, count_multi_sol, count_no_sol);
    printf("  time takes(ms) > %d\n", time_taken_ms);
    printf(" puzzles per sec > %d\n", (count * 1000) / time_taken_ms);

    return 0;
}
posted @ 2018-04-19 19:31  sh0116  阅读(195)  评论(0)    收藏  举报