• Post Reply Bookmark Topic Watch Topic
  • New Topic

Choose random element from array  RSS feed

 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everybody,

im trying to selected a random element from an array and insert it into another array. i tried searching the forums but i had no luck. would be much appreciative if someone could point me in the right direction.

what i have so far is a bunch of arrays with 10 random numbers in each. then i want to select 1 number from each array to put into a new array.

 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Are you trying to simulate some kind of lottery drawing machine? Do you know that random cannot guarantee uniqueness?
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, try using the java.util.Random class instead of Math.random
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i understand that there is a chance that i will select a double at some point. but i will write the code to reselect another number if it equals a number already in the array, once i understand how to select from the first lists into the final list
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:Also, try using the java.util.Random class instead of Math.random


i dont know how to use this properly

 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Search this forum for my posts and keywords “Random nextInt”. That will find 19 hits including this thread where there is discussion about ways to choose random numbers.
If you are removing things from an array, try replacing the element found with a nonsense number e.g. −1. Then you can wrap your selection instructions in a loop:-
do {find random element} while (element != -1);
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks for the help. i have finished it now. would appreciate any feedback. also i wanted to do a clear screen but all i could get to work was either adding a bunch of blank lines or backspacing everything.

 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A proper mental model can help you simplify this program tremendously. It seems to me that having all those lists is unnecessary. If all you really want to do is randomize a selection from a set of numbers, then you can do this instead:

Put a range of unique numbers in a List<Integer>. You don't need to randomize this yet so just add them to the List in order. You can use a for loop to do this.

Then create a Random object.

Pass the List and Random to Collections.shuffle(). This will randomize the order of the numbers you put into the List. The method is called shuffle for a reason, duh.

Then you can get the first N numbers from the list. Or you can generate a random index that will allow you get at least N numbers from the list starting from an arbitrary position, if you want. I don't think that's necessary but it's another twist you can throw in if you want.

Then, using the same List and Random, call Collections.shuffle() again and repeat the selection process. Do this as many times as you want/need to.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If your goal is to have a final list of random and unique numbers, your algorithm doesn't guarantee that. All those gyrations make it less likely to have repeats but there's still a possibility of getting repeats in non-adjacent positions. Think about it, your while loops on lines 92-112 only look forward at the next number. There's no guarantee that later numbers won't end up being the same as a previously set "final" number. You can see this by reducing the range of possible values (your MAX) from 80 to say 12.

If you follow the scheme I suggested in my last reply, you won't have this problem because by adding unique numbers to your collection from the start and only selecting numbers from that set, you'll never get repeats. One caveat is that your selection cannot be at random. Just imagine a standard deck of cards. They come out of the box in order. All the 52 standard playing cards are unique. Then you shuffle the cards. Shuffling seven times is supposed to guarantee randomness. I believe the Collections.shuffle() algorithm actually does that under the covers for you. Then you deal out the cards, in order, from the top of the deck. You have to do the equivalent in your program.

Random is not truly random, which is why it's called a pseudo-random number generator (PRNG). But there's really no point in trying to randomize something that's already randomized. Just like there's nothing much gained from shuffling a deck of cards more than seven times.
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For a List of any size, the number of possible combinations will rapidly exhaust the randomisation of shuffle; for lottery numbers there are 49! permutations. Maybe the random removal technique would therefore be better. Or would you say that at the beginner's stage nobody will notice?
I know some people will say this is an advanced technique, but you can create a sequential array or List with an IntStream. It has two methods which give a sequential Stream of a predetermined size, but you need to read the documentation carefully. An IntStream also has this method which creates an array:-Getting a List is slightly harder. You want to change the IntStream to a Stream<Integer> because you can't put ints into a List. Now we know that changing an int to an Integer is called boxing conversion←Beware: that link may be hard to read. So the method to change an IntStream to a Stream<Integer> is called boxed().
Every Stream has a method called collect(Collector), but if you look for a Collector, you find a link to the Collectors class, which has a method which returns a Collector ready‑made. If you follow all those links, you will probably find an example rather like what follows:-I think I have spelt all those method names correctly.
You can get an IntStream out of a Random object instead, if you prefer. Read about its ints() method (which comes in four versions). You will have to limit the size of the Stream with its (would you believe) limit() method, but call distinct() first to prevent duplication.Change line 6 to match lines 2‑3 of previous code block to get a List instead. Change the argument in line 5 and you can get your 7 lottery numbers ready‑made as an array
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . . I believe the Collections.shuffle() algorithm actually does that under the covers for you. . . .
Don't know about the algorithm, but Joshua Bloch suggests that shuffle() isn't random enough for 52 cards. Can't remember whether it is in Effective Java or Java Puzzlers, but it sounds more likely to be the latter.
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks for the advice. the only reason i had lots of lists filled with random numbers and then taken random numbers from the list was hoping to make it more random.
im in the process of following your advice. i'v only used array lists once and never used collections. so im still trying to understand it all but im getting there.
i'll keep you updated on my process.
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie i have never even touched on anything have you just told me before. but i will take it in, have a look and try to implement it. i only started writing code 12 weeks ago, but i did miss a few weeks in between so im still very new. thanks for the help
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not sure I can reconcile what I just read in the documention for shuffle and what you said about quickly exhausting the randomness; will look into this more when I have time and am so inclined. It doesn't look like the algorithm used by shuffle does the seven iteration minimum under the covers though. I do like the ints() stream approach you suggested though, makes the code a lot more functional than imperative. Learning something new on a Saturday morning, I'll give a cow for that. 
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, while the bacon is sizzling in the pan, I pulled up Bloch's Java Puzzlers book on Safari Queue and looked up the Lost in the Shuffle item. His solution for avoiding the problem you mentioned is... wait for it... To use the Collections.shuffle() method!

The flawed shuffle implementation that Bloch refers to in the book is the example naive implementation, NOT what is implemented in the library, which he confirms is a fair random shuffle.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
matthew reid wrote:thanks for the advice. the only reason i had lots of lists filled with random numbers and then taken random numbers from the list was hoping to make it more random.
im in the process of following your advice. i'v only used array lists once and never used collections. so im still trying to understand it all but im getting there.
i'll keep you updated on my process.

Streams are a little harder to wrap your head around so I suggest you start with Collections.shuffle() since we've already established that it doesn't suffer from the problem Campbell was warning about.
 
Piet Souris
Master Rancher
Posts: 2044
75
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:(...)


This is in practice good enough. For a range of 1 to N, having already drawn a unique set of K elements, the average number of drawings to get K + 1 elements = N / (N - K). In the extreme, going from 49 unique numbers to 50 unique numbers from the set of 1-50 takes on average 50 additional tries. But the average number of tries to get all 50 out of 50 is only about 225, so as said, good enough. The general formula is a tad complicated, but it is quite easy to simulate this process.

If you want to eliminate all the extra drawings: we all kow the classic trick of drawing an element and then switch that element with the last available element. Now, it is quite easy to get that method in a stream as well, but it may be a bit advanced for a beginning programmer. For those interested:
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
matthew reid wrote:. . . never even touched on anything have you just told me before. . . .
Lots of people think Streams are an advanced feature of the language, but I am not convinced. I think that the simpler uses of Streams are probably a basic form of programming in Java8. It won't work in Java7.
If you haven't used Lists, stick to the arrays. In the case of an IntStream, the code is simpler.
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for the cows, whoever it was (probably two people). And sorry that I forgot exactly what Bloch had said.
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hey everybody, i haven't had time to read all those posts yet but finished making a simplified version based on what Junilu Lacar told me. it is much more simple. i have had it working but it  did have a chance to duplicate so i made it remove the selection when it was put into the finishPool but then i had a runtime error after running it a few times because the array wasnt long enough due to removing elements. so i added a sorter to re organise. and then i wanted to fill in the gaps with the original number then randomise it again but i dont know what i should put in. the way i did would work for a normal array but not arrayList.

 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
matthew reid wrote:hey everybody, i haven't had time to read all those posts yet but finished making a simplified version based on what Junilu Lacar told me. it is much more simple.

Well, you could've fooled me...

That's not exactly what I had hoped you'd come up with from what I told you.

First thing: Main is a Pain. Putting all your code in main() basically turns your program into a script, which is to say, that's not how Java programs are supposed to be written. Heck, that's not even how good scripts are written.

If you followed the advice in our wiki about how to make main() small, I'd expect something like this:


Notes:

1. The main() method is now a single line of code.

2. The algorithm that I told you about is encoded in the run() method. That code is all high-level and abstract; there are no details in it, just a description of the intent of the program.

3. Multiple small methods are called to get the job done. Those methods are given names that reflect what they do. This is what's referred to as giving methods intention-revealing names.

4. The methods are small and the code in them does the singularly-focused thing the method name says it does.

5. The methods are arranged from top to bottom in order of abstraction. Towards the top of the code, the methods are more high-level and abstract. As you go further toward the bottom, the methods get more detail-oriented.

6. The declared type of the pool variable is List<Integer>, not ArrayList<Integer>. I alluded to this in my first reply to you but you didn't catch it. The List type is an interface and is more general. The ArrayList type is a concrete implementation of List. The difference is like referring to a Car (the general type) versus a 2017 Ford Mustang GT (a specific car, a concrete implementation of "Car"). Good programming form is to declare variables as the general type so that if you decide to change the kind of implementation type you want to use later on, you can do that on the one line where you have to reference the actual/implementation type, when you're creating the object. In the code above, you'll notice that would be line 21. No other line of code references the actual type of ArrayList except this one.

7. The pickWinners() method on lines 34-36 can be literally that small. You really only need one return statement to complete the method. Look over the java.util.List API documentation to see if you can find a method that will let you return a subset of a List. That line of code would basically implement what I described before: "When you've shuffled the numbers, you can use the first N numbers as the winning number." If you want to implement this: "You could also pick N numbers starting from an arbitrary part of the shuffled list" with a few more lines of code (no more than 2 extra lines).

8. You might end up with more lines of code if you structure your program this way but look how much more organized and readable it is.

I hope you get a better idea of what you should be shooting for in terms of program organization and structuring: small focused methods, abstract high-level methods calling out to low-level detail-focused methods, clear and expressive names that reveal intent, small main() method. This is how a Java program should be written.
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have been getting déjà  vu about shuffling. So I searched, and lo and behold, we discussed something similar last year.
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
wow Junilu Lacar there is now way i could have done that. i havent learnt any of that at all yet. but thanks for the help ill try to use it in the future. anyone know any good websites to learn from. i have searched google but there is so many. im only a beginer so i dont understand alot of the stuff i find. i need more then just reading about the code and more about how it is actually used in a program
 
Paul Clapham
Sheriff
Posts: 22841
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
matthew reid wrote:anyone know any good websites to learn from. i need more then just reading about the code and more about how it is actually used in a program


The Java™ Tutorials

And yes, you're right. Reading about the code is a start but what I've found in the past is that starting with somebody else's code, and tinkering with it to see what I can do, is a good way to get familiar with things. And the Oracle tutorials which I linked to do have code which you can download and tinker with.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
matthew reid wrote:wow Junilu Lacar there is now way i could have done that. i havent learnt any of that at all yet.

You must not have noticed but you did do some of it. The code in the initializePool() method is only a slight modification of your code. The shuffle() method is a single line of code that we've already discussed in this thread.

You already know the general approach from your past experience in problem solving.  Have you ever solved a jigsaw puzzle? Worked through a math problem? Solved a crossword puzzle? Assembled some Build-It-Yourself furniture you bought from IKEA? Built something out of Lego bricks? Made a sand castle at the beach? All of these have one thing in common with programming: You have to attack the problem one little bit at a time and systematically work your way towards the full solution.

There's another name we used to attach to the approach of putting everything in one method like main(): The Big Bang. That is, trying to write the entire program at one go. This just doesn't work for anything but the tiniest program like a Hello World. The sooner you realize this, the sooner you can change the way you think about problems and problem solving and switch to this layered and incremental approach to writing a program to solve a problem.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@OP: There's one more thing that strikes me about your comment that there's no way you could do what I showed. I understand that you meant that in terms of your learning progression, how you haven't been taught to solve problems like that or how you might not even know enough of the Java language.

This reminds of a scene in the movie Jack Reacher where the bad guy, "The Zec", gives a hired goon a choice: bite off his fingers like the Zec had to do in order to survive, or get executed on the spot. The guy ends up getting shot because he just can't bring himself to bite off his fingers. Afterwards, the Zec muses, "I just don't understand. They always choose death."

Again, I understand that it's not reasonable to expect a beginner to write programs the way that example was written. I'd be very pleasantly surprised if you did, but I totally understand how you end up writing what you did instead. However, I don't understand how you could see a much better alternative and still choose the more difficult but arguably more expedient way to do something. It may take you a while to learn how to organize your thoughts and systematically attack a problem and then write a program that reflects what's going on in your head. Now that you know there's a better way, however, I hope you won't still continue to choose the gunshot to the head approach.
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Junilu Lacar

i normally write using methods but i could figure how to put the array list into the method. so the easiest way i could see was just put it all in the main. using the arraylist in that coding was the first time i had used arraylist. in the university course i took for beginning programming, i realized now they didn't even cover all the basics. but im learning and im grateful for the help. you have made me think about a different way to approach it instead of my first attempt which was a massive amount of unnecessary code. one of my problems is i, at first normally over complicate things.
 
Knute Snortum
Sheriff
Posts: 4287
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i normally write using methods but i could figure how to put the array list into the method.

Assuming you meant "couldn't" (I do that all the time, by the way) here is how you would pass an ArrayList (or anything) into a method:
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
matthew reid wrote:my problems is i, at first normally over complicate things.

That's everbody I know, including myself. The trick is not to go with settle for your initial ideas (yes, plural) because they are based on your initial understanding of the problem and solution which most of the time is incomplete and/or flawed. The more you go over what you write and see what's too complicated then simplify it, the better you understand.

There's a corollary to Murphy's Law that says, "You'll always find what you're looking for in the last place you look." Well, the trick here is to look in the right places so you find it sooner. Similarly, you want to fix the right things in your program so you can make it better quicker. In programming as with Murphy, most of the time your best design is the last one you try.
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote:
i normally write using methods but i could figure how to put the array list into the method.

Assuming you meant "couldn't" (I do that all the time, by the way) here is how you would pass an ArrayList (or anything) into a method:


I tried using what you wrote but its not working for me i get a compile error. i also had to add static to the methods or i get compile error.



\FinalLottery.java:11: error: cannot find symbol
populatePool(pool);
^
  symbol:   method populatePool(List<String>)
  location: class FinalLottery

Note: G:\FinalLottery.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 errors
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When the compiler tells you it can't find a symbol, you probably misspelled something.  Look at the name on line 11 carefully. Then look carefully at what you wrote on line 13.  IDEs that have code completion will help you avoid these kinds of problems. On most IDEs, you just start typing a name then hit CTRL+Space or CMD+Space and a list of matching candidates will be shown.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, since pool is declared as List<String> on line 10, the parameter that you declare on line 13 should be List<String> instead of just List. You'll probably get some kind of warning from the compiler about that, too.
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . .  IDEs that have code completion will help you avoid these kinds of problems. . . .
As an alternative, if you hover your mouse on the red underlining or click the red mark on the left, you will probably get a list of possible corrections including spelling corrections.
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . . "You'll always find what you're looking for in the last place you look." . . . your best design is the last one you try.
There is of course a good scientific explanation for that; once you have found the lost article, you stop looking in other places. Once you have found a really good design you will stop looking for other designs
 
matthew reid
Ranch Hand
Posts: 38
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
what do you use to write code. i use textpad. i have netbeans to but dont know how to use it yet
 
Campbell Ritchie
Marshal
Posts: 56587
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stick with TextPad. Don't try NetBeans or other IDEs until you are more experienced. My favourite if I use Windows is Notepad++.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!