第二次作业——个人项目实战(Sudoku)
项目相关要求
利用程序随机构造出N个已解答的数独棋盘 。
输入
数独棋盘题目个数N
输出
随机生成N个 不重复 的 已解答完毕的 数独棋盘,并输出到sudoku.txt中,输出格式见下输出示例。
输入示例
sudoku.exe -c 1
输出示例
6 1 2 3 4 5 7 9 8
3 4 5 7 9 8 6 1 2
7 9 8 6 1 2 3 4 5
2 6 1 5 3 4 8 7 9
8 7 9 2 6 1 5 3 4
5 3 4 8 7 9 2 6 1
1 2 6 4 5 3 9 8 7
9 8 7 1 2 6 4 5 3
4 5 3 9 8 7 1 2 6
遇到的困难及解决方法
一、第一次使用VS
- 困难描述: 第一次使用VS,程序构建流程不清除,包括如何添加单元测试,将lib与主程序分开。
- 做过哪些尝试: 从github下载gtest的解决方案查看配置,换过无数次VS版本。
- 收获: VS各个版本的功能有所不同, VS compare,最终选择Visual Studio Enterprise 2015
二、单元测试&覆盖率
- 困难描述: VS除了Enterprise版本其他没有覆盖率分析。
- 做过哪些尝试: 使用其他扩展,但没找到一个扩展可以分析VS所托管的单元测试。
- 收获: 切回Visual Studio Enterprise 2015, 成功分析覆盖率
三、持续集成
- 困难描述: 想通过TravisCi和Coveralls+Github进行持续集成和单元测试覆盖率分析,当我push代码(source)之后,Travis 配置 持续集成,单元测试通过之后,自动构建项目,并发布到github,然后coveralls进行单元测试覆盖率分析。
- 做过哪些尝试: 各种Google,猜想:如果需要配置持续集成,必须使用gtest等VS以外的单元测试框架,于是放弃。
设计说明
解题思路
阅读题目后,首先想到的是爆搜,所有的情况有\((9!)^9\) , 仔细分析数独的特点,每一行每一列的数都是1-9 ,并且划分为9个区域,每个区域的3*3方格都是 1-9 ,那么,我们很容易可以确定前3行,先确定第一行的数,第2, 3行再通过偏移得出来,最后得到满足条件的前3行。 得到满足的前3行, 可以通过前三行分块列变换得到后6行,最后得出数独解矩阵。
设计实现
目录结构:
├─BIN
│ checker.exe
│ checker.iobj
│ checker.ipdb
│ checker.pdb
│ lib.lib
│ Sudoku.exe
│ Sudoku.iobj
│ Sudoku.ipdb
│ Sudoku.pdb
│ Sudoku.txt
│
└─Sudoku
│ Sudoku.sln
│
├─checker
│ │ main.cpp
│
├─lib
│ │ check.cpp
│ │ check.h
│ │ generator.cpp
│ │ generator.h
│
└─Sudoku
│ main.cpp
lib:check的方法有:
bool checkdiff(int arr[], int size); // 检查数组的元素是否互异,并且是1-size的自然数
bool checkSudoku(int grid[10][10]); // 检查该grid是否为合法的数独解
int string2Int (string s); // 将string转为int类型,用于命令行输入参数的转换
lib:generator
class generator
{
public:
generator(int sn); // 构造函数,参数sn: 左上角第一个数,并生成第一行满足条件的全排列
int(*generateGrid(int topLine[]))[10][10]; // 生成数独解 topLine: 第一行的排列
void generate(int n); // 打印n个数独解
void printGrid(int Grid[10][10]);
int(*firstLine)[10]; // 第一行
};
generator(6) -> generate(n) -> generateGrid(topLine);
代码说明
generator::generator(int sn) {
firstLine = new int[50000][10];
int line[10];
int cnt = 0;
line[cnt ++ ] = sn;
for (int i = 1; i <= 9; i++) {
if (i != sn) line[cnt++] = i;
}
int tot = 0;
while (next_permutation(line + 1, line + 9)) {
for (int i = 0; i < 9; i++) firstLine[tot][i] = line[i];
tot++;
}
}
// next_permutation 生成下一个全排列,返回true/false
// 预期复杂度 O(9!)
// 需生成至少4*1e4个排列。8! > 4*1e4,满足需求。
int (*generator::generateGrid(int topLine[]))[10][10] {
int (*result)[10][10] = new int [40][10][10];
int grid[10][10];
for (int i = 0; i < 9; i++)grid[0][i] = topLine[i];
for (int i = 1; i < 3; i++) {
for (int j = 0; j < 9; j++) {
grid[i][j] = grid[i - 1][(j + 3) % 9];
}
} // 生成前3行
for (int i = 3; i < 9; i++) {
for (int j = 0; j < 9; j++) {
grid[i][j] = grid[i - 3][(j % 3 == 0 ? j + 2 : j - 1)];
}
} // 生成4 - 9 行
int order[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int tot = 0;
while (next_permutation(order + 3, order + 6)) {
while (next_permutation(order + 6, order + 9)) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
result[tot][i][j] = grid[order[i]][j];
}
}
tot++;
}
}// 对3-6行与7-9行分别换行组合,生成其他满足条件的解。
return result;
}
// 通过组合理论上可生成 2*6*6种数独解。
bool checkSudoku(int grid[10][10]) {
int xx[] = { 1, 1, 1, 0, 0, -1, -1, -1 };
int yy[] = { 1, -1, 0, 1, -1, 1, -1, 0 };
int temp[10];
int cnt = 0;
bool isSudoku = true;
for (int i = 0; i < 9; i++) {
cnt = 0;
for (int j = 0; j < 9; j++) {
temp[cnt++] = grid[j][i];
}
if (!checkdiff(temp, 9)) return false;
} // 判断每一列的情况
for (int i = 0; i < 9; i++) if (!checkdiff(grid[i], 9)) return false; //判断每一行的情况
for (int i = 1; i < 9; i += 3) {
for (int j = 1; j < 9; j += 3) {
cnt = 0;
temp[cnt++] = grid[i][j];
for (int k = 0; k < 8; k++) {
temp[cnt++] = grid[i + xx[k]][j + yy[k]];
}
if (!checkdiff(temp, 9)) return false;
}
} // 判断每一个3 * 3方块的情况,
return true;
}
测试运行
6 1 2 3 4 5 7 9 8
3 4 5 7 9 8 6 1 2
7 9 8 6 1 2 3 4 5
2 6 1 5 3 4 8 7 9
8 7 9 2 6 1 5 3 4
5 3 4 8 7 9 2 6 1
1 2 6 4 5 3 9 8 7
9 8 7 1 2 6 4 5 3
4 5 3 9 8 7 1 2 6
6 1 2 3 4 5 7 9 8
3 4 5 7 9 8 6 1 2
7 9 8 6 1 2 3 4 5
2 6 1 5 3 4 8 7 9
8 7 9 2 6 1 5 3 4
5 3 4 8 7 9 2 6 1
4 5 3 9 8 7 1 2 6
1 2 6 4 5 3 9 8 7
9 8 7 1 2 6 4 5 3
6 1 2 3 4 5 7 9 8
3 4 5 7 9 8 6 1 2
7 9 8 6 1 2 3 4 5
2 6 1 5 3 4 8 7 9
8 7 9 2 6 1 5 3 4
5 3 4 8 7 9 2 6 1
4 5 3 9 8 7 1 2 6
9 8 7 1 2 6 4 5 3
1 2 6 4 5 3 9 8 7
...
性能分析
复杂度:
预估: 假设生成全排列(next_permutation)的复杂度为O(n!), generator(n)的构造函数复杂度为O(9!), generateGrid()的复杂度为O(3!*3!*9*9) 假设需要生成的数独解个数为n 那么复杂度大约为O(9! + n / 25 * 3!*3!*9*9) ≈ 1e8 所耗 CPU 预估小于1000ms 再加上输出到文件的IO操作,大概时间约为1000ms。
性能分析图
性能优化
个人认为,优化可以从输出到文件的IO操作中入手,可以适当增加运行内存当作缓冲区,再输出到文件。
单元测试
单元测试结果
覆盖率测试
PSP分析
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 12 | 20 |
· Estimate | · 估计这个任务需要多少时间 | 12 | 20 |
Development | 开发 | 350 | 515 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 180 |
· Design Spec | · 生成设计文档 | 20 | 40 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 15 |
· Design | · 具体设计 | 30 | 30 |
· Coding | · 具体编码 | 120 | 150 |
· Code Review | · 代码复审 | 30 | 40 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 60 |
Reporting | 报告 | 65 | 85 |
· Test Report | · 测试报告 | 15 | 15 |
· Size Measurement | · 计算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 40 | 60 |
合计 | 427 | 620 |
其他
结合上次作业的评分总结,在博客中谈谈你关于 执行力 、 泛泛而谈 的理解,好与不好都必须列举实际例子、数据或推理加以说明。
执行力:个人认为,执行力就是对于需要做的想要做的事情,是立马去做,还是拖了很久才做。并且做的过程应该是认真的,不是应付的。我觉得我的执行力确实不怎么样,5月份在todolist上的事情,拖到了8月份才做,甚至,8月份只做了一半,感觉周围的诱惑有点多,什么斗鱼直播,csgo,王者荣耀...,关于怎么提高执行力呢,,我也不知道。
泛泛而谈: 大概,在以后的简历上总会出现:熟悉,了解,掌握,这些词语对于计算机专业来说,是很难界定的。对于上个作业出现的:
项目经验也比较丰富吧
这句话,具体来说目前所写过的项目有: West2Join, 代代, **学车公众号,金**微信小程序,**平台超级管理后台, wonderland,以上项目的前端部分.还有就是一些自己练手的小东西。
第二次作业——个人项目实战(Sudoku)的更多相关文章
- 第二次作业——个人项目实战(sudoku)
第二次作业--个人项目实战(sudoku) 一.作业要求地址 第二次作业--个人项目实战 二.Github项目地址 softengineering1--sudoku 三.PSP表格估计耗时 PSP2. ...
- 《Blue Flke团队》第二次作业通讯录项目开题报告
Just_Do_IT! N:8A:8B:7C:6D:8总分:37 Miracle-House N:8A:6B:7C:6D:8总分:35 Spring_Four N:7A:7B:8C:8D: ...
- Solr集群、KI分词、项目实战
Solr是一个高性能,采用Java开发,基于Lucene的全文搜索服务器.同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展并对查询性能进行了优化,并且提供了一个完善 ...
- 软工实践作业2:个人项目实战之Sudoku
Github:Sudoku 项目相关要求 项目需求 利用程序随机构造出N个已解答的数独棋盘 . 输入 数独棋盘题目个数N(0<N<=1000000). 输出 随机生成N个不重复的已解答完毕 ...
- 【无私分享:ASP.NET CORE 项目实战(第二章)】添加EF上下文对象,添加接口、实现类以及无处不在的依赖注入(DI)
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 上一章,我们介绍了安装和新建控制器.视图,这一章我们来创建个数据模型,并且添加接口和实现类. 添加EF上下文对象 按照我们以前 ...
- 《Coderxiaoban团队》第二次作业:团队项目选题报告
<Coderxiaoban团队>第二次作业:团队项目选题报告 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 实验六 团队作业2:团队项目选题 团队名称 Co ...
- 《AlwaysRun!团队》第二次作业:团队项目选题报告
第二次作业:团队项目选题报告 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblog ...
- 【精编重制版】JavaWeb 入门级项目实战 -- 文章发布系统 (第二节)
说明 本教程是,原文章发布系统教程的精编重制版,会包含每一节的源码,以及修正之前的一些错误.因为之前的教程只做到了评论模块,很多地方还不完美,因此重制版会修复之前的一些谬误和阐述不清的地方,而且,后期 ...
- 软件工程基础团队第二次作业(团队项目-需求分析&系统设计)成绩汇总
一.作业题目 团队第二次作业:需求分析&系统设计 二.具体要求 1.作业任务 任务一:组长组织项目组开展需求调研工作(可采取需求调查.问卷.分析已有软件.网上资料等方法).概要设计.详细设计. ...
随机推荐
- 优化hexo访问速度-将hexo部署到云主机VPS
写在开始 一开始将自己hexo部署到github,结果发现打开页面速度有点慢,然后又将其同时部署到coding,实现双线路访问,国内解析记录到coding,国外解析到github,这样确实网站的速度能 ...
- 流畅python学习笔记:第十七章:并发处理
第十七章:并发处理 本章主要讨论Python3引入的concurrent.futures模块.在python2.7中需要用pip install futures来安装.concurrent.futur ...
- Office远程代码执行漏洞CVE-2017-0199复现
在刚刚结束的BlackHat2017黑帽大会上,最佳客户端安全漏洞奖颁给了CVE-2017-0199漏洞,这个漏洞是Office系列办公软件中的一个逻辑漏洞,和常规的内存破坏型漏洞不同,这类漏洞无需复 ...
- Oracle undo我们需要掌握什么
<Oracle undo我们需要掌握什么> 引言:undo 是Oracle数据库的重要组件,刚入门的朋友建议要把undo的原理和机制理解明白,尤其是和redo组件的区别和联系.了解undo ...
- 熟悉JS中的常用选择器及属性、方法的调用
选择器.属性及方法调用的配合使用: <style> #a{ width: 200px; height: 1 ...
- c++类大小问题
1.空类 class A { }; 解析:类的实例化就是为每个实例在内存中分配一块地址:每个类在内存中都有唯一的标识,因此空类被实例化时,编译器会隐含地为其添加一个字节,以作区分. 2.虚函数类 cl ...
- SUID SGID
SUID 1.只作用在可执行二进制文件上,普通用户需要对该文件有x权限, 2.在执行该文件时,用户身份切换为文件owner: 3.执行完毕,切换回普通用户. 一.查找具有SUID权限的系统文件(-40 ...
- 【win10】大水牛主机插入耳机没有声音
主机:大水牛,技嘉主板 操作系统:win10 问题:主机前面插入耳机,没有声音,扬声器图标出错 解决 一..插入耳机 二..Realtek高清晰音频管理器 1.打开音频管理器,点击右下角的设置 2.点 ...
- Flink 1.3.2 Standalone模式安装
一.依赖文件安装 1.1 JDK 参见博文:http://www.cnblogs.com/liugh/p/6623530.html 二.文件准备 2.1 文件名称 flink-1.3.2-bin-ha ...
- zetcode :: First programs in PyQt5
练习代码,详见网站 http://zetcode.com/gui/pyqt5/firstprograms/ import sys from PyQt5 import QtWidgets from Py ...