第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)
    运行结果如下:
    AutoIt教程:9. 问题、方案与实现 - 图1
    看懂了,原来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
    AutoIt教程:9. 问题、方案与实现 - 图2
    仔细看看,就会发现“计算总和”的过程是可以被独立出来的,那还不如把它写成一个函数,将来可以随意调用呢:
    $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()函数就可以算出数值……
    然后,程序就变成了这个样子:

    1. InetGet("http://www.kilgarriff.co.uk/bnclists/lemma.al", "lemma.al",0)
    2. $file=FileOpen("lemma.al",0)
    3. While1
    4. $line=FileReadLine($file)
    5. If@error=-1Then ExitLoop
    6. $lineElements=StringSplit($line," ")
    7. If AddUpCharactersInWordAsNumber($lineElements[3])
    8. ==100Then
    9. ConsoleWrite($lineElements[3]&@CRLF) EndIf
    10. WEnd
    11. FileClose($file)
    12. MsgBox(0,"","Finished!")
    13. Func AddUpCharactersInWordAsNumber($word)
    14. $wordLowerCase=StringLower($word)
    15. $Characters=StringSplit($wordLowerCase,"")
    16. $count=0
    17. For$i=1To$Characters[0]
    18. $count=$count+Asc($Characters[$i])-96 Next
    19. Return$count
    20. EndFunc

    如果你想把结果都写到一个文本文件之中,可以把第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粘贴

    周而复始,直至所有词汇全部处理完毕……