所以我以为我会自学C ++,但我似乎对语言没有任何问题,但坦率地说我很愚蠢。
所以我的想法是这样的。如果我说a = 1,b = 2,z = 26,aa = 27等,我可以将单词映射到数字,在哈希表中使用布尔值(当然是掩码)并且有一个O(1)拼写检查器。所以写这个根本不是问题。我的算法是这样的:
int pos;
word_key_t char_key;
word_key_t key = 0;
const char *raw = word.c_str();
cout << "Entering getKey loop with " << raw << endl;
for (pos = 0; raw[pos] != '\0'; pos++) {
if (raw[pos] >= 'A' && raw[pos] <= 'Z') {
char_key = raw[pos] - 'A';
} else if (raw[pos] >= 'a' && raw[pos] <= 'z') {
char_key = raw[pos] - 'a';
} else {
throw new runtime_error("Unrecognised Character");
}
key += (char_key + 1) * (pow(CHARS_IN_ALPHABET, pos));
}
cout << "word: " << raw << " ,score: " << key << endl;
return key;
似乎有效,
A = 1 B = 2 AB = 53 AC = 79
我认为这是正确的。
但是,我在尝试解码时遇到问题。这是我最好的尝试,它无法正常工作。我相信我需要使用pow(26,位置)并从字符串的末尾开始递减,但我只是在努力实现这一目标。这是一些可行的独立代码,它做错了:
#include <iostream>
#include <inttypes.h>
#include <string.h>
typedef uint32_t word_key_t;
const int CHARS_IN_ALPHABET = 26;
const int BUFFER_SIZE = 255; //ignore this for now.
using namespace std;
string reverseKey(const word_key_t key); //broken algo
int main(int argc, char** argv) {
reverseKey(53); // 53 = ab
return 0;
}
//disassemble a word_key_t into it's original string. returns lowercase only
string reverseKey(const word_key_t key)
{
char chr, buffer[BUFFER_SIZE];
word_key_t keyc = key, isolated, pos = BUFFER_SIZE;
cout << "key: " << keyc << endl;
while (keyc != 0) {
isolated = (keyc - 1) % ((word_key_t)CHARS_IN_ALPHABET + 1);
cout << "key: " << keyc << ", isolated: " << isolated << endl;
chr = (char)'a' + isolated - 1;
cout << "isolated character: " << chr << endl;
keyc = (keyc - isolated) / CHARS_IN_ALPHABET;
cout << "new key: " << keyc << endl;
pos++;
}
string s("test");
return s;
}
如果有人能够推动我找到正确的psudeocode来解决这个问题,那我真的很感激。我有点疯狂,并用解决方案丢失了情节。我只是看不到它。有东西告诉我2logX / 2log26,我想我只需要更聪明的眼睛。然后我可以回到学习C ++。“在这里输入代码
答案 0 :(得分:2)
稍后进行一些编辑。我确实误解了关键值的产生。我认为关键字母的生成将是:
while ( key )
{
int char_key = key % 26;
char c = 'a' + (char)( char_key - 1 );
key /= CHARS_IN_ALPHABET;
}
虽然我仍然不认为密钥的原始计算是正确的。我仍然认为关键计算应该是:
key = CHARS_IN_ALPHABET * key + char_key + 1;
以相反的顺序处理raw[]
数组,以避免以相反的顺序提取它们。
答案 1 :(得分:1)
你实际上有一个27号基数(aa = a * 26 + b)但是避免使用“零”。
INPUT: encodedWord such that "aa" = 27, "ab" = 28, etc. OUTPUT: The ASCII string outString := "" While encodedWord > 0 Do lastLetter = encodedWord % 27; encodedWord = encodedWord / 27; outString := toChar(lastLetter + 64) + outString; End-while Return outString;
答案 2 :(得分:0)
你的问题实际上恢复到基数到基数的转换,在你的情况下从基数10到基数26。 区别在于a = 0,b = 1等等(0 =第一个符号)。
另一个注意事项是你没有恢复转换后的字符串(ba = 53)。
这是完整的代码(第一个元素是0,而不是1,即a = 0)
与您的代码一样,转换后的字符串中的字符不会被反转(就像它们应该处于正常的基础到基础转换中一样)
#include <stdio.h>
int power(int x, int times){
int result = 1;
while (times--) result *= x;
return result;
}
void convert(int n, char *s){
int i = 0;
do {
s[i++] = (n % 26) + 'a';
} while ((n /= 26) > 0);
s[i] = 0;
}
int convertBack(char *s){
int i = 0;
int n = 0;
while (s[i]) {
n += ( (s[i]-'a') * power(26, i));
i++;
}
return n;
}
void main(){
char s[100];
convert(53, s);
printf("Converted:%s\n",s);
printf("Convert back=%d", convertBack(s));
}
答案 3 :(得分:0)
我建议不使用任何“power”函数,特别是浮点函数。
以下设置'a'= 0,'z'= 25,'aa'= 26等,仅使用整数加法,乘法和除法(无浮点)。每个编码的字符只需要一次乘法,每个字符解码只需要一个除法。
#include <cctype>
#include <iostream>
#include <string>
#include <algorithm>
template <class T>
T encode(const char* s)
{
T result = 0;
while (*s != 0)
{
result *= 26;
result += std::tolower(*s) - 'a';
++s;
}
return result;
}
template <class T>
std::string decode(T x)
{
std::string s;
while (x != 0)
{
s += x % 26 + 'a';
x /= 26;
}
std::reverse(s.begin(), s.end());
return s;
}
int main()
{
std::cout << decode(encode<unsigned int>("tbce")) << std::endl;
}
答案 4 :(得分:0)
你可以使用更多的空间进行权衡,并通过使基数为2的幂(在你的情况下为32)来获得更好的执行时间。
这样你就可以使用移位和逻辑运算代替乘法,除法和mod。
例如:
void convert(int n, char *s){
int i = 0;
do {
s[i++] = (n && 0x1F) + 'a';
} while ((n >>= 5) > 0);
s[i] = 0;
}
int convertBack(char *s){
int i = 0;
int n = 0;
while (s[i]) {
n += ( (s[i]-'a') >> 5*i;
i++;
}
return n;
}
主要应与kcsoft建议的相同。