想象一下单词的字母。
示例:
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
等等
答案 0 :(得分:12)
现在为神奇的公式:
使用示例编写代码并演示速度,即使在最糟糕的情况下:
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的三角形:
从右上角到左下角,首先是1的序列。然后是一系列计数数字。下一个序列是计数数字的总和。这些被称为三角数。下一个序列是三角形数字的总和,称为四面体数字,这种模式依次开启。
现在为二项式定理:
通过组合二项式定理和帕斯卡三角形,可以看出第n个三角形数字是:
和第n个四面体数字是:
前n个四面体数的总和是:
然后......
现在解释一下。对于这个解释,我将只使用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
为了解决这个问题,我们将其分为三部分:
接下来,我们将重复长度为3的序列:
123 124 125 126
134 135 136
145 146
156
234 235 236
245 246
256
345 346
356
456
我们再次将此问题分解为步骤:
此
234 235 236
245 246
256
变为
12 13 14
23 24
34
将这些长度为3的总公式合并为:
对于更高长度的序列,我们可以遵循这种减少模式
现在我们将通过我们的公式来寻找模式:
长度1:y1
长度2:
长度3:
注意:我还使用长度4来确保模式保持
通过一些数学,术语分组以及从6到26的变化,我们的公式变为:
为了进一步简化这一点,必须进行更多的数学计算 这个身份适用于所有a和b。为了快速有趣的练习,证明它(并不是很难):
此身份允许进一步分组和否定术语以达到我们过于简单的公式:
答案 1 :(得分:4)
这是两个问题的组合:parsing a number in a base that isn't 10和determining 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();
}
}