Codewars 打怪日记 5星级kyu 数独游戏 我是否完成了数组 Did I Finish my Sudoku? 看小菜和大神循环的巧妙运用
2016-06-27 19:52
696 查看
史蒂夫·乔布斯说过,每个人都应该学习给电脑编写程序的技术,因为这一过程能够教你如何去思考!学习编程的渠道有很多种,比如你可以利用一些互动平台或者书籍去学习编程,无论是哪种,只要找到适合自己的就OK。编程极富有创造性,你可以创造出许多新奇有趣的想法。很多时候,开发者在相同的问题上花费了大量时间,而忽略了创造性。所以很多网站都发起编程挑战赛,找到千千万的实现方法,codewars就是这样一个在线编程社区,而且有奖励系统激励程序员们像打游戏升级一样地做习题,做的题目难度大,自己段位就升高。随着段位的升高,会获得相应的特权。
只说不练假把式,编程更重要的实践,codewars提供的题目都有实际背景,不管初学者还是小牛,都可以去codewars挑战自己。
进入正题,编写一个函数,输入是一个数组,判断该数组是否是完成了的数独 ,如果是 返回'Finished!'
否则返回'Try again!'; 数独游戏 ,我们从小都玩过,这里的规则是 输入一个9行9列的数组,每行每列都包含1-9个数字,数字不能重复,不能有完全相同的两行或者两列,除此之外,每个区域(小9宫格也要满足这个要求)。如图是一个完成的数独。
我的思路是:先判断每一行是否包含1-9,再判断每一列是否包含 1 -9 ,如果所有行和所有列都包含1-9 ,那么肯定不会有相同的行和列(如果输入的是9*9数组)。然后再去判断 小区域 ,区域是三行三列一个循环,所以在这里,对循环的访问嵌套了四层,时间复杂度达到o(n^4)。好吧,来看看小菜的代码吧。
判断行的时候把每一行放到数组arrR里,然后调用isValid()判断每行是否符合要求 ; 然后判断列,控制循环把每一列放到数组里,。。。 然后就是块,再把块放到数组里,判断。 isValid()的函数就是用来判断一组数组是否包含1-9并且不重复的, 但是方法很笨,首先数组排序,i从1到9循环,看下标为i-1的数组的值是否为i,如果不是则返回0,
都通过了则返回真。
其次,判断行,rows.every(is_valid_row) ,代替了我的两个for循环,对于Array类来说,二维数组其实还是按照一维的访问,只是每一个元素是一个数组,所以这里every的元素就是每一行。
判断列和判断块。块和列分别申请两个二维数组,block的每一行是一个块,columns的每一行是一列。仅仅两个for循环,搞定块和列,然后同样适用every对每一行检测。代码非常简洁,重要的是并不晦涩难懂,所以很值得学习。
最重要的感悟就是多用js原生对象的内置方法。可以减少很多不必要的循环。
ps : 如果比对数独游戏感兴趣点击这里 和 这里 。欢迎交流。关于前端,关于codewars,关于工作和面试。
/*为了判断每一块是否满足,我可谓是煞费苦心,但是最后搞出来四层嵌套循环也是很无奈 ,
只说不练假把式,编程更重要的实践,codewars提供的题目都有实际背景,不管初学者还是小牛,都可以去codewars挑战自己。
进入正题,编写一个函数,输入是一个数组,判断该数组是否是完成了的数独 ,如果是 返回'Finished!'
否则返回'Try again!'; 数独游戏 ,我们从小都玩过,这里的规则是 输入一个9行9列的数组,每行每列都包含1-9个数字,数字不能重复,不能有完全相同的两行或者两列,除此之外,每个区域(小9宫格也要满足这个要求)。如图是一个完成的数独。
我的思路是:先判断每一行是否包含1-9,再判断每一列是否包含 1 -9 ,如果所有行和所有列都包含1-9 ,那么肯定不会有相同的行和列(如果输入的是9*9数组)。然后再去判断 小区域 ,区域是三行三列一个循环,所以在这里,对循环的访问嵌套了四层,时间复杂度达到o(n^4)。好吧,来看看小菜的代码吧。
var isValid = function(arrR){ arrR.sort(); for (var n = 1 ;n<= 9; ++n) { if (arrR[n-1] != n) { arrR.length = 0; return 0; } } arrR.length = 0; return 1; } function doneOrNot(board){ //your code here var rows = board.length; var columns = board.length ; if (rows != columns || rows != 9 ) {return "Try again!";}; var i,j; var arrR = []; ///////////////先检查行 for(i = 0;i < rows ; ++ i) { for (j =0;j < columns ; ++ j) { arrR.push(board[i][j]) ; } if ( !isValid(arrR) ) { return "Try again!";} ; } arrR.length = 0; //////////////在检查列,如果行列都满足,则满足 for(j = 0;j < columns ; ++j) { for (i =0;i< rows ; ++ i) { arrR.push(board[i][j]) ; } if ( !isValid(arrR) ) { return "Try again!";} ; } //////////////判断每一块是否满足 arrR.length = 0; <span style="color:#ff0000;"> for (var count = 0; count < rows ; ) { for(var countC = 0; countC < columns ; ) { for ( i =count ;i < count + 3;++ i) { for( j = countC ; j <countC + 3; ++j) { arrR.push(board[i][j]) ; } } if ( !isValid(arrR) ) { return "Try again!";} ; countC += 3; } count += 3; } <span style="font-family: monospace; white-space: pre; background-color: rgb(240, 240, 240);">/*为了判断每一块是否满足,我可谓是煞费苦心,但是最后搞出来四层嵌套循环也是很无奈 ,思路就是最外面两层,代表行和列,每次增加3,这样这样控制访问到9个小块,*/</span></span>
<span style="color:#ff0000;"><span style="font-family: monospace; white-space: pre; background-color: rgb(240, 240, 240);">/* 然后每个小块的填充又用了两层循环,第一层三行,第二层三列,这样组成3*3的数组,然后调用isValid()判断是否有效 */</span></span>
<span style="font-family: Arial, Helvetica, sans-serif;"> return "Finished!"; </span>
}doneOrNot()函数思路就是
判断行的时候把每一行放到数组arrR里,然后调用isValid()判断每行是否符合要求 ; 然后判断列,控制循环把每一列放到数组里,。。。 然后就是块,再把块放到数组里,判断。 isValid()的函数就是用来判断一组数组是否包含1-9并且不重复的, 但是方法很笨,首先数组排序,i从1到9循环,看下标为i-1的数组的值是否为i,如果不是则返回0,
都通过了则返回真。
function doneOrNot(rows){ var columns = [] , blocks = []; for (var i = 0; i < 9; i++) { columns[i] = []; for (var j = 0; j < 9; j++) { var k = Math.floor(i / 3) + Math.floor(j / 3) * 3; blocks[k] = blocks[k] || []; blocks[k].push(rows[i][j]); columns[i].push(rows[j][i]); } } var is_valid_row = (row) => row.slice(0).sort((a, b) => a - b).join('') == '123456789'; var is_valid = rows.every(is_valid_row) && columns.every(is_valid_row) && blocks.every(is_valid_row); return is_valid ? 'Finished!' : 'Try again!'; }看看高分代码吧!首先也是把 判断一个数数组是否满足要求单独写一个函数,但是他的实现方法不用循环,很简洁,还用了es6的新的箭头函数。row.slice(0)复制数组,大概是为了不污染输入数组,row.slice(0).sort((a,b) => a-b) 排序,row.slice(0).sort((a,b) => a-b) .join('') == "123456789' 排序之后分割成字符串 ,看字符串是否等于1-9。 简单的代码,用原声的js方法代替了我的循环,效率肯定比我的循环快。
其次,判断行,rows.every(is_valid_row) ,代替了我的两个for循环,对于Array类来说,二维数组其实还是按照一维的访问,只是每一个元素是一个数组,所以这里every的元素就是每一行。
判断列和判断块。块和列分别申请两个二维数组,block的每一行是一个块,columns的每一行是一列。仅仅两个for循环,搞定块和列,然后同样适用every对每一行检测。代码非常简洁,重要的是并不晦涩难懂,所以很值得学习。
最重要的感悟就是多用js原生对象的内置方法。可以减少很多不必要的循环。
ps : 如果比对数独游戏感兴趣点击这里 和 这里 。欢迎交流。关于前端,关于codewars,关于工作和面试。
/*为了判断每一块是否满足,我可谓是煞费苦心,但是最后搞出来四层嵌套循环也是很无奈 ,
相关文章推荐
- 我们需要的是实践
- JQuery开发的数独游戏代码
- 项目实践之javascript技巧
- 15条JavaScript最佳实践小结
- Appium自动化测试系列2- 写一个Python测试脚本来测试一下YY语音
- 8. react-native-android之----模拟手机百度feed流
- 为什么你的运营方法论在工作中用不上?理论和实践的距离有多远
- Node.js学习笔记一
- 内存泄露从入门到精通三部曲之常见原因与用户实践
- Git入门与实践
- 实践是检验真理的唯一标准——《精益创业实战》让你的成功飞起来
- 有了梭子和毛线就能织出各式各样的衣服
- Linux fedora 实践
- 敏捷的真正腐败【The True Corruption of Agile】
- 想法值几个钱
- Restful API的设计与实践
- 数据结构实践项目——串
- 岁月划过生命线——记我的大学生活(前言)
- 岁月划过生命线——大一上
- 岁月划过生命线——大一下