2008年03月31日 10:32
假期结束,恢复到上班状态。
突然发现今天居然是3月的最后一天了,而明天则是传说中的愚人节。希望不要有人来愚弄我,我不喜欢这种感觉。
在休假期间主要还是把精力放在了g4p方面,做了代码的Code Review并且提交了自己的代码。看着这个项目的代码渐渐的多起来,虽然还没有到可以初步运作的程度,还是觉得很高兴。
昨天跟g4p项目组的人员碰了一下面,交流了一下目前项目的进展和问题。解决了一些问题之外,大家对当前的项目进度还算满意。毕竟刚刚开始,而且面对如此松散的团队,没有具体的激励形式,大家对开发语言和工具的掌握还有待改善的情况下,不能对项目的要求过于严厉。后期可以逐步的加快进度。另外还初步的讨论了一下网站的定位和发展的问题。不过我们都觉得现有的目标不做大的改动,把想法都记录下来,等到我们有东西出来之后再考虑。
当然,秉承BT群聚会一向的BT风格,海阔天空仍然是免不了的。在项目讨论之外,我们还讨论了一些创意想法、黑客技术、IT业界以及其他河蟹及不河蟹的话题。其中有人提到说现在李开复和唐骏都属于那种没做什么事的人,为什么还在那个位置上呆着。结果今天一早来就看到了唐骏离职的消息。为BT群深厚的BT威力囧一个。也为开复Lee以及我们提到的另两家知名网站捏一把汗。
2008年03月24日 14:19
最近忙,没有及时读朋友的blog。今天看到了Jessie的可不可以不联系,突然想起了自己的年少时光。
虽然没有Jessie MM这样丰富的人生,但少年时也免不了有些天荒地老海誓山盟。可是现在想想,其实也没有很多年,那些永远的誓言,转眼间就成为了天边的浮云。
回首过去,物似人非,自己身边的朋友,竟然变化了一茬又一茬。一路走来倒还不觉得,一回想还真让自己吓了一跳。曾经的那些死党,现在发现竟然连联系方式都不曾留下,唯一留下的,只有那些曾经的记忆片段了。
曾经以为永远很遥远,曾经以为朋友是一辈子的。现在看来并非如此,我们总也不知道明天会发生什么,总也不知道未来会怎样。锵锵的誓言今天看起来是如此的虚无缥缈。目前我们能做的,只能是把握好现在的每一天,把握好身边的每一个人,把握好我们一起做的每一件事。日后当真天各一方之时,至少可以拥有一个美好的回忆:
想当年啊,我曾经有这样一个朋友……
2008年03月18日 14:41
今天听了温总理的记者见面会,记住了这样一句话。本来是送给达赖的,我想也应该送给温总理自己以及各级政府官员们。
2008年03月11日 19:01
用户产生内容 VS 专家一文再次提到了个人用户和专家的问题。我记得我是第N次看到这样的问题了。
这个问题随着web 2.0的发展一再被提出,到底需要个人用户还是需要专家的问题也不断的被辩论。这个著名的“1%的维基用户承担了接近一半的编辑任务”的实例似乎让大家觉得,无论平台多么开放多么平等,这世界仍然是专家的。
事实是这样么?
其实这里有一个非常重要的问题:
谁是专家?
在传统的web 1.0网络中,有些人生来就比别人更平等——例如网站的管理员,网络编辑。而他们的产生并不是通过民主选举制度,而是通过少数人员的指派。他们有“专家”之名,但未必一定比所有的读者都更专业。在这个等级一下的读者,未必比专家们水平更差,但无法通过一个有效的途径变成“专家”。这中间有一个不可逾越的门槛的存在。
在平等的平台上,比如Wikipedia或其他UGC(User Generated Content 用户产生内容)网站,虽然的确只有少数的“专家用户”产生着高质量的内容甚至是唯一的内容,而绝大多数“普通用户”仅仅扮演着接受者或垃圾制造者的角色。但是,非常关键的一点是:这里的“专家用户们”,并不比“普通用户”拥有更多的特权!
所有专家用户们可以做的事情,普通用户都可以做,这里没有任何的门槛跟界限。(有些网站可能会根据贡献度给予活跃用户更多的权利,但这并不影响问题的本质)。所有的“专家”,都是因为其贡献而自然的成为专家,如果一个普通用户做了同样的贡献,获得了大家的认同,拥有了足够的影响力,他也可以变成专家。而专家们如果贡献少了,在用户中影响力下降,自然就沦为普通用户。
拿Wikipedia的例子来说,虽然1%的用户贡献了50%的内容,但这并没有为剩下的99%用户设置任何内容贡献方面的门槛,那99%的人之所以成为99%中的一员,是因为他们自己放弃了成为1%的权利。
其实我们也可以很清楚的看到Wikipedia这样的UGC系统的一些特点:
这个系统不适合懒人——在一个用户产生内容的系统中,如果每个人都等着“专家们”去产生内容,那么这个系统永远不会有内容产生。你永远都要记得,你就是这个系统的一份子。当没有内容产生的时候,你也是有责任的。所以,你必须时刻打起精神,为这个系统多做贡献,它才会不断充实完善。坐享其成的心态不适用于UGC系统。不合适就骂街,这种心态也不适用于UGC系统——诅咒它,不如自己动手改进它。
制度平等,而不是人人平等——必须承认,每个人的能力是有差别的,有些人就是比其他人懂得更多,做得更好;有些人就是喜欢比其他人更爱表现自己。UGC并不能创造一个环境,让每个人都变成专家。它只创造了一个环境,让每个人都有机会变成专家。这种机会,是通过公平的制度实现的。在制度公平的情况下,能不能成就自己,完全取决于自己的能力,抱怨客观条件是没有用的。
有平滑自然的退出机制——在UGC系统中,“专家”是自然产生的,它的基础是个人影响力。大家都选择相信你说的,大家都选择你,你自然就变成了“专家”。那么,很显然的,当一个人的个人影响力逐渐消失,他也会非常自然的从“专家”的位置上被淘汰下来,让位给更合适的人。有些网站会给一些高活跃度用户增加一些特权,但很多网站只考虑特权的增加但没考虑特权的删除,这也是不对的。如果一个用户很久没有贡献,这个系统中的大多数人都不认识他,对大多数用户而言他也没有什么个人影响力。而他却拥有一些特权,这就是不公平的。
多重来源,多种声音——一个UGC系统中因为所有用户都可以提交内容,往往一个问题会有很多中不同角度的来源和声音。看起来会让人无所适从,其实这也就是UGC系统的一个特点——把对问题的思考留给读者自己,系统只负责提供仅可能多的素材,但不负责产生结论。比较严肃的UGC系统比如Wikipedia,还会增加额外的条款来更严格的保证这一点——比如它著名的中立原则。
说了一大堆,简单的归纳就是:这个世界的确并非生而平等,我们仍然需要专家的带领。然而,我们希望这些专家是我们真正想要的,而不是由某些人指定的。但为了做到这一点,我们自己也得做些努力,幻想着天上掉下我们想要的专家,是不可能的。如果你不努力,就别抱怨。
UGC系统正是给了我们这样一个平台。我很喜欢这样的平台。
2008年03月11日 11:41
昨天有人加我工作用的MSN,开始还以为是公司的同事。结果加了之后几句话说得莫名其妙,后来才发现,原来是对方加错了人。
今天,那个“被加错的”人也找上我了,一看ID,果然是只差了一个字母。
随口聊了两句,才发现,不仅英文ID如此接近,就连中文名字,也只差了一个字而已。
我的姓氏本来就不是大姓,我的名字也不是那种很大众化的名字。能遇上一个同姓的已经难得,居然还遇上一个名字的拼音完全一致,中文字也几乎一样的人。
我不由得再次感慨,太神奇了太神奇了。
2008年03月08日 11:41
昨天有朋友问我2 7 8 9如何得到24。我突然想到似乎从来没有写过二十四点计算程序,一时兴起就小研究了一下。
其实掌握递归概念之后,这个算法定义并不复杂,而且可以引申至N个数计算得到某个指定结果的情况。简述如下:在给定的N个数中取出一个,将它跟剩下的N-1个数的计算结果做加减乘除的计算。注意因为减法和除法是不满足交换率的,所以还要考虑先后次序的问题。
按照这个算法写了一个简单的Python代码,考虑了一些基本的重复表达式的过滤。没有其他的优化手段。基本上是“可用”的。
其中用到了一些Python的特性,如表达式字符串求值、generator等。我也用C++实现了一个类似的,不过因为没有这些“高级”手段,代码复杂了很多,单从代码行而言,CPP程序是py的三倍。
下面是python的代码:
def genResult(source):
if len(source) 1:
yield source[0] * 1.0 #division need a float number to get the exact result
for index, num in enumerate(source):
remainList = source[0:index] + source[index+1:] #skip the number itself
for op in ['+', '-', '*', '/']:
for subExpression in genResult(remainList):
if len(remainList) 1:
yield '%s%s%s' % (str(num*1.0), op, subExpression) #avoid the uneccessary bracket
else:
yield '%s%s(%s)' % (str(num*1.0), op, subExpression)
if (op '-' or op '/'): #minus and division is order sensitive
if len(remainList) 1:
yield '%s%s%s' % (subExpression, op, str(num*1.0))
else:
yield '(%s)%s%s' % (subExpression, op, str(num*1.0))
def findSolution(source, result):
for expression in genResult(source):
try:
r = eval(expression) #if the expression cannot be calcutated, just ignore it.
if (abs(r-result) < 0.001):
yield expression, result
except:
pass
_solutionBuffer = {}
def isDuplication(expression, result):
global _solutionBuffer
if expression not in _solutionBuffer.keys():
_solutionBuffer[expression] = result
return False
else:
return True
if __name__ "__main__":
input_str = raw_input("Please input numbers: ")
source = [int(n) for n in input_str.split()]
input_str = raw_input("Please input the result: ")
result = int(input_str.split()[0])
index = 0
for expression, result in findSolution(source = source, result = result):
if not isDuplication(expression, result):
index += 1
print '[%03d]: %s = %d' % (index, expression, result)
这个代码已经考虑了一部分重复表达式的过滤。但还不是十分完整,例如,它不能判断 2.0 * (7.0 + 9.0) – 8.0 和 2.0 * (9.0 + 7.0) – 8.0 实际上是同一个表达式。要做到这一点还需要一个表达式规范化的算法。这个会大大增加代码的复杂度,以后再考虑吧。
Update:
上面的代码被我可耻的发现了一个严重的bug:我取元素都是一个一个取的,因此最终形成的表达式总是 a op (b op (c op d)))这样的形式,而不会出现 (a op b) op (c op d) 这样的形式。因此 5 5 5 5这个简单的算式居然也会被判定为无解。
下面是改正过的算法,基本原理是产生N个数序列的全排列(这样就不用再考虑数字顺序问题),每次取其中的一条,然后分别取1个,2个,...N-1个元素,与剩下的元素产生两个子表达式,再用操作符拼接起来,这样应该可以产生出全部的表达式了。
#coding:utf-8
def genFullPermutation(source):
"产生全排列序列"
if len(source) == 1:
yield source
else:
for index, elem in enumerate(source):
remain = source[0:index] + source[index+1:]
for permutation in genFullPermutation(remain):
yield [elem] + permutation
def genExpression(source):
"对于某一种排列,产生全部的表达式"
if len(source) == 1:
yield source[0] * 1.0
else:
for n in range(len(source)):
begin = source[:n]
end = source[n:]
for op in ['+', '-', '*', '/']:
for subexp1 in genExpression(begin):
for subexp2 in genExpression(end):
yield '(%s)%s(%s)' % (subexp1, op, subexp2)
if (op == '-' or op == '/'): #minus and division is order sensitive
yield '(%s)%s(%s)' % (subexp2, op, subexp1)
def findSolution(source, result):
for permutation in genFullPermutation(source):
for expression in genExpression(permutation):
try:
r = eval(expression) #if the expression cannot be calcutated, just ignore it.
if (abs(r-result) < 0.001):
yield expression, result
except:
pass
_solutionBuffer = {}
def isDuplication(expression, result):
"一个简单的去除重复的方法"
global _solutionBuffer
if expression not in _solutionBuffer.keys():
_solutionBuffer[expression] = result
return False
else:
return True
if __name__ == "__main__":
input_str = raw_input("Please input numbers: ")
source = [int(n) for n in input_str.split()]
input_str = raw_input("Please input the result: ")
result = int(input_str.split()[0])
index = 0
for expression, result in findSolution(source = source, result = result):
if not isDuplication(expression, result):
index += 1
print '[%03d]: %s = %d' % (index, expression, result)
当然,这段代码未经优化,效率不高,而且表达式也没有做规范化处理,会产生很多重复的式子。
2008年03月05日 23:23
晚上猎手不小心在自己完全不了解的情况下使用了ReiserFS,引起了我们对于文件系统类型的兴趣。猛禽说也想知道自己的系统使用了什么文件系统。可是当我想回答的时候却发现,原来通常的几个命令都不能看到具体的文件类型(比如fdisk -l /dev/sda之类)。于是这个简单任务突然变成了一个高难度任务。
不过还好,Google了一圈,发现其实还是有方法的。
可以用file命令获取分区设备的文件系统的类型
$ sudo file -s /dev/sda1
/dev/sda1: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs)
也可以用stat命令获取逻辑目录对应的文件系统类型
$ stat -f /boot
File: "/boot"
ID: 77633b51f3827c6b Namelen: 255 Type: ext2/ext3
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 245085 Free: 236288 Available: 223838
Inodes: Total: 124672 Free: 124640
2008年03月02日 22:59
项目真正开始才知道什么叫做累。比上班还要更累。
从零开始的团队运作果然感觉是大不相同啊。
不过自己做事情有一个好处就是有了更多的决定权,看着项目在自己手里一步步的开始发展。虽然累,但是很开心。