google reader 朋友规则简化

今天下午google reader忽然发给我好几十个邀请,是一堆buzz上fo了我的人,现在想要我给他们分配在reader上comment我的权限。由于这个权限我设定是在某个group里的人才能comment,导致权限设定很麻烦,直接点击他给我的一个allow-ignore链接,他会弹一个对话框告诉我,无法这样简单设定,需要到google contacts那里面去设定。

说起来google contacts还真是一直都做得比较混乱,各种不同类型的关系和权限级别我一直都没搞清楚。再加上很多buzz上fo我的人,他隐藏了自己的gmail地址,我还真不知道怎么弄才能把他弄进group里去,直到后来才发现点击他的名字link,会进入到他的reader share列表,那里会有一个link引导你把他加入一个group。。不过这操作流程也实在太不友好了吧。。要找这么久。。

没过多久,大概一个小时?刷新reader的时候发现google立即简化了自己的朋友规则,现在所有fo我的人都可以在我的item下面comment了。恩这样才是合理的嘛。

其实人际关系是所有关系里面最复杂的东西了。也难怪这部分google总也做不好。如果只是做通信簿还挺容易。但是涉及到人际关系,要把人分组,分类,设定权限。。这就太复杂了。尤其是又要涉及到隐私问题,又不能随便实验。用google那工程师脑子,不太可能搞得好这部分内容。他们现在开始尝试简化这部分,也是一个有益的尝试吧。

gcj又败了。。不甘心啊

呼这两天一直在玩gcj,本来还挺有信心的觉得应该能进第二轮,结果又悲剧的死在门口了orz|||

round 1A是早晨9点开始的,我8点多爬起来玩,可能是早晨确实状态不好吧,连第一题脑残题都没做对,事后发现居然是遍历数组的时候写反了i和j,绝对白痴啊。后面的动归和数论题其实也挺简单。事后想想其实1A是最容易过的,题目又不难,参赛人数又少(只有2000多人)。没把状态调整好结果挂了挖哈哈。名次都是倒数几名里面的。

round 1B是半夜0点开始搞到2点半。没想到题目出奇的简单,几乎所有人都做出了前两道题。结果我居然卡在第三题上了,第三题是类似斐波那契数列那样可以顺序求值的一个数列,只不过每求一个新的元素的时候需要一些判断条件,我就卡在那个判断条件上了。。是因为过了2点脑袋就昏了还是怎么也不知道,明明只需要加减法的一个等式,偏偏是推了半个小时也没推出来囧|||可能室友熄灯睡觉了让我也犯困了吧(喂喂找什么不搭界的借口啊。。)结果由于第二题小数据错了一次,排名排到了1013名。。离入选下一轮的1000名仅有13名之隔。。呜怨念啊。。

round 1C是最后的机会了,时间是下午5点。第一题依旧脑残之外,第二题我貌似没有看清题意。我直接用对数再算二分法的时间复杂度(又是2的对数)给的结果,小数据提交正确了。我看了一下大数据给的范围用double没问题,就没改代码直接又提交了大数据。当时名次是300多名,并且到比赛结束的时候还是480多名,虽然第三题再次悲剧的没做出来(第三题实在是简单,问题是实在是太麻烦了吧。。不是拼算法是拼编程速度啊。。我这样没有练习过的人只有悲剧啊。。)我还一度以为这次可以开心了。结果没想到第二题大数据判错,把我摔到了1100多名。呜现在暂时没心情。。过一会去下载个正确解看看。。第二题究竟是啥地方我没考虑到呢?还是完全错解了题意小数据只是碰巧对了?

呜总体看来这次失败问题还是很多的,最重要的问题就是理解题意的能力太差,很多题基本上都是提交小数据判错才知道其实根本就是题意理解错了。。囧|||至于说编码太慢,写个遍历写半天,这种问题是没办法了。。懒人平时不练习最后就只有这个下场。。不过话又说回来round 1的比赛还真没有什么算法,基本上都是枚举解决问题,或者一行公式搞定。。基本上是考察编程基本素质的。。唯一用到算法的可能就是几道动归题了(呜全都悲剧的来不及做。。)

不过经常参加参加比赛打打酱油还是蛮有好处的,这三次比赛咱的状态也是越来越好,到1C的时候前两题也差不多40多分钟就搞定了。不像1A的时候磨蹭了1个多小时一道题都没搞定。。

总归,反正我也不是专门搞这个的,强身健体参与第一啦(又来自我安慰了囧|||)

明年再努力吧!这之间有时间就加加油多练习就好啦,趁着读研的闲空~

Google pac man

google这次换的图标太有才了。。居然把游戏直接嵌上去了。。
而且原来的“手气不错”按钮变成了insert coin…可以支持两人对战!
分别是方向键和wasd。。。一男一女。。。pac man & pac woman。。。
太强大啦。。

还能相信谁

最近在网上看到太多让我绝望的事情,各种内幕大便汁灌臭豆腐,还有http://feedproxy.google.com/~r/chinagfwblog/~3/yYg_7VxoIxk/13.html。愈发让我感觉到整个社会根本就建立在一个其实早就瓦解了的基础之上,摇摇欲坠。

之前消息传出,我们即使是说赖以生存也不为过的互联网,只需几个小时就可以让他全面崩溃。那个时候我说,互联网是建立在互相信任体系上的学术模型,对当前的商用领域不能符合要求。当然互联网最初是为了军事目的建立的,但是建立之初他只是作为一个内联体系,没有考虑过要和自己的敌人,或者竞争对手存在于同一个网络之上。因此他现在的诸多不安全因素,其实也源于它本身的“公理”,他建立时所依据的最基本的一些假设。那就是大家使用这个网络都是出于好的目的,能够遵循协议并且互相信任。这是互联网的基础。

互相信任,这是互联网的基础,也是整个社会的基础。这是我那个时候没有想到的。你去理发店剃胡子,理发师随时可以将你的喉管割断。你的钱存入银行,银行随时可能破产。你买房子,从没问过地基究竟挖了多深;你去饭店吃饭,也不会(现在是也不敢)琢磨这饭菜究竟是走了怎样的流程在摆在眼前的。

因为整个社会的运转,必须是建立在最基本的互相信任的原则之上的。否则人生将成为一场永无止境的战争,你的每一个睡梦都将被冰冷清脆的后窗敲碎的声音惊醒,被永无宁日的轰鸣的铜钟扰得不得安宁,被焦急和燥热似无数蚂蚁上身而痛苦不已。

然而,信任,这社会运行的最基本的一环,正在渐渐破碎。

未来究竟会成为什么样子呢?我小的时候曾经做过这样的猜测:1)要不然有一股强大的力量足以维护每一个人的利益,使得大家都得以放下戒心和手中的武器,2)要不然所有的人都变成武林高手,有钱人顾保镖,有力的人开武馆,穷人和老弱病残只能忍受人间炼狱的痛苦和同样生而为人的手足同胞残害。

没有人希望情况变成后者,那跟无政府主义有什么区别,假如没有一种至高无上的力量足以遏制形势挽回局面,整个社会最终只有分崩离析,堕入永无天日的窘境。

但那强大的力量是什么呢?3000年前,社会动荡曾经比当今还激烈,诸子百家没少争吵这股力量究竟该是什么。没有人给出解答。是军事和行政的强权吗?秦灭足以为证。是所谓“仁义道德”吗?生活困苦的百姓连饭都没有的吃那什么去念仁义道德,蛀虫和瘴虐作威作福,用什么去推动他念仁义道德。是宗教吗?看看西方宗教历史的丑陋血泪和腐败,哪一点比不上无神论者。是财富吗?用钱能买的来文明吗?还是说只能买的来鬼推磨?

先别说集体吧,先说自己。在这么一个恐怖的世界里,一个人究竟还能相信谁,相信什么?新闻报道?我们看得到的只是不同派别不同利益集团的争权夺势。只不过是我们也恰巧属于其中的某个利益集团,因此就觉得某些人的话格外好听,而另一群人的话格外刺耳或格外可笑而已。饮食卫生?吃的喝的最好尽量出自己手。虽说自己种地是种不了了,但是少吃饭店,少用乱七八糟调味料,少用别人加工过的东西,总归是有好处的。医疗保健?现在医院已经是最不可靠的黑洞了,能不去医院尽量别去。流感是绝症,医院又治不了的,平日强身健体,经常接触病原,感点小冒,闹点小肚子,反而是好事,不干不净吃了没病,其实也不是瞎说的。 记得小时候看读者有篇文章叫“健康人不怕传染”,印象很深。所谓小病不断,大病不来,让身体的防御系统随时处在备战状态,身体自然硬朗。至于得了大病,开刀动手术免不了的,哪怕多交钱,也比被医院害了强。至于绝症,我有自己的看法,假如我得了绝症我就不治,让他该怎么着怎么着,我该咋活还咋活。又化疗又放疗的,头发掉光身体浮肿连话都说不出来,就为了多续几天命,在我看来没意思。有那闲钱多享受几天短暂而美好的炼狱人间不强多了。更别说保健了,啥补品啊美容啊减肥药啊增高鞋啊从小就没信过,今后更不会信,但愿所有人都不要信。真正该信任的就是自己的身体,他生是什么样子,就该让他按照自然的法则去运作。用人造的去掩盖甚至替换自然的,就像用破布去掩盖真金。

又回到前面关于社会的讨论,要在这样一个恐怖而黑暗的世界上活下去,要拥有的,除了勇气和正义之外,还需要的就是智慧。上天赋予人智慧,除了用于互相欺骗互相摧残互相杀戮之外,也是用来互相帮助以存活下去的唯一希望。我以前太小了,总觉得自己了不起,有一颗还算灵光的脑袋,能解习题,能听懂故事和传说。那时候幼稚的我狂妄自大,瞧不起因循守旧,固守着自己的经验不放的“老年人”。瞧不起用拼命做习题用套模式套公式的方式解题的“死脑筋”。但是现在我认识到自己的错误了。其实人的智慧,正是来源于经验。人的智慧,本来就是用来分析整理所有这些经验的一个模型。庄子有句话说的很好:“朝菌不知晦朔,蟪蛄不知春秋”。没有一整天的经验积累,就不可能知道昼夜交替,没有一整年的经验积累,就不可能知道季节变换。同理,人生苦短,经验不足,更不可能了解以世纪为单位以纪元为单位的变化。因此,除了不断积累自己的经验以外,学会利用他人的经验,利用历史的经验,是延伸自己智慧的必须手段。

上两节貌似说跑题了,其实也不算跑题,主要是说在这个黑暗的世界上个体该如何挣扎吧。至于群体呢,我想,也就是前面说的那股“强大的力量”,可能就是求生的本能吧。

每个人都希望能活下去,能活得更好,能享受这人生炼狱里的每一分每一秒。这种本能在人与人之间传递,或许最终能够拯救世界。当人与人之间再也无法信任,当运一担“生辰纲”都要雇镖头押运,正大午赶太阳路还生怕遭了劫匪,当最平常的信件都必须加几层密码,还要怕被人偷换过签名,当饭不敢吃水不敢喝夜不能寝食不甘味,人人自危,生活好像无以为继,假如人类社会到了这种程度,居然还有机会继续前进,假如文明竟然幸运到不至于就此止步,那一定是求生的本能唤醒了人心底最后一丝良知。大家终于决定停止互相欺骗的战争状态,终于决定坐下来,制定一个协议,共同遵守,互相信任,互相帮助,那这个社会才有可能在那崩溃的边缘,终于煞下车。当人们受够了苦难,最终应该能学会放弃目光短浅的小聪明吧。毕竟大自然赋予生物的两条路,正是促使生物繁荣昌盛的基础,一是求生之门,一是地狱之渊。

当然,正如庄子所说,小年不及大年,小知不及大知,以世纪为单位的人类文明的脚步,将向何方前进呢?仅以幼稚的我,当然无法判断,正如寿命仅有几个小时的短暂生命,无法判断,这恐怖的黑夜,究竟什么时候能够结束,一样。

lisp学习笔记

2013年重读这篇笔记,错误很多,对定义的理解有很多混淆;作为自己学习和成长的记录不再将其中的错误一一纠正了

刚刚开始学lisp,还只是开始熟悉他的语法。但是学lisp确实是开阔眼界的一个好办法,能从更高的角度来看程序语言。

至今为止任何类型的程序语言其实都是图灵机的一个实现。比如说经典的x86 CPU吧,他就是一个图灵机。这个问题我其实还是想了好久才想出来的。可能是我太愚钝了吧。。图灵机的一种描述是这样的,存在一个两边都无穷长的纸带,一个含有一系列状态和命令的指针。这个指针一次执行一个命令,或者向前或向后移动一格,或者在纸带上读取或写入一个符号,命令有可能改变指针的状态。而读取到的符号会根据指针的当前状态产生一个新的指令。循环往复。直至到达某个特定的状态(终态)停止下来。

一开始我觉得CPU的寄存器表示状态。可这样的话,寄存器的值是不确定的,于是似乎不能模拟确定有限自动机。静下心来想想,其实应该认为所有寄存器的一种取值组合就是一个状态,所以假如有m个寄存器,每个寄存器的取值数量是ni,则总的状态数量就是i从1取到m, 将所有的ni相乘。(不能打公式郁闷。。)然后应该认为汇编代码就是那个带子上的符号。这样比如

ADD a, a, b ;a=a+b

这样的一条指令,应该看作是一个符号(所有可能的汇编指令应该是有限的,可以认为每一个都给编了唯一确定的符号)。这个符号对应CPU的不同状态,(例如这里的a和b的所有不同状态组合),可以看作每个状态都有接受了这个符号之后指向一个新的状态的箭头。使得寄存器状态改变。比如对于a=1,b=3这组状态(1, 3),这个箭头就应该指向(4, 3),当然这里没有考虑溢出位啦。同时又存在一些其他的操作,例如处理内存或中断的操作,可以看作是向纸带上的特定位置写入字符(由于内存和中断的数量也是有限的,所以可以给他们的每一个地址对应纸带上的一个位置)。

那么lisp呢,lisp是怎样实现图灵机的呢?

根据lisp1的自解释逻辑,可以认为lisp是一个不断扫描输入纸带的一个指针。他的状态则由输入中给定的“环境”决定。可以认为lisp仅有函数定义和函数调用两种语法。对于函数定义,其实是增加了新的状态组,把它的所有形参的所有取值组合看作是一组状态加入到自动机中。而函数调用,就是将实参值带入形参,计算函数结果的过程,对应于状态接受一个输入指向另一个状态的一个箭头,即在此实参情况下,如何应该进入什么样的下一个状态(次态)。

不过很有趣的是,鉴于lisp的递归定义,可以认为他的状态机也是递归的。在运行的最初,该状态机仅有函数定义及函数调用的最基本语法。指针扫描纸带(程序源代码)一遍,生成了最外层的函数定义,这是状态机为这些新函数增加新的状态,之后指针移动到该函数调用的起始位置,第二遍扫描源码,生成新一层次的函数定义,向状态机添加新的状态,直至最终所有的函数定义全部生成结束,递归到最底层,所有的实参都被计算成为原子,再依次递回,直至最上层。

从这个角度看lisp的有趣之处在于他用自己的规则定义自己,不断充实自己。不过也因为这种灵活性,使得用c实现一个高效的lisp编译器变得有些困难。一开始我在考虑的是lisp只有递归没有循环,确实不符合c语言的常规思路。不过转念一想,尾递归优化成循环其实倒反而是一件轻松的事情,只需要将形参改成自变量,把递归调用的那一句改成goto到函数开头就可以了。然后再改成while循环即可。麻烦就麻烦在这个函数的动态声明。有没有可能一次扫描完lisp文本之后就确定全部的函数定义呢?给定两个附加条件,一是所有的函数定义必须在他的调用的同一级或外层(注意这里指的是定义这个函数的外层,而不是调用这个函数的外层),二是函数定义必须在函数调用的前面。这样就可以逐级求值而避免递归了(相当于首递归)。当然这里避免的仅仅是(相当于)编译期的递归,在(相当于)运行期的递归仍然是避免不了的(也不可能避免)。当然对于lisp而言,编译和运行是交叉进行的,也没法分得这么仔细啦。(所以才说是解释型语言嘛。。汗)当然话说回来,将lisp先编译成机器码再运行也是可能的。只是编译时间会比较长而已,而且对于变量类型可能要做一些处理。(最简单的想法是用链表,不管是树也好,字符串也好,数字也好,都可以用链式结构存,以适应lisp的list结构。)

好吧,先做这些记录,下次有了感想再写了。

呼,因为结束实习,搬家,赶毕设,一下子好久没有写博了呢。。今天终于补了一篇。。证明我这段时间也没有荒废时间啊。。以后还是要经常写博客自勉啊。。回头看了一下大半夜的逻辑有点混乱估计有写错的地方。。不过天色晚了没心情挑错了,改天再回来改吧。。

旅行商问题的一点笔记

最近朋友跟我讨论了一个类型的旅行商问题。原版的旅行商问题是说,给定一个图,给定起点和终点,求不重复经过任何节点的最短路径,遍历全部节点。而他的问题是,仍然不许重复经过任何节点,但是不要求路径遍历全部节点,而是遍历某一个给定的关键点集,求最短路径。问题里面对图没有做任何限制,图可能包含数千节点,不过关键点集是充分小的,比如只有5个关键点,这样。

一开始我没听清楚题目,以为这个问题跟斯坦纳树有什么关系。(所以才会写了上面一篇note。。)不过后来知道不许重复经过节点,那么这种想法就没有用了。

不过既然关键点集充分小,求的又是路径,那么几个关键点必然只能依次经过。可以尝试所有关键点的排列,依次求最短路径。比如说5个关键点,也只需要算120次。还算可以接受吧。并且假如采取分支定界,其实还是可以减去很多分支的。当然可以构造出几个关键点无论怎么排列,路径都等长的情况。比如所有两两点间都有路径长度为1的任何图,都是这样。。。不过假如是工程上使用的话,可能还有其他办法可以提前退出,比如求出“足够好”的解,或者算了很长时间,一直没有找到更好的解,之类的。。这个就可以根据需求而定了。

不过朋友比较担心的是割点的问题。割点是说,一旦去掉这个点,则图会被拆成两个独立的联通分量。就是说从图的某些点出发,永远也无法到达图的另外一些点了。。之所以担心这类点,是怕一旦算法的前面走过了这类点,那么由于存在不许重复任何节点的限制,可能导致某些点无法经过了。那么这个割点至少有两种情况。就是这个割点会导致关键点被割掉,或者只会导致非关键点被割掉。

导致非关键点被割掉的那种割点,可以直接收缩为一个点。因为题目并不要求遍历非关键点。并且求出的路径绝不可能进到那个割点后面去(因为1.里面没有关键点,2. 进去就出不来了)。那么至于说会导致关键点被割掉的情况呢?暂且也把他收缩为一个点吧。如果不断这样收缩,整个图就会最终退化为不含割点的图。并且最后一次收缩的割点应该不会超过两个。假如超过两个,那么这个图是无解的。因为总有一些关键点,你要经过一个割点才能进去,然后就出不来了。至于不超过两个,那是说起点和终点可以从割点经过。当然这个是欧拉说的啦。。

比如上面的图,每个椭圆表示里面有一坨点,并且里面的每个点都至少有两个入度。假如上图的三个小椭圆里面都有关键点,那么这个题就无解了。假如任何一个小椭圆里面没有关键点,那么就可以直接去掉。

最后肯定只有不超过两个小椭圆里面是有关键点的。比如上图的红色椭圆。可以暂时收缩成一个点。

所以最后一次收缩的割点,不会超过两个。

那么其实这种收缩可以重复进行,于是可以写出递归代码来解。当然现在问题就转化成,对于没有割点的情况,怎么解这个问题。

当然其实问题的难点,也正是在没有割点的情况下吧。。还是继续前面那种遍历所有关键点顺序的那个思路,这回每次需要考虑的关键点都变少了(好吧也可能没变少,至少不会变多!!)。接下来的事情可以参考旅行商问题的一般解法来求吧。。因为不是我的题目,所以没有继续去查。。同样是做个记录留下来吧。。还是方便以后捡回来。。

斯坦纳树的一点笔记

大三的时候做了一道斯坦纳树的题,最近几天朋友跟我讨论某个问题,忽然觉得跟那时候的做法很类似,结果发现自己没有留下任何材料。想了半天把那时候的想法回忆起来了。当时没有留记录是因为想法太简单,算法性能太差。不过现在想想无论好坏,啥想法都应该记下来,以后至少可以在这个基础上继续走。

Steiner Tree, 就是说给定一个图,和他的节点的一个子集。求包含该子集内所有节点的最小生成树(不要求包含全图的所有节点)。其实是算法老师留的作业,那时候也没当回事周末随便写了点。结果发现这个居然是一个NPC问题。只好临时想了一种解法。还是沿着prim算法的思路走,每次向已生成好的树里面增加一个新节点。只不过这次,每次都只增加关节节点集里面的节点。而寻找节点的时候,需要用Dijkstra算法。并且找到需要加入的关键点后,也需要把路径上的其他非关键点也加入进正在生成的树上面去。说到Dijkstra算法,复杂度是n^2, 再加上prim算法复杂度也是n^2,复杂度岂不是到达n^4?其实没有。因为每次使用Dijkstra算法,都把某一个点到其他所有点的路径长度都求出来了。而最终的结果,最坏也不过把所有节点两两之间的最短路径求出来,相当于填了一张n×n的表,n是节点数量。用一次Dijkstra算法可以填一行。总共n行所以复杂度是n^3。恩这里算是用到了动态规划。性能还算是可以接受吧。不过这个算法明显求不出精确解。我也没有证明过他求出的解究竟能多逼近,或者在哪些条件下能求出足够逼近的解。只不过是当时老师给的样例输入正好碰上是返回正确结果,就这样交卷了。

恩后来又在网上查了很多资料,貌似斯坦纳树研究的人还是很多的。不过搜到的资料大多是些没法下载的论文。。。所以也就荒废了没有继续看下去。。今后有机会在继续看吧。这次只是把过去的思路记录一下以后方便捡起来。

Google 实时搜索

可能是我火星了。不过第一次看到这个一直在滚动的实时搜索结果。

主要内容有各新闻站点,也有来自twitter的消息。

另外,又是大地震。。。

协作开发和二进制管理

因为经济的原因,协作开发一直是仅做源代码管理,由开发者checkout代码后自行编译。

但在有大笔资源的情况下,时效应该是更为重要的东西,为什么不考虑二进制管理?

在公司,一个项目编译出来需要3到5个小时。。(会跑来这里写东西的原因也说出来了。。)。。反正提交代码之前每个人都必须做build, 做测试,然后才能提交的,为啥不一开始就把大家build的结果保留下来,需要用的人自取呢?

这正好可以跟系统每天的daily-build和test-suite结合起来,一起完成。

开发过程还是一样,checkout, update,之后提交。但这个时候提交的内容不要直接进main branch. 先在他checkout的版本基础上,patch上他的update,之后做buddy-build和test-suite。如不通过,打回重练。这个过程可以以天或者以周为单位。以天为例吧。每天晚上12点,系统尝试将通过测试的patch进行合并。如果合并失败的话,就把导致合并失败的patch拿掉,直至合并成功为止。如果成功合并,进main branch, 并且做daily-build和test-suite。假如合并之后导致新的bug或build break产生,应该知道这些问题是协作造成的,将受影响的文件或模块相关的patch除去,重新build-test。直至没有bug产生为止。次日早晨发邮件给没进main branch的patch的owner们,让他们解决问题。

关键在于编译。在编译脚本里面可以加上新的机制,允许从服务器下载跟本地版本相符的obj,lib,dll,exe等内容。即编译器需要和源代码管理器协作,确定即将编译的一段代码是否被edit过。如果没有被edit过,检查目前版本的代码在服务器上是否有相应的二进制目标文件。如果有就可以直接下载,如果没有才考虑自己编译。这个过程跟编译顺序相反,是自顶向下,从最终目标开始比较,尽可能下载整个的lib,dll之类,这样就可以避免下载很多可能本地根本用不到的obj文件。

当然,由于二进制文件没有有效的增量备份算法,在服务器上不可能保存所有版本的二进制文件。但至少可以保存最近几天或几周的版本的,还有历史上的几个milestone版本的。

当然在这种机制下必须要求所有人都在最新版本下工作,否则必须新开branch。每天的patch都只能接受从当天版本号基础上checkin。如果有旧版本的patch提交,可以有两种选择,一种是要求开发者更新到最新,然后重新提交patch,另一种是要求开发者开新branch, 并在新branch上做开发。具体选择哪一种看具体需求以及开branch的成本了。

毕竟当项目变大,每个人要处理的模块都是很小的一部分,其余的部分只需要lib,dll就可以了,没有必要自己编译。并且,如果不需要编译,其实开发人员的机器配置就没有必要那么高,节省的成本可以做更好的服务器机器。其实这种策略也更符合所谓“云计算”。当然更加有趣的是,可以让编译本来就发生在由所有客户机结成的计算网格上面。并且所有的二进制文件也都分布式存储在这些分散的机器上面。服务器仅仅是一台或几台管理信号的中转路由。这样做可能可以进一步降低成本,并且对于每个计算网格而言,本地编译某个模块,然后二进制文件就存储在本地,也没有太多网络开销。当然具体算法如何实现,这个恐怕要仔细研究了。(研究生课题?:)

程序员的世界

不是说把人生编成程序。只是说程序员的人生。

今天偶然看到这篇文章,21天学通C++,很有感触。

其实学通C++,这个词的含义无法准确定义。究竟什么是学通C++。如果说是要完全掌握使用C++编程的技巧的话,需要的时间是无穷的。因为难并不在于C++,而在于编程。

使用编写程序是一种生活方式。它不仅仅是工作或者学习。就像舞蹈或者作诗也是一种生活一样,一旦你进去了,就出不来了。程序员的生活沉浸在无尽的逻辑,抽象,接口,复用,通讯,数据,算法,blabla之中。。。

程序员的世界是抽象的

程序员看到的不是人,而是某一“类”人的一个“实例”。有些人是虚基类,你看到很多貌似相同的人,在某些具体的方面却有着完全不同的行为。有些人是模板类,很多貌似不同的人,却有着惊人相似的行为。有些人是单件,失去了就再也找不回来。

程序员看到的不是化学定律,不是生物学定律,不是物理学定律。程序员看到的是数学规律在各个具体场景中的表达形式。用相同的程式,程序员可以模拟桌球碰撞,可以模拟气体飞散,也可以模拟生物群落迁移,牛奶混合进咖啡,或者婚姻的结合以及破裂。

程序员的世界是定量的

程序员不理解“质变”,只理解“量变”。当别人看到悲剧,程序员看到概率。别人谈“可行性”,程序员谈“可能性”。任何东西都可以定量估计,不管是系统崩溃的概率,银河系中存在类人外星人的星球数量,还是一杯温水忽然一半结冰另一半沸腾,或者身边的椅子忽然变成一个美女的可能性。一切的一切,只要存在,就可以定量估计。

减肥的人会为少吃一块巧克力而自豪,而程序员指出其实瓶颈不是少吃了多少而是消耗了多少。排队的人为插到前面一个人而高兴,而程序员指出其中机会成本其实更高,而利益没有几秒。程序员乐于估算一辆公交车能装多少皮球,75码能把人撞飞多远,或者人一生能打多少个喷嚏。这些喷嚏造成的推力能把一架喷气飞机推进多远。

程序员的世界是协议化的

程序员调用函数,遵照函数的规格声明。程序员发送消息,遵照网络协议手册。程序员对这个世界过度“预判”,并根据这种预判作出推测和决定。程序员预判其他人也是程序员。所以大家任取1~100之间一个数,要想最接近所有数和的2/3,那答案必定是0。程序员预判其他人也会遵照协议,所以拿着用户手册去跟客户争吵那不是bug而是feature。

程序员制定协议,程序员遵照协议。然而如果事实证明协议无法实现,程序员会孜孜不倦的抛弃他,并重新创造新的协议。然而程序员不可能离开协议而存在。程序员需要protocol, 需要pattern, 需要manual  and guideline。程序员在种种规则和限制之中,找到了自由,假如失去了规则限制,程序员反被关在混乱的牢笼里,寸步难行。

程序员对程序是虔诚的

程序绝不会犯错,如果犯错一定是程序员的错。程序员一定会犯错。程序员像一群苦诵经书的狂信徒,无尽的敲出一行又一行一段又一段的咒语。据说摩西五经其实包藏了耶和华的真名,而这真名只有通过反复诵读才能体会。而代码之中也保藏了程序的真谛,无数程序员在反复敲打之中要去领悟醍醐。

公司里很多同事坐久了腰痛,干脆跪在机器前面写代码。虽则这种膜拜不能就另拙劣的代码产生灵性,然久而久之,程序说不定产生佛性,亦有可能。

一只脚已经踏入这个世界,我现在仿佛觉得这个荒谬的世界才是真实的,反倒是外面的世界是无法理解的。进入这个世界的话,就离不开了吧。