给出一个单词,打印其索引,可以相应增加单词

时间:2013-07-05 18:47:43

标签: algorithm

想象一下单词的字母。

示例:

 a ==> 1 
 b ==> 2 
 c ==> 3 

 z ==> 26 
 ab ==> 27 
 ac ==> 28 

 az ==> 51 
 bc ==> 52 
 and so on. 

这样字符序列只需要按升序排列(ab有效但ba不是)。给定任何单词如果有效则打印其索引,否则打印0。

 Input  Output 

 ab      27 

 ba       0 

 aez     441 

在这个问题中,我可以轻松地做数学,但我没有得到任何算法。

我在数学方面所做的是

一封信26

两个字母325

等等

5 个答案:

答案 0 :(得分:12)

  1. 首先制作所有字母数字:
    • 'aez'将成为1,5,26
  2. 将这些数字变量称为...... X3,X2,X1
    • 26将是X1,5将是X2,1将是X3(注意,从右到左)
  3. 现在为神奇的公式:

    enter image description here

    使用示例编写代码并演示速度,即使在最糟糕的情况下:

    def comb(n,k): #returns combinations
        p = 1 #product
        for i in range(k):
            p *= (n-i)/(i+1)
        return p
    
    def solve(string):
        x = []
        for letter in string:
            x.append(ord(letter)-96)  #convert string to list of integers
        x = list(reversed(x))  #reverse the order of string
        #Next, the magic formula
        return x[0]+sum(comb(26,i)-comb(26-x[i-1]+1,i)*(1-i/(26-x[i-1]+1)) for i in range(2,len(x)+1))
    
    solve('bhp')
    764.0
    >>> solve('afkp')
    3996.0
    >>> solve('abcdefghijklmnopqrstuvwxyz')
    67108863.0
    >>> solve('hpz')
    2090.0
    >>> solve('aez')
    441.0
    >>> if 1:
            s = ''
            for a in range(97,97+26):
                    s += chr(a)
            t = time.time()
            for v in range(1000):
                    temp = solve(s)
            print (time.time()-t)
    
    
    0.1650087833404541
    

    为了理解我对这个公式的解释,我需要在pascal的三角形和二项式定理中重复数学:

    这是pascal的三角形:

    enter image description here

    从右上角到左下角,首先是1的序列。然后是一系列计数数字。下一个序列是计数数字的总和。这些被称为三角数。下一个序列是三角形数字的总和,称为四面体数字,这种模式依次开启。

    现在为二项式定理:

    enter image description here

    通过组合二项式定理和帕斯卡三角形,可以看出第n个三角形数字是:

    enter image description here

    和第n个四面体数字是:

    enter image description here

    前n个四面体数的总和是:

    enter image description here

    然后......

    现在解释一下。对于这个解释,我将只使用6个字母a-f,并用数字1-6替换它们。程序与更多字母相同

    如果长度为1,则可能的序列为:

    1
    2
    3
    4
    5
    6
    

    在这里,答案只是值

    现在长度为2:

    12  13  14  15  16
    23  24  25  26
    34  35  36
    45  46
    56
    

    为了解决这个问题,我们将其分为三部分:

    1. 查找上面行中的元素总数
      • 在这种情况下,第一行中有5个元素,第二行中有4个元素,第三行中有3个,依此类推。我们要做的是找到一种方法来对序列的前n个元素求和(5,4,3,2,1)。为此,我们减去三角形数字。 (1 + 2 + 3 + 4 + 5) - (1 + 2 + 3)=(4 + 5)。类似地(1 + 2 + 3 + 4 + 5) - (1 + 2)= 3 + 4 + 5。因此该值等于:
        • enter image description here
    2. 现在,我们已经考虑了目标以上的值,并且仅关注它所在的列。为了找到这个,我们添加x1-x2
    3. 最后,我们需要添加长度为1的序列。这等于6.因此,我们的公式是:
      • enter image description here
    4. 接下来,我们将重复长度为3的序列:

      123  124  125  126
      134  135  136
      145  146
      156
      
      234  235  236
      245  246
      256
      
      345  346
      356
      
      456
      

      我们再次将此问题分解为步骤:

      1. 查找每个数组上方有多少个元素。数组值是向后的三角形数字(10,6,3,1)。这一次,我们减去四面体数字,而不是减去三角形数字:
        • enter image description here
      2. 注意每个单独的数组如何具有长度为2的序列形状。通过从x1和x2中减去x3,我们将序列减少到2度。例如,我们将从第二个数组中减去2
      3. 234  235  236
        245  246
        256
        

        变为

        12  13  14
        23  24
        34  
        
        1. 我们现在可以使用长度为2的公式,使用6-x3而不是6,因为我们的序列现在具有不同的最大值
          • enter image description here
        2. 最后,我们添加长度1和长度2序列的总数。事实证明,存在特定长度的序列数量的模式。答案是组合。有enter image description here个长度为1的序列,长度为2的enter image description here,依此类推。
        3. 将这些长度为3的总公式合并为:

          enter image description here

          对于更高长度的序列,我们可以遵循这种减少模式

          现在我们将通过我们的公式来寻找模式:

          长度1:y1

          长度2:

          长度3:

          enter image description here

          注意:我还使用长度4来确保模式保持

          通过一些数学,术语分组以及从6到26的变化,我们的公式变为:

          为了进一步简化这一点,必须进行更多的数学计算 这个身份适用于所有a和b。为了快速有趣的练习,证明它(并不是很难):

          enter image description here

          此身份允许进一步分组和否定术语以达到我们过于简单的公式:

答案 1 :(得分:4)

这是两个问题的组合:parsing a number in a base that isn't 10determining if input is sorted

请注意,由于这可能是家庭作业,您可能不能仅仅使用现有方法来完成这项工作。

答案 2 :(得分:1)

对于长度超过一个字符的虚构字母,我们可以使用递归:

XnXn-1..X1 = 
  max(n-1) 
      + (max(n-1) - last (n-1)-character letter before 
                    the first (n-1)-character letter after a)
  ... + (max(n-1) - last (n-1)-character letter before the
                    first (n-1)-character letter after the-letter-before-Xn)
  + 1 + ((Xn-1..X1) - first (n-1)-character letter after Xn)

where max(1) = z, max(2) = yz...

Haskell代码:

import Data.List (sort)
import qualified Data.MemoCombinators as M

firstAfter letter numChars = take numChars $ tail [letter..]

lastBefore letter numChars = [toEnum (fromEnum letter - 1) :: Char] 
                          ++ reverse (take (numChars - 1) ['z','y'..])

max' numChars = reverse (take numChars ['z','y'..])

loop letter numChars = 
  foldr (\a b -> b 
                 + index (max' numChars) 
                 - index (lastBefore (head $ firstAfter a numChars) numChars)
        ) 0 ['a'..letter]

index = M.list M.char index' where
  index' letter
    | null (drop 1 letter)  = fromEnum (head letter) - 96
    | letter /= sort letter = 0
    | otherwise = index (max' (len - 1))
                + loop (head $ lastBefore xn 1) (len - 1)
                + 1
                + index (tail letter) - index (firstAfter xn (len - 1))
   where len = length letter
         xn = head letter

<强>输出:

*Main> index "abcde"
17902

*Main> index "abcdefghijklmnopqrstuvwxyz"
67108863
(0.39 secs, 77666880 bytes)

答案 3 :(得分:0)

Base 26编号系统。我建议你看一下八进制,十进制和十六进制编号系统,一旦你理解了如何将它们中的任何一个转换为十进制,你也会知道这个。

答案 4 :(得分:0)

这确实应该是一个评论,但我无法在评论中加入代码。

根据原始海报提供的标准,我写了一个蛮力计划来计算一个,两个,三个,四个和五个字母单词的数量。

  

想象一下单词的字母表,这样单词中的字符序列只能按升序排列。

以下是我的计划的结果。

One letter words   - 26
Two letter words   - 325
Three letter words - 2600
Four letter words  - 14950
Five letter words  - 65780

Total words        - 83681

我的解决方案&#34;将生成一个从a到abcdefghijklmnopqrstuvwxyz的所有单词的字典。

这是我使用的代码。也许有人可以看看嵌套循环并提出一个公式。我不能。

public class WordSequence implements Runnable {

    private int wordCount = 0;

    @Override
    public void run() {
        int count = createOneLetterWords();
        System.out.println("One letter words   - " + count);
        count = createTwoLetterWords();
        System.out.println("Two letter words   - " + count);
        count = createThreeLetterWords();
        System.out.println("Three letter words - " + count);
        count = createFourLetterWords();
        System.out.println("Four letter words  - " + count);
        count = createFiveLetterWords();
        System.out.println("Five letter words  - " + count);

        System.out.println("\nTotal words        - " + wordCount);
    }

    private int createOneLetterWords() {
        int count = 0;

        for (int i = 0; i < 26; i++) {
            createWord(i);
            wordCount++;
            count++;
        }
        return count;
    }

    private int createTwoLetterWords() {
        int count = 0;

        for (int i = 0; i < 25; i++) {
            for (int j = i + 1; j < 26; j++) {
                createWord(i, j);
                wordCount++;
                count++;
            }
        }
        return count;
    }

    private int createThreeLetterWords() {
        int count = 0;

        for (int i = 0; i < 24; i++) {
            for (int j = i + 1; j < 25; j++) {
                for (int k = j + 1; k < 26; k++) {
                    createWord(i, j, k);
                    wordCount++;
                    count++;
                }
            }
        }
        return count;
    }

    private int createFourLetterWords() {
        int count = 0;

        for (int i = 0; i < 23; i++) {
            for (int j = i + 1; j < 24; j++) {
                for (int k = j + 1; k < 25; k++) {
                    for (int m = k + 1; m < 26; m++) {
                        createWord(i, j, k, m);
                        wordCount++;
                        count++;
                    }
                }
            }
        }
        return count;
    }

    private int createFiveLetterWords() {
        int count = 0;

        for (int i = 0; i < 22; i++) {
            for (int j = i + 1; j < 23; j++) {
                for (int k = j + 1; k < 24; k++) {
                    for (int m = k + 1; m < 25; m++) {
                        for (int n = m + 1; n < 26; n++) {
                            createWord(i, j, k, m, n);
                            wordCount++;
                            count++;
                        }
                    }
                }
            }
        }
        return count;
    }

    private String createWord(int... letter) {
        StringBuilder builder = new StringBuilder();

        for (int i = 0; i < letter.length; i++) {
            builder.append((char) (letter[i] + 'a'));
        }

        return builder.toString();
    }

    public static void main(String[] args) {
        new WordSequence().run();
    }

}