第7节里提到过的问题,实际上在《把时间当作朋友》一书中出现过,作为反驳“成功学谬误”的例子:
除了“以偏概全”、“单向成立”之外,“成功学”书籍里甚至不乏赤裸裸的、厚颜无耻逻辑混乱。最令我印象深刻的赤裸裸地逻辑混乱的“成功学”例子是关于“态度改变一切”的一个例子。我知道,也相信“有些时候,仅仅态度上的改变就真的可以带来不同的结果”。然而,我认为用以下的逻辑让我接受,或者让任何人接受,都不仅是不可能的,甚至是不道德的。
如果将字母 A 到 Z 分别编上 1 到 26 的分数,(A=1,B=2…,Z=26) ,那么:
- 你的知识(KNOWLEDGE)得到 96 分 (11+14+15+23+12+5+4+7+5=96)
- 你的努力(HARDWORK)也只得到 98 分 (8+1+18+4+23+15+18+11=98)
- 你的态度(ATTITUDE)才是左右你生命的全部,因为 1+20+20+9+20+21+4+5=100
拜托,有点基础逻辑好不好呢?事实上,用这种方法计算,结果等于100的单词多的去了:
alienation (疏远)
apoplectic (中风患者)
boycott (联合抵制)
cacophony (杂音、刺耳的音调)
chimpanzee (黑猩猩)
connivance (纵容)
coyness (羞怯)
flurry (慌张)
frisson (颤抖)
impotence (阳痿)
inflation (通货膨胀)
pussy (小猫<俚>女阴/阴户)
socialism (社会主义)
status (身份、地位)
stress (压力)
surcharge (超载, 追加罚款, 额外费)
syndicate (财团)
tuppence (微不足道的东西)
turkey (火鸡,无用的东西)
Wednesday (星期三)
wholesale (批发)
以上罗列的只是我在BNC英文词汇表中找到的一千多个中的一小部分名词而已。对了,形容词useless如果按照这种算法,结果也等于100。补记:刚刚写完,顺手在GOOGLE上搜索了一下“KNOWLEDGE 11+14+15+23+12+5+4+7+5=96″。得到的结果特别值得回味:前150项几乎都来自中文网站。搜索结果的第16页才开始陆续有一些英文网站提到这个莫名其妙的算法,在GOOGLE搜索结果的第151项看到这么一篇:指出 bullshit = 103,于是接着说,“So, it stands to reason that hard work and knowledge will get you close, attitude will get you there, but bullshit will put you over the top.” 还有更逗的,作者又接着指出另外一个词:asskissing=127!
当时我就想,要是有很多莫名其妙的词按这种算法加起来也等于100呢?我猜肯定有的!只不过,用手工计算是(几乎)不可能的事情。还好,我有工具[1]和技能,所以,就可以去验证,而后“精彩而又直接地”驳斥这种荒谬的说法。
有些时候我们非常依赖工具和技能。在心存狐疑之时,拥有工具掌握技能的人,可以去验证;而没有工具没有技能的人,只能“心有余力不足”。事实上,大多数“力不足”的人“心并无余”,他们甚至不会“心存狐疑”,而是直接“被震惊”、“被惊喜”,“被打动”……直接被这种说法带到坑里去了……
问题是:“有哪些词按这种算法也等于100?”──而解决方案倒也简单:?找一个词表(如有必要,就把它转换为文本文件,便于程序阅读)
- 逐一计算
- 把那些按这种算法计算等于100的词挑出来
刚开始的时候,其实没必要一定要先去找个词表,我只新建了名称为一个“wordlist.txt”的文件,其中只有以下几行内容:
Hardwork
Attitude
Knowledge
Success
Anything
而后我们就可以写这样的代码处理这个文本文件中的每一行:
$file=FileOpen(“wordlist.txt”,0)
While1
$line=FileReadLine($file)
If@error=-1Then ExitLoop
; test if sum of character values in this word equals to 100, if so, print it to the output…
WEnd
FileClose($file)
注意,在AutoIt代码中,分号“;”后面的内容是“注释”,是给代码阅读者看的,AutoIt在执行代码的时候,忽略一切“;”和它后面的内容。注释的写法有若干种,请参阅帮助文档。
现在的问题是,如何才能计算出一个单词按这种算法等于多少呢?我到AutoIt 的帮助文件里翻了翻与字符串(String)相关的函数,看看有没有能够用得上的……当然有,我找到了个StringSplit()。它会把一个字符串按照指定的“分隔符”拆分成若干段,而后把这些拆分后的片段按顺序保存在一个数组之中返回……如果分隔符是空字符(即,“”),那么它就把一个字符串拆分成一个字母一个片段……就是它了!
大致看了一下帮助文档,而后写了个代码片段测试这个函数:
#Include
_ArrayDisplay(StringSplit(“Success”,””))
结果竟然出错了……仔细看了看出错提示,才发现_ArrayDisplay()这个函数第一个参数标明了是ByRef的,即,只接受变量作为参数,不接受表达式或函数调用。所以,改了改测试代码:
#Include
$a=StringSplit(“Success”,””)
_ArrayDisplay($a)
运行结果如下:
看懂了,原来StringSplit()返回的是一个这样的数组:$a[0]之中保存的是“分割后片段的个数”(即,Success这个字符串总计7个字母),而后的元素则为每一个字母……
现在的问题是,如何让a=1,b=2… c=26呢?
在AutoIt帮助文件的Variables and Conversion章节中,找到一个函数Asc()。这个函数返回一个字符对应的ASCII代码。例如:
Asc(“0″) == 48, Asc(“9″)== 57, Asc(“A”) == 65, Asc(“Z”) == 90, Asc(“a”) == 97, Asc(“z”) == 122
所以,Asc(“a”) == 97 、Asc(“b”) == 98 … 于是,只要用这个函数的返回值再减去96就可以得到1、2、…26这些数值了。不过,还有个问题,大小写字母的值不一样,Asc(“A”) == 65,而Asc(“a”) == 97……再去看看跟String 相关的函数,找到一个StringLower()──我们可以先用它把一个词中的字符全部转换为小写,而后再进行计算……
现在我们可以写出(或起码能够完全理解)以下的代码了:
$file=FileOpen(“wordlist.txt”,0)
While1
$line=FileReadLine($file)
If@error=-1Then ExitLoop
; test if sum of character values in this word equals to 100, if so, print it to the output…
$wordLowerCase=StringLower($line)
$Characters=StringSplit($wordLowerCase,””)
$sum=0
For$i=1To$characters[0]
$sum=$sum+Asc($characters[$i])-96 Next
MsgBox(0,$line,$sum)
WEnd
仔细看看,就会发现“计算总和”的过程是可以被独立出来的,那还不如把它写成一个函数,将来可以随意调用呢:
$file=FileOpen(“wordlist.txt”,0)
While1
$line=FileReadLine($file)
If@error=-1Then ExitLoop
; test if sum of character values in this word equals to 100, if so, print it to the output…
$sum= AddUpCharactersInWordAsNumber($line)
MsgBox(0,$line,$sum)
WEnd
Func AddUpCharactersInWordAsNumber($word)
$wordLowerCase=StringLower($word)
$Characters=StringSplit($wordLowerCase,””)
$count=0
For$i=1To$Characters[0]
$count=$count+Asc($Characters[$i])-96 Next
Return$count
EndFunc
如此这般之后,我们可以去找一个很全的英文词汇表去测试了。我到网上Google 了一下“BNC Frequency Word List”,很快在这个网站上找到一个词汇表,“lemma.al”。网站上有这个词表的格式说明:
The format for the list is:
sort-order, frequency, word, word-class
and a sample from the top of the alphabetically-ordered list is:
5 2186369 a det
2107 4249 abandon v
5204 1110 abbey n
966 10468 ability n
321 30454 able a
这个比较好办,就用我们刚刚用过的StringSplit()函数,用一个空格(” “)作为分隔符,就能把每一行中的“word”提取出来,然后在调用我们刚写过的AddUpCharactersInWordAsNumber()函数就可以算出数值……
然后,程序就变成了这个样子:
InetGet("http://www.kilgarriff.co.uk/bnclists/lemma.al", "lemma.al",0)$file=FileOpen("lemma.al",0)While1$line=FileReadLine($file)If@error=-1Then ExitLoop$lineElements=StringSplit($line," ")If AddUpCharactersInWordAsNumber($lineElements[3])==100ThenConsoleWrite($lineElements[3]&@CRLF) EndIfWEndFileClose($file)MsgBox(0,"","Finished!")Func AddUpCharactersInWordAsNumber($word)$wordLowerCase=StringLower($word)$Characters=StringSplit($wordLowerCase,"")$count=0For$i=1To$Characters[0]$count=$count+Asc($Characters[$i])-96 NextReturn$countEndFunc
如果你想把结果都写到一个文本文件之中,可以把第9行的
ConsoleWrite($lineElements[3]&@CRLF)
改成
FileWriteLine(“result.txt”,$lineElements[3])
而FileWriteLine()这个函数的用法,当然要参见帮助文档。
作业:
- 把程序里的StringLower()函数换成StringUpper(),并修改其它相应的部分,使其得出正常结果。
- 这里有个更长的词表:
http://www.doczj.com/doc/1b5d369e51e79b8968022637.html /BNClists/all.al.gz,下载后解压
缩,看看这个词表中有哪些词按这种算法等于100?
?这里还有一个词表:
http://www.doczj.com/doc/1b5d369e51e79b8968022637.html /words/wlist.zip,下载后解压缩,
看看这个词表中有哪些词按这种算法等于100?
?回顾一下之前的所有文章,确保每一行代码都读得懂……
Footnotes:
1.当时我用的是Python,现在是在讲解AutoIt,所以当然得用AutoIt重写一遍。AutoIt教程:10. 模拟键盘鼠标操作
by 李笑来 on 2010/05/07
in Auto-It
AutoIt的独特之处之一在于它可以非常方便地模拟Windows上的键盘鼠标操作,进而“自动”、“批量”地完成一些复杂而又重复的操作。
想象一下:
你有一个词表,你想把它的所有单词在Collins COUBILD中的释义文本拷贝出来。那么,你原本只能这样:
打开词表文本文件;
新建一个文本文档(如果想要保留格式的话,就要新建一个rtf文件──用“写字板”程序,而非“记事本”)
打开Collins词典(Collins COBUILD Dictionary On CDROM)
从词表文件中Control+C拷贝出一个词
切换到Collins词典,将刚刚拷贝的词粘贴到输入框中,而后按回车键
再从菜单中选择Edit,再选择Copy Entry
切换到写字板程序,按Control+V粘贴
…
周而复始,直至所有词汇全部处理完毕……
