Прибавьте значение от AAA до ZZZ с циклическим вращением

Мне нужно закодировать метод, который увеличивает значение строки от AAA до ZZZ с циклическим вращением (следующее значение после ZZZ равно AAA)

Вот мой код:

    public static string IncrementValue(string value) {
        if (string.IsNullOrEmpty(value) || value.Length != 3) {
            string msg = string.Format("Incorrect value ('{0}' is not between AAA and ZZZ)", value);
            throw new ApplicationException(msg);
        }
        if (value == "ZZZ") {
            return "AAA";
        }
        char pos1 = value[0];
        char pos2 = value[1];
        char pos3 = value[2];

        bool incrementPos2 = false;
        bool incrementPos1 = false;

        if (pos3 == 'Z') {
            pos3 = 'A';
            incrementPos2 = true;
        } else {
            pos3++;
        }

        if (incrementPos2 && pos2 == 'Z') {
            pos2 = 'A';
            incrementPos1 = true;
        } else {
            if (incrementPos2) {
                if (pos2 == 'Z') {
                    pos2 = 'A';
                    incrementPos1 = true;
                }
                pos2++;
            }
        }

        if (incrementPos1) {
            pos1++;
        }

        return pos1.ToString() + pos2.ToString() + pos3.ToString();
    }

Я знаю, что этот фрагмент кода довольно грязный и не очень эффективный, но я не знаю, как это сделать должным образом.

Как обеспечивается этот фрагмент? (это будет выполняться только в виде окна)

Как я могу его оптимизировать и сделать его более читаемым?

Спасибо за ваши комментарии

Ответ 1

Подумайте об этом математически: ваши строки (AAA, AAB,...) ведут себя точно так же, как натуральные числа (000, 001,...), за исключением основания 26 вместо базы 10.

Итак, вы можете использовать тот же принцип. Вот какой код:

// iterate cyclicly from 0 to 26^3 - 1
int incrementValue(int i) {
    // a verbose way of writing "return (i + 1) % 26^3"
    i++;
    if (i == 26*26*26) i = 0;
    return i;
}

// convert 0 to AAA, 1 to AAB, ...
string formatValue(int i) {
    var result = new StringBuilder();

    result.Insert(0, (char)('A' + (i % 26)));
    i /= 26;
    result.Insert(0, (char)('A' + (i % 26)));
    i /= 26;
    result.Insert(0, (char)('A' + (i % 26)));

    return result.ToString();
}

Ответ 2

Возможно, мне что-то не хватает, но я думаю, что это разумное тривиальное решение работает, а не только для трехзначных чисел; любое произвольное количество базы 26 может быть увеличено. Он будет переноситься из ZZZZ в AAAA в соответствии с вопросом, а не увеличивать "правильно" от ZZZZ до AAAAA.

// Increment a base 26 number (composed of "digits" A..Z), wrapping around
// from ZZZ... to AAA...
string increment(string str) {        
  char[] digits = str.ToCharArray();

  for (int i = str.length - 1; i >= 0; --i) {
    if (digits[i] == 'Z') {
      digits[i] = 'A';
    } else {
      digits[i] += 1;
      break;
    }
  }
  return new string(digits);
}

Ответ 3

Я думаю, что проще разобрать его на целое число, сделать приращение, а затем форматировать результат как строку. Обратите внимание, что если вам просто нужно перебирать числа, чтобы сгенерировать диапазон комбинаций, вам действительно не нужно приращение/синтаксический анализ. Вы можете просто иметь цикл for в целочисленном диапазоне и использовать метод format для преобразования целого в строку.

public static string IncrementValue(string value) {
    if (string.IsNullOrEmpty(value) || value.Length != 3) {
        string msg = string.Format("Incorrect value ('{0}' is not between AAA and ZZZ)", value);
        throw new ApplicationException(msg);
    }
    if (value == "ZZZ") {
        return "AAA";
    }
    int thisValue = Parse( value );
    thisValue = (thisValue + 1) % 17576; // 26 * 26 * 26
    return Format( thisValue );
}

private static int Parse( string value )
{
     int result = 0;
     foreach (var c in value)
     {
         result += ('Z' - c);  // might need to cast to int?
     }
     return result;
}

private static string[] Alphabet = new string[] { 'A', 'B', ... };
private static string Format( int value )
{
   int digit0 = value % 26;
   int digit1 = (value / 26) % 26;
   int digit2 = value / 676;
   return Alphabet[digit2] + Alphabet[digit1] + Alphabet[digit0];
}

Ответ 4

В 'C' я написал следующее, которое будет делать точно так, как запрошено, то есть, если AA будет увеличиваться до AB. Если ZZZ будет увеличиваться до AAA (цикл).

main(int argc, char **argv)
{

     int i;
     char *s = argv[1];

     for(i=strlen(s)-1; i >= 0; i--) {
          if(++s[i] > 'Z')
               s[i] = 'A';
          else
               break;
     }

     printf("%s\n",s);
}

Ответ 5

import java.util.*;

import java.io.*;

public class abc{

public static void main (String arg[])throws Exception{

int  i;

String s;

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

System.out.println("...");\\just for get length of vector example 3 for aaa to zzz
i= Integer.parseInt(br.readLine());  
char[] guess = new char[i];

Arrays.fill(guess, 'a');


 do {
 System.out.println("Current guess:  " + new String(guess));


 int n = guess.length - 1;

 while (n >= 0) {

guess[n]++;

if (guess[n] > 'z') {

                if (n > 0) {

                    guess[n] = 'a';

                }

                n--;

            }

    else {

                break;

            }

        }


    }
 while (guess[0] <= 'z');

}