Как увеличить строку Java через все возможности? - PullRequest
17 голосов
/ 05 декабря 2008

Мне нужно увеличить строку в java с "aaaaaaaa" до "aaaaaab" до "aaaaaac" вверх по алфавиту, а затем со временем до "aaaaaaba" на "aaaaaabb" и т. Д. И т. Д.

Есть ли хитрость для этого?

Ответы [ 13 ]

53 голосов
/ 05 декабря 2008

В основном вы реализуете Система счисления 26 с нуля с ведущими "нулями" ("a").

Вы делаете это так же, как конвертируете int в строку base-2 или base-10, но вместо 2 или 10 вы используете 26 и вместо «0» в качестве своей базы вы используете «a» .

В Java вы можете легко использовать это:

public static String base26(int num) {
  if (num < 0) {
    throw new IllegalArgumentException("Only positive numbers are supported");
  }
  StringBuilder s = new StringBuilder("aaaaaaa");
  for (int pos = 6; pos >= 0 && num > 0 ; pos--) {
    char digit = (char) ('a' + num % 26);
    s.setCharAt(pos, digit);
    num = num / 26;
  }
  return s.toString();
}

Основная идея заключается в том, чтобы не хранить строку, а просто какой-то счетчик (int или long, в зависимости от ваших требований) и преобразовывать его в строку по мере необходимости. Таким образом, вы можете легко увеличивать / уменьшать / изменять свой счетчик без необходимости разбирать и заново создавать строку.

13 голосов
/ 26 февраля 2010

В следующем коде используется рекурсивный метод для получения следующей строки (скажем, от «aaaa» до «aaab» и т. Д.) Без необходимости создания всех предыдущих комбинаций, поэтому он довольно быстрый и не ограничивается заданная максимальная длина строки.

public class StringInc {
 public static void main(String[] args) {
   System.out.println(next("aaa")); // Prints aab

   System.out.println(next("abcdzz")); // Prints abceaa

   System.out.println(next("zzz")); // Prints aaaa
 }

 public static String next(String s) {
   int length = s.length();
   char c = s.charAt(length - 1);

   if(c == 'z')
     return length > 1 ? next(s.substring(0, length - 1)) + 'a' : "aa";

   return s.substring(0, length - 1) + ++c;
 }
}
4 голосов
/ 05 декабря 2008

Увеличивает последний символ и, если он достигает Z, сбрасывает его до A и перемещается к предыдущим символам. Повторяйте, пока не найдете символ, который не является Z. Поскольку строки являются неизменяемыми, я предлагаю вместо этого использовать массив символов, чтобы избежать выделения большого количества новых объектов.

public static void incrementString(char[] str)
{
    for(int pos = str.length - 1; pos >= 0; pos--)
    {
        if(Character.toUpperCase(str[pos]) != 'Z')
        {
            str[pos]++;
            break;
        }
        else
            str[pos] = 'a';
    }
}
1 голос
/ 05 декабря 2008

Я бы согласился с подходом @ saua, если бы вы хотели только конечный результат, но здесь есть небольшое изменение в случае, если вы хотите получить каждый результат.

Обратите внимание, что, поскольку существует 26 ^ 8 (или 208827064576) различных возможных строк, я сомневаюсь, что вы хотите их все. Тем не менее, мой код печатает их вместо хранения только одного в String Builder. (Хотя это не так важно.)

  public static void base26(int maxLength) {
    buildWord(maxLength, "");
  }
  public static void buildWord(int remaining, String word)
  {
    if (remaining == 0)
    {
      System.out.println(word);
    }
    else
    {
      for (char letter = 'A'; letter <= 'Z'; ++letter)
      {
        buildWord(remaining-1, word + letter);
      }
    }
  }

  public static void main(String[] args)
  {
    base26(8);
  }
1 голос
/ 05 декабря 2008

вы можете использовать метод toString (radix) большого целого числа, например:

import java.math.BigInteger;
public class Strings {
    Strings(final int digits,final int radix) {
        this(digits,radix,BigInteger.ZERO);
    }
    Strings(final int digits,final int radix,final BigInteger number) {
        this.digits=digits;
        this.radix=radix;
        this.number=number;
    }
    void addOne() {
        number=number.add(BigInteger.ONE);
    }
    public String toString() {
        String s=number.toString(radix);
        while(s.length()<digits)
            s='0'+s;
        return s;
    }
    public char convert(final char c) {
        if('0'<=c&&c<='9')
            return (char)('a'+(c-'0'));
        else if('a'<=c&&c<='p')
            return (char)(c+10);
        else throw new RuntimeException("more logic required for radix: "+radix);
    }
    public char convertInverse(final char c) {
        if('a'<=c&&c<='j')
            return (char)('0'+(c-'a'));
        else if('k'<=c&&c<='z')
            return (char)(c-10);
        else throw new RuntimeException("more logic required for radix: "+radix);
    }
    void testFix() {
        for(int i=0;i<radix;i++)
            if(convert(convertInverse((char)('a'+i)))!='a'+i)
                throw new RuntimeException("testFix fails for "+i);
    }
    public String toMyString() {
        String s=toString(),t="";
        for(int i=0;i<s.length();i++)
            t+=convert(s.charAt(i));
        return t;
    }
    public static void main(String[] arguments) {
        Strings strings=new Strings(8,26);
        strings.testFix();
        System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString());
        for(int i=0;i<Math.pow(strings.radix,3);i++)
            try {
                strings.addOne();
                if(Math.abs(i-i/strings.radix*strings.radix)<2)
                    System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString());
            } catch(Exception e) {
                System.out.println(""+i+' '+strings+" failed!");
            }
    }
    final int digits,radix;
    BigInteger number;
}
0 голосов
/ 29 октября 2018
public static String incrementString(String string)
{
    if(string.length()==1)
    {
        if(string.equals("z"))
            return "aa";
        else if(string.equals("Z"))
            return "Aa";
        else
            return (char)(string.charAt(0)+1)+"";
    }   
    if(string.charAt(string.length()-1)!='z')
    {
        return string.substring(0, string.length()-1)+(char)(string.charAt(string.length()-1)+1);
    }
    return incrementString(string.substring(0, string.length()-1))+"a";
}

Работает для всех стандартных строк, содержащих алфавиты

0 голосов
/ 27 февраля 2017

Поскольку ни один из ответов не был мне полезен, я написал свой собственный код:

/**
 * Increases the given String value by one. Examples (with min 'a' and max 'z'): <p>
 * 
 * - "aaa" -> "aab" <br>
 * - "aab" -> "aac" <br>
 * - "aaz" -> "aba" <br>
 * - "zzz" -> "aaaa" <br>
 * 
 * @param s
 * @param min lowest char (a zero)
 * @param max highest char (e.g. a 9, in a decimal system)
 * @return increased String by 1
 */
public static String incString(String s, char min, char max) {
    char last = s.charAt(s.length() - 1);
    if (++last > max)
        return s.length() > 1 ? incString(s.substring(0, s.length()-1), min, max) + min : "" + min + min;
    else
        return s.substring(0, s.length()-1) + last;
}
0 голосов
/ 21 января 2016

Опираясь на решение @cyberz, следующий код является примером того, как можно написать рекурсивный вызов, который может быть оптимизирован компилятором, поддерживающим Tail Recursion .

Код написан на Groovy, так как он работает на JVM, его синтаксис очень похож на Java, а его компилятор поддерживает оптимизацию хвостовой рекурсии

static String next(String input) {
    return doNext(input, "")
}

@TailRecursive
@CompileStatic
static String doNext(String input, String result) {
    if(!self) {
        return result
    }

    final String last = input[-1]
    final String nonLast = self.substring(0, input.size()-1)
    if('z' == last) {
        return doNext(nonLast, (nonLast ? 'a' : 'aa') + result)
    }

    return doNext('', nonLast + (((last as Character) + 1) as Character).toString() + result)
}
0 голосов
/ 03 ноября 2013

Этот код должен работать для строки любого размера.

 public static String iterateAlphabetic(String input) {
            String output = input.toUpperCase();
            char[] array = output.toCharArray();
            boolean overflow = true;
            for(int itr=array.length-1; itr>=0; itr--) {
                if(overflow && array[itr]=='Z') {
                    array[itr] = 'A';
                    overflow = true;
                    continue;
                }
                if(overflow) {
                    array[itr] = next(alphabeticUpper,array[itr]);
                    overflow = false;
                    continue;
                }
                break;
            }       
            if(overflow)
                output = "A" + new String(array);
            else
                output = new String(array);
            if(output.length() < input.length())
                output = StringUtil.padding(output, 'A', input.length());
            return output;
        }

public static String padding(String input, char pad, int width) {
     if (width < 0)
         throw new IllegalArgumentException("width must be > 0");

     if (width < input.length())
         return input;

    StringBuilder sb = new StringBuilder();
    for(int i = 0;i < (width - input.length()); i++) {
        sb.append(pad);
    }
    sb.append(input);
    return sb.toString();
}
0 голосов
/ 05 декабря 2008

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

public class Permutator {

    private int permutation;

    private int permutations; 

    private StringBuilder stringbuilder;

    public Permutator(final int LETTERS) {

        if (LETTERS < 1) {
            throw new IllegalArgumentException("Usage: Permutator( \"1 or Greater Required\" \)");
        }

        this.permutation = 0;

        // MAGIC NUMBER : 26 = Number of Letters in the English Alphabet 
        this.permutations = (int) Math.pow(26, LETTERS);

        this.stringbuilder = new StringBuilder();

        for (int i = 0; i < LETTERS; ++i) {
            this.stringbuilder.append('a');
        }
    }

    public String getCount() {

        return String.format("Permutation: %s of %s Permutations.", this.permutation, this.permutations);
    }

    public int getPermutation() {

        return this.permutation;
    }

    public int getPermutations() {

        return this.permutations;
    }

    private void permutate() {

        // TODO: Implement Utilising one of the Examples Posted.
    } 

    public String toString() {

        this.permutate();

        return this.stringbuilder.toString();
    }
}    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...