0

I am trying to write a method that will generate random integers in sorted order, and the limit of the random numbers should be log of how many are entered. The code I have written works when I do 10 integers, I get 0 for all the outputs which is correct. However, if I enter 100 or 1000 I don't get the values 0,1 or 0,1, and 2. I don't know why it isn't computing the correct way, I just need it to only initializes the integers in the array to be log of the number, but it doesn't work for anything greater than 10. Any help would be greatly appreciated, I have posted the code below.

public static void randomSortedLimited(ArrayList<Integer> inL,
                                                    int inHowMany) {

    inL.clear();
    int limit = (int) (Math.log10(inHowMany));
    //System.out.println(limit); added to make sure limit is calculated properly
    inL.add(0);
    for (int i = 1; i < inHowMany - 1; i++) {
        inL.add(i, inL.get(i-1) + new java.util.Random().nextInt(limit));
     }
}

Input: randomSortedLimited(emptyList, 10);

Output: [0,0,0,0,0,0,0,0,0,0]

Input: randomSortedLimited(empytList, 100);

Output:

[0, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 15, 15, 15, 16, 16, 17, 17, 18, 19, 20, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 27, 28, 29, 30, 30, 30, 31, 31, 32, 32, 32, 32, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 40, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 50]
BUILD SUCCESSFUL (total time: 0 seconds)
  • May be show the outputs to help us see the problem, what unexpected outputs you get when using 100 or 1000 values. – Badda Sep 24 '19 at 22:12
  • Please also explain what your inputs are. A [mcve] would be very helpful. – azurefrog Sep 24 '19 at 22:13
  • Your limit gets exceded, i suppose, because everytime you create a new Integer, you add something that might be as big as limit and add it to something that already was possibly as big as limit. But as Badda said, output would be helpful. – GitPhilter Sep 24 '19 at 22:14
  • 3
    @azurefrog I guess he or her is clearing the list first, but I dont get the point in passing a List as an argument which then gets cleared. Why not create a new List inside the function? – GitPhilter Sep 24 '19 at 22:17
  • @GitPhilter Huh, I overlooked that. Now I have even less idea what this method is supposed to do. – azurefrog Sep 24 '19 at 22:19
  • I have added outputs and inputs to the code. Is there a way I can prevent the limit from exceeding itself. @GitPhilter – mickeyvolmouse Sep 24 '19 at 22:46
  • You now show your output to be `[0, 1, 2, 2, 3, 3, 4, 4, 4, 5, ...]`, which seems correct, given the code. Are you saying you expected `[0, 1, 1, 0, 1, 0, 1, 0, 0, 1, ...]`? If so, then why did you code `inL.add(i, inL.get(i-1) + random.nextInt(limit))`, which specifically accumulates the new random number as a delta added to previous number? --- Your code should be `inL.add(random.nextInt(limit))` – Andreas Sep 24 '19 at 22:47
  • *Unrelated:* Do not create a new `Random` inside the loop. Create it before the loop and use that single `Random` object. Recreating new `Random` objects will reduce the randomness of the result. – Andreas Sep 24 '19 at 22:48
  • @Andreas the characters are sorting correctly, but if I enter 100 as how many I want, the values inside the array should not go past 0 and 1 because I want the limit to be log(100) which is 2. I don't want the numbers to pass 0 and 1 in that case. – mickeyvolmouse Sep 24 '19 at 22:54
  • @mickeyvolmouse You're confusing me. Values should not go past 0 and 1, so you want `[0, 1, 1, 0, 1, 0, 1, 0, 0, 1, ...]` like I asked, or not? Please edit the question and show what you expect the result to be. – Andreas Sep 24 '19 at 23:00
  • I am not sure if the answer I posted is correct, because I am beginning to doubt that I understood the question regarding all the comments that have been written here. – GitPhilter Sep 24 '19 at 23:01
  • @mickeyvolmouse It is that you want only 0's and 1's, but you want them sorted, i.e. `[0, 0, 0, 0, 0, ..., 1, 1, 1, 1, 1]` for input 100? Or `[0, 0, 0, 0, 0, ..., 1, 1, 1, 1, 1, ..., 2, 2, 2, 2, 2]` for input 1000? If so, then just **call `Collections.sort(inL)` after the loop**. – Andreas Sep 24 '19 at 23:07
  • @Andreas I want the values to be 0 and 1 but I need all the 0s together and all the 1s together, I need it to be sorted as well as have the numbers not go past the limit. I can't use Collections.sort because it is too expensive of a call. – mickeyvolmouse Sep 24 '19 at 23:08
  • @mickeyvolmouse - I hope the solution to [this question of yours](https://stackoverflow.com/questions/58596693/sum-of-two-long-values-returns-negative-value/) worked for you. Do not forget to accept the answer so that future visitors can also use the solution confidently. Check https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work to learn how to do it. Feel free to comment in case of any doubt/issue. – Arvind Kumar Avinash May 29 '20 at 21:11

3 Answers3

1

Since you don't want the numbers to increment, don't do the inL.get(i-1) + part.

To get better randomness, don't create a new Random object inside the loop.

To get the randomly generated numbers in sorted order, call sort() before returning.

Which means you code should be:

public static void randomSortedLimited(ArrayList<Integer> inL, int inHowMany) {
    int limit = (int) (Math.log10(inHowMany));
    Random random = new Random();
    inL.clear();
    for (int i = 0; i < inHowMany; i++) {
        inL.add(random.nextInt(limit));
    }
    Collections.sort(inL);
}

UPDATE: From comment:

I can't use Collections.sort because it is too expensive of a call.

Instead of add the random numbers to the list as they are generated, count them instead, and add the afterwards. Since there are only limit distinct integers, you can use an array of counters:

public static void randomSortedLimited(ArrayList<Integer> inL, int inHowMany) {
    int limit = (int) (Math.log10(inHowMany));
    
    // Generate and count random numbers
    Random random = new Random();
    int[] count = new int[limit];
    for (int i = 0; i < inHowMany; i++) {
        count[random.nextInt(limit)]++;
    }
    
    // Build list of random numbers in ascending order
    inL.clear();
    for (int i = 0; i < limit; i++) {
        Integer number = i; // autobox once
        for (int j = 0; j < count[i]; j++) {
            inL.add(number);
        }
    }
}

Sample Output with inHowMany = 1000, for both solutions above

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247
0

This should work:

    public static void randomSortedLimited(int inHowMany) {

        ArrayList<Integer> inL = new ArrayList<Integer();
        int limit = (int) (Math.log10(inHowMany));
        //System.out.println(limit); added to make sure limit is calculated properly
        inL.add(0);
        for (int i = 1; i < inHowMany - 1; i++) {
            inL.add(i, (int)(Math.random() * (limit - inL.get(i - 1)) + inL.get(i - 1));
        }
    }
GitPhilter
  • 171
  • 9
  • This sort of works, but for 100 I get one 0 and the rest are 1s or for 1000 I get one 0 and the rest are 2s is there a way to make it more even? – mickeyvolmouse Sep 24 '19 at 23:06
  • Of course there are many more ways to do this...one has been posted after my answer by Andreas. Can you think of any other way to do this? It is a good exercise to think about it... – GitPhilter Sep 24 '19 at 23:17
  • Is there a way to do this with only one loop? Or do you have to do multiple if you want to have different values? – mickeyvolmouse Sep 25 '19 at 01:13
-1

Check what Math.log (your expression and type cast) returns when applied to 10 and 100 respectively... And nextInt returns between 0 and one less than its argument (what the log expression is).

Håkan
  • 154
  • 6
  • Which OP seems to fully understand, because with input 10 (log = 1), OP expect all 0's, and with input 100 (log = 2), OP expects only 0's and 1's, and with input 1000 (log = 3), OP expects 0's, 1's, and 2's. This question does not appear at all to be about a confusion with how `log` works. – Andreas Sep 24 '19 at 23:04