65.9K
CodeProject 正在变化。 阅读更多。
Home

字母算术和模糊二分查找词-数字

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (3投票s)

2017年3月2日

MIT

7分钟阅读

viewsIcon

13037

字母算术 - 将任何字母的任何单词转换为 N 进制数以进行二分查找和单词操作

引言

字母算术是指将任何字母表转换为数字系统,其中数字等于字符数加一,并应用以下操作:加法、减法、附加、删除、插入、替换、分离,以及因此可能进行的二分查找。

例如,以拉丁字母 a - z 为例,共 26 个字符,并以零 \0 - 空字符为零,替换 '\0' = 0, 'a' = 1 ... 'z' = 26。这将形成一个 27 进制数字系统。现在,任何字母或单词在该系统中都是所有可能字母组合中唯一的。这使得我们可以进行比较(大于、小于或等于)、排序和使用二分查找。以及生成单词的增量和减量。

如果你没有零。那么就不会出现诸如:abc\0 == abc 的情况。但存在其他问题,基于公式分离的操作在分离位置的最后一个字符处将不适用,结果会多出一个单位,这是数字系统的问题。你可以引入一个因子,但需要计算,这很长,是浮点数,并且仍然不稳定。总的来说,我未能获得正常结果,而是将减法残差细分。这本质上是对单词的字符导向分析,保存结果,对其进行操作并构建不那么令人愉悦的东西。

如果有零,一切就和数字一样简单。基于除法运算的操作根据任何数字系统的公式进行。就像其他任何一样。但有一些特点:转换后的单词会保留字符串索引表示。因此,所有右侧的 `null` 字符都会被移除,就像数字的情况一样,只是方向相反。

1 == 0001,相应地,对于字母:a == a\0\0。此外,如果这些字符存在于单词中,在操作过程中会导致它们的丢失。可能的操作:加法和减法是微不足道的。

a + a = b; z + a = \0a; a - a = \0; b - a = a;

当然,相对于单词而言,数学上的乘法或除法没有意义,你需要将其分为左半部分和右半部分,或者附加到这部分或那部分。

我们得到以下算法公式:

在操作数上是镜像的,以保留左侧的视觉索引。

索引的除法(取左侧)

$L = W \% N^{i+1}$

其中 \(L\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(i\) = 索引

带索引余数的除法(取右侧)

$R = \frac{W}{N^{i}}$

其中 \(R\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(i\) = 索引

部分单词的乘法(右插)

$NW = W + P * N^{W1}$

其中 \(NW\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(P\) = 附加部分

单词的乘法(左插)

$NW = W * N^{P1+P}$

其中 \(NW\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(P\) = 附加部分, \(Pl\) = 附加部分的长度, \(Wl\) = 单词长度

进一步的操作组件

替换索引的一部分

$Wt = \left ( \frac{W}{N^{i}} \right ) \% N^{P1}$
$O = W + \left ( P - Wt \right ) * N^{i}$

其中 \(NW\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(P\) = 替换部分, \(Pl\) = 替换部分的长度, \(i\) = 索引

插入索引的一部分

$L = W \% N^{i}$
$NW = (R * N ^ Pl + P) * N^Ll+L$

其中 \(NW\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(P\) = 粘贴部分, \(Pl\) = 插入部分的长度, \(Ll\) = \(L\) 部分的长度, \(i\) = 索引

移除索引的数字

$L = W \% N^{i}$
$NW = \left ( R * N^{P1 + P} \right ) * N^{L1+L}$

其中 \(NW\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(Ll\) = 部分 \(L\) 的长度, \(i\) = 符号的索引号 = a

取索引上的部分

$NW = W \% \frac{N^{i+c}}{N^{i}}$

其中 \(NW\) = 结果, \(W\) = 单词数, \(N\) = 数字系统, \(c\) = 数字, \(i\) = 索引

整数除法,如果使用分数类型,则需要截断小数部分。如果单词或一部分包含零符号,结果可能不正确。

当然,代码需要检查部分长度、索引值以及其他检查。

转换

字符串到数字的转换(最重要的数字在右侧)

      i=0, k=1
i < Sl  FOR   O += tonum(S[i]) * k
     i++, k*=N

使用循环,其中 O = 输出,N = 数字系统,S = 行,l = 长度,i = 索引,tonum 返回与字母对应的数字。

以下转换(最重要的数字在右侧)

        i=0
i < len FOR char [i] = tochr (W % N); W / = N;
        i++

要反向转换,创建一个 char [len] 数组,其中 len = 单词-数字的长度,W = 单词数,N = 数字系统,tochr = 返回与数字对应的字符。

最重要的数字也可以在左侧,只是另一种方式。

带有方法集和小型测试的类在 GitHub 页面上。

GitHub 上的算术字母表(Alphametic)

排序数组中的模糊二分查找词-数

排序算法可以是任何按照数字顺序自然排序的算法。我们将文本转换为数字并将其移动到所需的索引。

例如,使用冒泡排序算法。你需要按确定字母表的 `string` 数组进行排序,可以是字母或符号,这不重要。然后更改代码类中的字母部分。非常重要的是,字母表必须包含所有排序 `string` 中包含的符号和字母。然后对其进行排序。

    BubbleSort(string[] array)
    {
        string temp = string.Empty;
        for(int i = 0; i < array.Length - 1; i++)
        {
            for(int k = i + 1; k < array.Length; k++)
            {
                if(Word.ToWord(array[i] > Word.ToWord(array[k])
                {
                    temp = array[i];
                    array[i] = array[k];
                    array[k] = temp;
                }
            }
        }
    }

现在可以通过 `string` 进行二分查找。就这么简单。

    int index = Word.FuzBinSearch(a_searching_string, array);

当然,排序和二分查找算法可以是你需要的其他算法。

数组部分示例

scorn
adorn
thorn
mourn
begun
drawn
shown
blown
brown
crown
drown
frown
grown
marco
bingo
cargo
radio
hello
piano
photo
cheap
scrap
strap
sheep
sleep
creep
steep

由于最高位数字在右侧,排序结束后可能反之,但那时我们必须记住搜索词应该采用相同的表示法。

单词搜索返回索引,或者最接近所需数字方式的某个邻居的索引。是左还是右,结果不确定。例如:查找“`pea`”返回其索引,将单词改为“`rea`”返回“`sea`”或“`pea`”,因为词典的这个部分是

oz
pea
sea
tea
aha

并且不包含单词“`rea`”,但从数值上看它位于`pea` - `sea`之间。你可以检查“`sea`” == dic [index]以返回键的值,否则可以继续搜索。由于它们是按数字排序的,因此它会根据长度和其中的字符按字母顺序排序。最新字母的所有可能组合都位于\0\0a之上,并向下跟随zza。

但词语通常不会严格地排列,也就是说,在这种情况下,词语在其范围内

只有八个

pea
sea
tea
aha
via
ana
era
asa

你可以编写一个循环,它会向上遍历到某个特定单词并返回可用索引,然后向下遍历。当然,所有单词的数量都会不同,具体取决于字母的受欢迎程度。如果你在前面、后面添加或删除字母,范围将会有很大差异。在这种情况下,可能最好执行重复搜索。以及搜索固定数量的可能错误。

总的来说,你需要进行实验。

在包含 8,000 个单词的词典中查找单词的平均步数是 12。

缺点

最大的问题是由于数字过大导致单词长度受限。在 C# 中,十进制(128 位)的大小,可以包含不超过 19 个字符的单词,这是超出此字母表大小的边界,进行数字转换时会溢出。

如果你输入完整的字母表和其他字符,字符数量会更少。文件中最长的单词有 16 个字符,当然它原则上不是最长的,但还有一些组成部分,有些则没有。对于字典,你可以将最高的数字作为单词的标志,该单词以大写字母开头,这将略微扩大范围。

文件包含 8000 个英文小写单词并已排序。

© . All rights reserved.