在这篇文章中,我们将研究一个bash脚本,该脚本获取一串字母,以各种可能的方式重新排列它们,并检查每个排列以识别哪些是英语单词。在这个过程中,我们将仔细研究这个脚本,并计算它的工作难度。
注意,在使用的算法中,每个字母的排列都必须使用所有提供的字符串中的字母。不考虑由子字符串组成的单词。
首先,脚本希望将被打乱的字符串作为参数提供,如果没有提供参数,则会提示它。然后,它检查每一个字母的排列,以找到那些存在于系统中单词文件,在这个案例中,那就是/usr/share/dict/words.以下是脚本的第一行:
#!/bin/bash if [$# == 0];然后echo -n "乱码字符串> " read string else string=$1 fi
脚本的下一部分定义了一个函数,该函数将重新排列字母并在单词文件。如果数组不包含匹配项,则匹配项将被添加到数组中。
Function mix {if ["${#1}" == 1];grep ^$word$ /usr/share/dict/words &> /dev/null if [$?= = 0);如果[!]"$ {word [@]} " =~ "$word"]];然后# add word if new words[$n]=$word ((++n)) fi fi else for I in $(seq 0 $(${#1}-1));做前= " $ {2}$ {1:$ i: 1}”pc1 = " ${1:0: $我}" pc2 = " $ {1: $ ((i + 1))}”电脑= " $ {pc1} $ {pc2} "混合"美元pc”“以前美元”做fi}
在脚本的最后几行中混合函数第一次被调用。在运行所需的次数之后,脚本显示保存在数组中的单词数,然后列出单词。
$string echo ${#words[@]} "word(s) found" for n in ${words[@]};echo $ n;完成
如果我们为字母“olwf”运行脚本,我们将得到一个包含三个单词的列表。
$ unscramble olwf 3字发现狼禽流
响应将在一秒钟左右传递。
然而,这个脚本最糟糕的地方是,如果您给它一个相当长的字符串来整理成单词,那么它将需要长是时候回到你身边了。你不妨去喝杯咖啡休息一下,或者提前休个假。使用12个字符的字符串听起来可能不是什么大事,但这意味着您将使用12个字符!(12的阶乘)不同的字母排列。如果你很久没学过阶乘,让我提醒你12!是12 x 11 x 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2或479,001,600不同的字母排列(计算任何重复的字母在单词中超过一次)!对于8个字符的字符串,脚本需要几分钟,但是对于12个字符的字符串则需要更多的时间。
要计算阶乘,你可以使用如下脚本:
#!/bin/bash if [$# == 0];然后echo -n "enter number> " read num else num=$1 fi fac=1 while [$num -gt 1] do fac=$((fac * num)) num=$((num - 1)) done echo $fac
当给出数字8时,脚本会告诉我们8个字符的字符串将有40320种不同的排列方式。如果再增加4个字符,我们将看到近5亿人。
$ factorial 8 40320 $ factorial 12 47001600
对象中生成和检查所有字符串所需的时间受到了很大的影响单词文件。一个8个字符的字符串应该只需要运行几分钟。
$ time unscramble bthpaale 1 word(s) found alphabet real 1m49.693 user 1m20.559s sys 0m26.921s
一个9个字符的字符串需要两倍的时间来处理吗?不,应该要九倍的时间。一个长度的字符串?将近12000(11800)倍。下面是一个使用9个字符的字符串运行的示例:
$ time unscramble fialactor 1 word(s) found factorial real 16m27.318s user 12m1.492s sys 4m5.169s
一个12个字符的字符串可能需要几周的时间,除非,也许,您只是碰巧使用的是一台超级计算机。
总结
使用所描述的方法解读单词是彻底的,但是对于长单词,可能会非常慢。我怀疑网站喜欢wordunscrambler正在使用相当不同的方法-可能利用一个预先生成的无序和未无序单词列表。
虽然我编写和使用的大多数bash脚本都很简单,而且相当有效,但对解置字符串问题的研究表明,有时最符合逻辑的解决问题的方法两者都不是。