软件工程基础个人项目
|
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;
}

浙公网安备 33010602011771号