[Project Euler, Problem 24] 一道编程题引起的思考

最近和同事们讨论了一道小编程题, Project Euler 的第24题.

有的同事能够解出来, 有的同事解不出来,有的同事很快, 有的同事比较慢.

虽然只是有道小问题, 但我们一起还是观察到了不少差别,

 

为此我想到了一个问题:

我们要如何把"解决这些问题" 的知识或者能力, 传递给解决不出来这道问题的朋友呢?

是的, 我指的是提高大家的编程能力, 提高今后解决问题的能力, 而不是只给大家能运行出答案的代码.

 

为此, 我做了一些思考. 整理如下.

 

首先, 题目是这样的:

写道
A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:

012 021 102 120 201 210

What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

 

为了把解决这一问题的能力传递给他人, 教给他人,

我首先问了自己这样的问题: "他/她为什么没有解出这道题呢?"

为此我观察到下面一些现象.

 

一. 心里面有算法, 但是我从下笔, 不知道如何把它映射成程序

 

我们有一个兄弟是这样,

他最终用笔和纸算出了正确答案

(PS1. 但从这一点我便认定他将来一定是个优秀的程序员, 我很喜欢他^-^),

(PS2. 因为用笔解了出来, 所以算法不是全排序),

但是他却没有办法把他在笔和纸上面做的事情映射到程序上面.

不知从何写起, 那必然写不出程序.

 

显然这一问题跟"如何用程序语言清晰的表达实际的问题" (也就是, 如何写出清晰可读的代码)

 

为此, 我们可以先聊一聊如何拆解问题

如何把整个问题拆解成更小的问题, 拆解成更小的函数,

经过这样的层层分解, 我们再从叶子节点(最小的问题开始)反过来, 就可以编写出我们的程序.

推而广之, 在真实的开发环境中, 为了写出漂亮可读的代码, 这些拆的学问, 仍然十分必要.

 

虽然如何拆解问题需要具体问题具体分析,

但是一些通用的法则仍然适用, 比如单一职责,DRY, 正交性, 概念完整性等等.(ps. 有很多进阶的经典书, 你懂的)

如果小问题拆解的恰当, 那么大的问题会迎刃而解,

如果没有拆解,或者小问题拆解的不恰当, 大的问题的求解以及描述就会复杂而不清晰.

 

接下来, 我们可以聊一聊如何抽象问题

自然语言真的很奇妙, 很多时候这两个次得含义差不多,

因为我们在说抽象一个问题, 设计一个问题的时候,

往往也就是把问题从混沌的状态拆解成可以实现,可以执行的若干部分.

 

然而有意识的区别一下抽象和拆解这二者还是有区别的.

比如: 发现一个好概念, 给他一个好名字, 在抽象问题时,这很关键, 而对于拆解问题则不尽然

比如: 有些时候抽象问题会往更泛化,更高层的方向去, 并不像拆解那样更容易把我们引向更小更细的方向.

 

 

二. 算法写了出来, 但是执行结果总是不对, 狂Debug, 但是仍找不到原因.

 

之所以想到这一问题, 是因为我观察到了这样的现象:

 

有些人给出的第一个答案便是正确答案, 他们很自信.

而还有一些朋友的情况,
大家也会很快的给出答案,然而答案是错误的,然后大家会开始Debug
很多时候很不幸, 这个Debug过程很像长征, 但是却没有赢得最后的胜利,
再给出的答案依然错误,
....然后如此反复

 

为什么他们会有如此大的区别?

 

原因在于:

前者使用TDD, 他依赖自动化测试用例保证他的结果正确.

而后者是在使用Debug试图找到程序中的错误(我想我们都亲眼见过也经历过那种狂debug的过程).

从这一问题扩展开来:

我们也可以教会大家TDD,教会大家TDD的思考方式

同时也教会大家不要过度依赖Debug,

PS. 如果学会了TDD的思考方式, 很有助于解决上一个问题(如何拆解和抽象问题).

 

 

----------------------------------------------------------------------------------------------------------

 

总结1: 对培训的价值

经过以上的思考, 我发现这个问题真的不错,

我们几乎可以透过这个问题, 传递(观察)出"任何我们所坚持的, 我们相信他们是正确的以及敏捷的, 那些价值观"

这一点真的出乎我的意料,

是我开始真的跟别人交流"可以/应该用怎样的思维来解决这类题目"的时候,才发现的.

 

同时

这个问题的复杂程度适中, 既没有复杂到难以理解的程度, 又没有简单到不足以说明问题;

而且, 这些问题往往还都能引起大家的兴趣(因为大家都是程序员),

使交流(讨论, 学习, 或者培训)的过程不枯燥.

引申开来(虽然引申得有点儿远), 也许我们可以在team(部门, 公司)里面展开ACM?恩

 

(PS.有时候我们会拿实际的项目来做,然而身边的不少实际项目, 或者本身就存在着一定的问题, )

(或者本身问题有些复杂又不够收敛, 就我目前身边的项目, 我认为更适合边工作边讨论)

 

总结二: 激起对编程的的乐趣, 感受脚本语言的乐趣

是的, 这是我想讨论这道题目的主要目的之一,

我希望他能激起对编程的乐趣, 感受脚本语言的乐趣,

进而产生兴趣去学习这些, 目前还不是生产我们Release代码的编程语言.

看看下面Ruby的解决办法(参这道题目在Project Euler 上的讨论区, 那里还有更多语言的更多解法).

快乐? 优雅? 我相信这行代码会比我的语言更有感染力

 

puts (0..9).to_a.to_a.permutation(10).to_a[999999].join

 

 

写在最后:

最近从一个新同事那里得知了这个网站: Project Euler , 在它上面有很多有趣的编程问题(多与数学相关)

我在最后, 必须要感谢我这个同事, 他告诉了我一个如此有趣的网站~  ^-^

我想在今后, 我要学习一门新语言的时候, 我一定会拿这上面的题练练手.

无聊的时候, 他也一定会给我带来很多的乐趣.

thx, end~

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值