Последовательность от a до zzz

320
13 мая 2017, 21:08

Как перебрать последовательность букв в цикле? каждую последовательность нужно иметь возможность получить, зная номер позиции.

1=a

2=b

...

z=26

aa=27

ab=28

ac=29

...

и так до zzz

Что-то вроде системы счисления, но без цифр.

Answer 1

В вашей системе счисления, условно выражаясь, есть ведущие нули, но нет "внутренних" нулей. Ведущие нули присутствуют только в начале "времени жизни" разряда, т.е. как только разряд стал ненулевым, он уже никогда не станет нулевым.

Это позволяет нам использовать классический алгоритм перевода путем итеративного деления с остатком на основание системы счисления, не забывая при этом, что каждый разряд начинает свою жизнь в особом - "пустом"/"нулевом" - состоянии. Это отражается в том, что перед выполнением деления с остатком, надо вычесть из переводимого значения единицу. В это правило, кстати, естественным образом вписывается соглашение о том, что значению 0 соответствует пустая строка.

За исключением этого предварительного вычитания единицы, классический "школьный" алгоритм перевода остается неизменным

std::string convert_ascii(unsigned v, unsigned b)
{
  std::string s;
  for (; v > 0; v /= b)
  {
    --v; // предварительное вычитание единицы
    s = (char) ('a' + v % b) + s;
  }
  return s;
}

Вот и все.

В вашем случае b = 26. Например, convert_ascii(12345678, 26) дает нам zzjut, а convert_ascii(322973, 26) - rita.

Answer 2

Оно похоже на просто систему счисления, но беда в том, что в ней нет нуля...

Вобщем, проще чем приведенное у меня что-то с утра не получается. Приходится учитывать, что a - это не нуль...

string az(unsigned int num)
{
    string s("");
    --num;               // Для отсчета с 0
    s += 'a' + num%26;   // Чередование последней буквы
    if (num >= 26)       // Есть вторая буква
    {
        num -= 26;
        s += 'a' + num/26%26;
    }
    if (num >= 26*26)    // Есть третья буква
    {
        num -= 26*26;
        s += 'a' + num/(26*26);
    }
    reverse(s.begin(),s.end());
    return s;
}

int main(int argc, const char * argv[])
{
    for(unsigned int n = 1; n <= 18278; ++n)
        cout << setw(5) << n << "  " << az(n) << endl;
}

Update
Все, написал в общем виде, кратенько и красиво :)

string az(unsigned int num)
{
    string s("");
    for(unsigned int cnt = 1; num >= cnt; cnt *= 26)
        s = char('a' + (num-=cnt)/cnt%26) + s;
    return s;
}

Update 2

Только для @AnT :)

string div26(const string& d, unsigned int& r)
{
    string q;
    r = 0;
    if (d.length() == 0) return q;
    bool wroted = false;
    for(size_t i = 0; i < d.length(); ++i)
    {
        r = r*10 + (d[i]-'0');
        unsigned int v = r/26;
        r %= 26;
        if (!wroted && v == 0) continue;
        q += char('0' + v);
        wroted = true;
    }
    return q;
}
void dec(string& n)
{
    if (n.length() == 0) return;
    if (n.length() == 1 && n[0] == '0') return;
    for(int i = n.length()-1; i >= 0; --i)
    {
        if (n[i] >= '1') { --n[i]; break; }
        n[i] += 9;
    }
    size_t nz = n.find_first_not_of("0");
    if (nz == string::npos) n = "";
    else n = n.substr(nz);
}
string az(const string& number)
{
    string res;
    for(string n = number; n.length();)
    {
        dec(n);
        unsigned int r;
        n = div26(n,r);
        res = char('a' + r) + res;
    }
    return res;
}

Проверяйте. Строка номер гугол: hxrtplbmwaiwcqlzpmglpziaegsdivmbvlnssusbjtbcgywaycqnhxztqwwikxvrsptazpp

Answer 3

Решение так сказать в лоб.
Это конечно не c++ и не delphi(это java), но идея в принципе думаю понятна.

public class Main {
    public static void main(String[] args) {
        int n = 26;
        int iterator = 0;
        int L = n + n * n + n * n * n; // общая длина массива
        String[] code = new String[L + 1]; // сам массив
        for (int i = 97; i <= 122; i++) { // заполняем для первой буквы
            iterator++;
            code[iterator] = String.valueOf((char) i);
        }
        for (int i = 97; i <= 122; i++) {// заполняем для второй буквы
            for (int j = 97; j <= 122; j++) {
                iterator++;
                code[iterator] =(char) i +"" + (char) j;
            }
        }
        for (int i = 97; i <= 122; i++) {// заполняем для третей буквы
            for (int j = 97; j <= 122; j++) {
                for (int k = 97; k <= 122; k++) {
                    iterator++;
                    code[iterator] = ""+(char) i + (char) j + (char) k;
                }
            }
        }
        Scanner scanner=new Scanner(System.in);
        System.out.println(code[scanner.nextInt()]); // выводим на консоль нужный символ
    }
}

Вывод всё как надо: 1 a 26 z 1000 all 27 aa

READ ALSO
Непонятная битовая операция

Непонятная битовая операция

Что может означать операция i = i & (i+1) в реализации дерева отрезков?

291
C++ теорема синусов [требует правки]

C++ теорема синусов [требует правки]

Здравствуйте! У меня есть задание написать дочерний класс Треугольник от класса УголКласс Угол уже готов, но у меня есть задание: имея класс...

246
Отсутствует компонент TDBGrid в Embarcadero C++ Builder 10.2

Отсутствует компонент TDBGrid в Embarcadero C++ Builder 10.2

Не удаётся найти компонент TDBGrid в Embarcadero C++ Builder 102

416
Как исправить ошибку undefined reference to

Как исправить ошибку undefined reference to

Мне нужно использовать готовый C++ класс CatalogИспользуя статью сделал начальную настройку проекта

504