Счетчик произвольных цифр - PullRequest
0 голосов
/ 22 декабря 2009

Мне нужен счетчик algortihm , который использует произвольные заданные цифры для целей подсчета.

Мой код похож на это:

static char digits[] = {'x','y','z'}; /* Arbitrary number of arbitrary digits. */
int i;
for(i=0; i<100; i++) {
    printf("%s\n", get_next());
}

Мой ожидаемый результат:

x
y
z
yx
yy
yz
zx
zy
zz
yxx
yxy
yxz
yyx
yyy
yyz
yzx
yzy
yzz
zxx
... and so on

Как видите, мне нужен алгоритм для реализации функции get_next(), поэтому использование языка Си не имеет смысла.

Изменить I для уточнения:

Моя функция get_next () может похожа на это:

char get_next() {
    static previous = digits[0];
    char *next_number;

    /* do something here using previous and digits[] */

    return next_number;
}

Обратите внимание, что использование прототипа get_next(void) или next(previous_number) или next(digits, previous_number) для вашей функции, которая генерирует следующее число, для меня не важно.

Изменить II для уточнения:

Мой реальный сценарий более сложен из простого примера выше, мне нужно универсальное решение, которое работает с произвольным числом из произвольными цифрами .

Пример ввода цифр:

static char digits[] = {'a', 'b', 'c', ... 'z', '0', '1', ...}; /* Lots of digits */
static char digits[] = {'s','t','a','c','k','o','v','e','r'};   /* Arbitrary sequence */

Ответы [ 4 ]

5 голосов
/ 22 декабря 2009

Это довольно просто. Вы хотите преобразовать в base digit_count, а затем вместо того, чтобы преобразовывать цифры в числа, вы индексируете в свой массив.

Чтобы преобразовать в произвольную базу, вам нужно разделить и остаток.

Вот более лучшая версия, чем та, которую я использовал ранее, потому что она фактически создает буфер (а не распечатывает его), отбрасывает рекурсию для итерации и находится в C вместо моей предыдущей сборочной ложки C / Python.

Поскольку он использует статический буфер, код не является потокобезопасным. Также обратите внимание, что нет никакой проверки ошибок, что код не опустошает буфер, если число слишком велико. Наконец, он использует хитрость построения строки от конца к началу и возврата указателя на середину буфера, чтобы ему не приходилось переворачивать цифры в конце.

char *getnum(int x)
{
    static char buffer[1024];
    int idx = 1024;

    buffer[--idx] = '\0';

    if (x == 0)
        buffer[--idx] = digits[0];
    else
    {
        while (x != 0)
        {
            buffer[--idx] = digits[x % digit_count];
            x /= digit_count;
        }
    }    

    return buffer + idx;
}
2 голосов
/ 22 декабря 2009

Ваш вопрос можно разделить на две части:

  1. конвертирует целое число в его представление в произвольной базе, n и
  2. учитывая n символов, выведите изображение выше.

Вторая часть, очевидно, очень проста. Если у вас есть представление числа в заданной базе и символов, которые вы хотите использовать в такой базе, то их распечатка - это просто печать вещей в цикле.

Чтобы получить целочисленное представление в данной базе, мы будем использовать массив int s, со значениями, представляющими цифры, и индексами, представляющими места. Нам также нужно хранить количество действительных цифр. Кроме того, мы предполагаем, что имеем дело только с положительными числами, поскольку это то, что вы, похоже, предлагаете в своем вопросе.

#define MAX 128 /* maximum number of digits in the final representation */

/* abstract representation of a number in a given base.
   `n` is the number of valid digits in the representation, and
   `digits` stores the digits in reverse order */
struct rep {
    int digits[MAX]; /* change as needed, or dynamically allocate */
    size_t n;
};

Тогда давайте напишем функцию для преобразования числа в его представление. Поскольку проще вернуть обратное представление, мы вернем его и затем напечатаем в обратном порядке:

/* convert a number `n` to its (reversed) representation in base `base`,
   and return the result in `ret`. */
void convert(int n, size_t base, struct rep *ret)
{
    size_t i = 0;
    do {
        ret->digits[i++] = n % base;
        n /= base;
    } while (n > 0 && i < MAX);
    ret->n = i;
}

Сделав это, давайте напишем функцию для вывода представления:

/* return a string representation of `num` in base `ndigits`, with `digits`
   representing the symbols */
char *next(const char *digits, size_t ndigits, int num)
{
    struct rep r;
    static char ret[MAX+1];
    size_t i;
    convert(num, ndigits, &r);
    if (r.n == MAX)
        return NULL;
    for (i=r.n; i; --i)
        ret[r.n-i] = digits[r.digits[i-1]];
    ret[r.n-i] = 0;
    return ret;
}

Затем мы можем написать нашу программу драйвера:

int main(void)
{
    const char digits[] = {'x','y','z'};
    size_t ndigits = sizeof digits / sizeof digits[0];
    int i;
    for (i=0; i < 100; i++) {
        char *data = next(digits, ndigits, i);
        if (data)
            printf("%s\n", data);
        else
            fprintf(stderr, "%d, error converting\n", i);
    }
    return 0;
}

Я написал convert и next выше, чтобы они не зависели друг от друга (кроме очевидного упрощения, что я использую обратные представления). Это позволяет легко использовать их в других программах.

0 голосов
/ 23 декабря 2009

Похоже, вместо get_next вам нужно перегрузить operator++. Это приводит к следующему выводу: эта вещь должна быть отдельным объектом.

Я бы преобразовал «цифры» в десятичную, затем обработал их, а затем преобразовал их обратно.

0 голосов
/ 22 декабря 2009
char *get_next()
{
  static char str[10];
  static int i=0;
  int radix = 3; // size of array
  itoa(i,str,radix); // create base-3 representation
  char *p = &str[0];
  while( *p )
  {
    *p = digits[*p-'0']; // convert to the xyz scheme, breaks if radix>10
    p++;
  }
  i++;
  return str;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...