0

I'm trying to find an algorithm in java for getting a special list of numbers. I tried writing my thoughts in code, but I feel my brain starting to melt... Maybe you can help me.

The algorithm should give me a list of all numbers:

  • with a setable length

  • with only numbers in a setable range

  • with each number appearing once or less

So if I set the length to 3 and the range of numbers to 0-4 it should start like this:

012
013
014
021
023
024
031
032
034
041
042
043
102
103
...

I know this is not a question for something I don't know, but I already spent an eternity with this algorithm and my brain starts hurting. Maybe I'm just thinking the wrong way...

Froxx
  • 957
  • 4
  • 14
  • 27
  • What you are asking are the combinations of r items taken l by l. –  Sep 17 '14 at 15:27
  • If this is a homework problem you should say so. It sounds like one. – x-code Sep 17 '14 at 20:22
  • possible duplicate of [Permutation of array](http://stackoverflow.com/questions/2920315/permutation-of-array) – phs Sep 17 '14 at 21:48

2 Answers2

1

Base X Numeral Systems!

You can interpret generate combinations of {...}x as count in base X

Your question, rephrased: Enumerate base X numbers, up to the highest such number with n digits

Naïve stab:

for(int i = 0; i < Math.pow(5, 3); i++) {
    System.out.println(Integer.toString(i, 5));
}

Now, a few observations:

  • Your example begins with "012", I'll assume that you actually meant "000"
  • The base in your example is "4 + 1 = 5"
  • The base in the general case is "b - a + 1", where your range is {a..b}
  • The symbols normally used to represent numbers in base X are the Arabic numerals 0..(X-1)
  • The symbols that you use in your number system are the Arabic numerals, from a to b
  • Numbers do not have leading zeros, string representations of numbers do.
  • The highest number of length n in base X is Xn - 1
  • You can not customize String padding, so set width to n and replace ' ' with a

To generate your list of Strings:

  1. Find the base of your number system
  2. Count from 0 to Xn-1
  3. Generate a base X representation of each number
  4. Add a to all symbols in the generated representation
  5. Pad the string on the left with a

Code!

public static void main(String[] args) {
    for(String s : generate(3, 0, 4)) {
        System.out.println(s);
    }
}

private static List<String> generate(int n, int a, int b) {
    List<String> numbers = new ArrayList<>();
    int base = b - a + 1;                        // (1)
    for(int i = 0; i < Math.pow(base, n); i++) { // (2)
        String s = Integer.toString(i, base);    // (3)
        s = substituteSymbols(s, a);             // (4)
        s = String.format("%" + n + "s", s);     // (5)...
        s = replacePadding(a, s);                // ...(5)

        numbers.add(s);
    }
    return numbers;
}

private static String substituteSymbols(String s, int a) {
    char[] digits = s.toCharArray();
    StringBuilder sb = new StringBuilder();
    for(int c = 0; c < digits.length; c++) {
        int val = Character.getNumericValue(digits[c]) + a;
        sb.append(Character.forDigit(val, Character.MAX_RADIX));
    }
    return sb.toString();
}

private static String replacePadding(int a, String s) {
    return s.replace(' ', Character.forDigit(a, Character.MAX_RADIX));
}

Note:

  • You could also stick to the naïve stab and discard Strings containing digits less than a
  • A robust solution should handle invalid arguments
  • A generic solution should not assume alphanumeric symbols
  • This solution will create unnecessary garbage due to all new Strings
  • If the base is higher than Character.MAX_RADIX, base 10 will be used
folkol
  • 4,752
  • 22
  • 25
  • I think he is requiring each digit appears at most once. `000` is invalid because it contains more than one `0`. – phs Sep 17 '14 at 21:47
  • Oh, that explains the 012 in the beginning. But he did say "number" :P – folkol Sep 18 '14 at 05:35
  • Wow, that's awesome! A great way of setting a new radix. I didn't get this one by myself. Thanks a lot! The only thing that doesn't fit with my idea is '000' etc., but that's a thing I can do by myself ;) – Froxx Sep 18 '14 at 09:52
  • Yeah, that was a misunderstanding from my part. I think it was because you used the word "number" to mean "symbol/digit". Anyway, good luck! – folkol Sep 18 '14 at 10:49
0

Your code should be like

public static void main (String[]args) {
    int totalNumbers=10, max=50,min =20;
    Random rand = new Random();
    Set<Integer> integers = new HashSet<Integer>();
    while(integers.size()<totalNumbers){
        integers.add(randomNumberGenerationInRange(rand, max, min));
    }
    for(Integer eachInteger: integers){
        System.out.println(String.format("%05d", eachInteger));
    }
}

private static int randomNumberGenerationInRange(Random rn,int maximum, int minimum) //This is where I'm trying to find LCM of 2 numbers
{
    int n = maximum - minimum + 1;
    int i = rn.nextInt() % n;
    return minimum + i;
}

Note String.format("%05d", eachInteger) is what adds the leading zeros to the number ... if you chafe 5 to 3 the the desired output as the question will be achieved. Set is use so that there are no duplicates.

StackFlowed
  • 6,664
  • 1
  • 29
  • 45