5

I need to generate character sequences that increment, where each character can be of a different letter or number range. Does anyone know of a library that does such a task? For example:

AAA000_A0

Where A's are any letter A-Z, and 0's are any number 0-9. I need to increment them as well, so for example:

AAA000_A0++ = AAA000_A1

And if you keep going it would carry over like this:

AAA000_A9++ = AAA000_B0

Until it reached:

ZZZ999_Z9
Ben
  • 51,770
  • 36
  • 127
  • 149
Kevin Lawrence
  • 741
  • 9
  • 18
  • 1
    I don't know whether there's a library for this, but it sounds like a cute interview question! :) – Dilum Ranatunga May 29 '13 at 19:38
  • 1
    There is no such library in the JDK that will generate sequences that can be customized in the way you describe. It wouldn't be greatly difficult to write an implementation, though. An important question to answer is: does the generator need to be thread safe? – scottb May 29 '13 at 19:39
  • @DilumRanatunga outsource by interview?! I like your style! – Kevin Lawrence May 29 '13 at 20:48
  • @KevinLawrence, I have done that in the past -- asked solid candidates a variant of an actual problem I was tackling. But in this case, the problem is simple to explain, and asks the candidate to demonstrate some decomposition skills etc. – Dilum Ranatunga May 29 '13 at 20:51

2 Answers2

3

I would decompose the problem to each spot, sort of like a car's odometer:

public class CounterDigit {
    private final CounterDigit _higher;
    private final String _chars;
    private int _index = 0;

    public CounterDigit(CounterDigit higher, String chars) {
        _higher = higher;
        _chars = chars;
    }

    public CounterDigit(CounterDigit higher, char first, char last) {
        this(higher, charRange(first, last));
    }

    private static String charRange(char first, char last) {
        StringBuilder b = new StringBuilder();
        for (char c = first; c <= last; ++c) {
            b.append(c);
        }
        return b.toString();
    }

    public char current() {
        return _chars.charAt(_index);
    }

    public void increment() {
        if (++_index >= _chars.length()) {
            _index = 0;
            if (_higher != null) {
                _higher.increment();
            }
        }
    }
}

You can then aggregate an ordered sequence of these:

public class Counter {
    private CounterDigit[] _digits;

    public Counter(String template) {
        CounterDigit recent = null;
        _digits = new CounterDigit[template.length()];
        for (int i = 0; i < template.length(); ++i) {
            char c = template.charAt(i);
            if      (c == 'A') { recent = new CounterDigit(recent, 'A', 'Z'); }
            else if (c == '0') { recent = new CounterDigit(recent, '0', '9'); }
            else               { recent = new CounterDigit(recent, c, c);     }
            _digits[i] = recent;
        }
    }

    public void increment() {
        _digits[_digits.length-1].increment();
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder(_digits.length);
        for (CounterDigit digit : _digits) {
            b.append(digit.current());
        }
        return b.toString();
    }
}
Dilum Ranatunga
  • 13,254
  • 3
  • 41
  • 52
  • I'm somewhat surprised there isn't a library for this, there seems to be a library for everything. I am going to hack around with this and maybe make the types a little more extendible. Great job, many thanks! – Kevin Lawrence May 29 '13 at 21:04
1

It's a simple algorithm, a short function would suffice over a library.

Here's an example in JavaScript that I threw together.

var _LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var _NUMBERS = "0123456789";
function nextValue(str) {
    var result = "";
    var carry = true;
    var chr, idx, lookup;
    for(var i=str.length - 1; i>=0; i--) {
        chr = str.charAt(i);
        if(carry) {
            lookup = _LETTERS.indexOf(chr) >= 0 ? _LETTERS : (_NUMBERS.indexOf(chr) >= 0 ? _NUMBERS : "");
            idx = lookup.indexOf(chr);
            if(idx >= 0) {
                if(idx == lookup.length - 1) {
                    idx = 0;
                } else {
                    idx++;
                    carry = false;
                }
                chr = lookup.charAt(idx);
            }
        }
        result = chr + result;
    }
    return result;
}

var demo = "0_A";
while(demo != "9_Z") {
    demo = nextValue(demo);
    console.log(demo);
}

It should be simple for you to port/convert to Java the function names like "indexOf" and "charAt" should be the same.

Louis Ricci
  • 20,804
  • 5
  • 48
  • 62