I have an ArrayList which is defined outside the main method, just inside the class StringRandomize:
public static ArrayList<String> countries = new ArrayList<String>();
I also initialized a random object.
Random obj = new Random();
Then I add some Strings to the list:
StringRandomize.countries.add("USA");
StringRandomize.countries.add("GB");
StringRandomize.countries.add("Germany");
StringRandomize.countries.add("Austria");
StringRandomize.countries.add("Romania");
StringRandomize.countries.add("Moldova");
StringRandomize.countries.add("Ukraine");
How do I make those strings appear randomly? I need output like "Germany", "Moldova" and so on.
I need exactly the strings in the output, not their IDs.
Thanks for your help.
You probably want to use something like:
countries.get(Math.abs(new Random().nextInt()) % countries.size());
Or, to avoid creating a new Random object every time, you could use the same one:
Random gen = new Random();
for (int i = 1; i < 10; i++) {
System.out.println(countries.get(Math.abs(gen.nextInt()) % countries.size()));
}
I would use Collections.shuffle(countries) if you wanted a randomized List.
Else a new Random().nextInt(max) like Flavius described.
static void shuffleArray(string[] ar)
{
//set the seed for the random variable
Random rnd = ThreadLocalRandom.current();
//go from the last element to the first one.
for (int i = ar.size()- 1; i > 0; i--)
{
//get a random number till the current position and simply swap elements
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
This way you shuffle the entire array and get the values in a random order but NO duplicate at all. Every single element changes position, so that no matter what element (position) you pick, you get a country from a random position. You can return the entire vector, the positions are random.
Related
I have a problem for an online course I am doing. The question is:
Given an Integer x, write a program which generates random numbers between x and 0 until each number in this range has been generated at least once. Once all numbers in this range have been generated, the program should display the numbers which were generated.
I have written a program which I thought would solve this but am having problems with the checking if a number is in the range. Here is my code so far:
public static void main(String[] args) {
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.remove(temp);
}
}
}
}
My idea was to first create two arraylists. The first would hold all numbers between 0 and the given x. The second would contain the random numbers generated. I then fill the range arraylist with the range between 0 and x. My While loop then checks this range list to see if it is empty. If not, it generates a random number, adds it to my second arraylist. I then check if this number is in the range arraylist - if it is it removes it and carries on. The problem I am having is it is running into IndexOutOfBoundsException after a few goes. I think this is because I am removing the generated numbers from the arraylist. Can anyone help me with fixing this
EDIT: I cant use any collections or other APIs. This part of the course is mainly about using Arrays and loops etc, not advanced Java stuff.
remove is an overloaded method, there is remove(int) which removes the item at the index specified and there is remove(T) which removes the first object int the list that is equal to the argument you passed in
since you passed an int to the method not an Integer, the first method is chosen
the simpliest modification to your code is replacing range.remove(temp); with range.remove(range.indexOf(temp)); or range.remove((Integer)temp)
also you have to call generator.nextInt(x+1); or else the program will be stuck in an infinite loop
You can just replace range.remove(temp); with range.removeIf(t -> t == temp);
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.removeIf(t -> t == temp);
}
}
OR You can use Iterator to remove from the List
for (Iterator<Integer> it = range.iterator(); it.hasNext(); ) {
Integer obj= it.next();
if (obj == temp) {
// Remove the current element from the iterator and the list.
it.remove();
break;
}
}
One more issue in your logic
int temp = generator.nextInt(x-1); The random number you are generating doesn't contain all the numbers. It should be int temp = generator.nextInt(x+2);
Hope the below will meet your requirement.
Random random = new Random();
int x = 3;
List<Integer> range = new ArrayList<>();
for(int i = 0; i <x+1; i++) {
range.add(i);
}
List<Integer> list = new ArrayList<>();
while (!list.containsAll(range)) {
list.add(random.nextInt(x + 1));
}
System.out.println(list);
While I was trying to create a small GUI in Java, I've stumbled onto this small issue with arrays.
I've tried inserting Random Integers into an one dimensional array, only to find out that the Random Integers won't get assigned.
//Declaring an Integer Array
int[] wuerfel = new int[2];
//It will loop once while assigning a random number to the array
for(int i = 0; i <= 1; i++) {
Random rand = new Random(6);
int zahlen = rand.nextInt(6) + 1;
wuerfel[i] = zahlen;
}
System.out.println(Arrays.toString(wuerfel));
I expect the output from the array to be a number between 1 - 6.
However, I keep receiving [2,2] as a result every time I try to rerun.
The constructor call new Random(6) doesn't do what you think it does: 6 is the seed, rather than the range of possible outputs. Therefore it will produce the same output every time.
Possible solutions:
Use the no-argument constructor for Random() instead, which will give it a different seed each time.
Declare and initialise rand outside the loop, with or without an explicit seed.
Use Math.random().
So in your code you set up a seed for your Random and you create new Random object every loop iteration so it just returns same number every time. If you use seed the documentation of Random class says :
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.
In your case you can get rid of seed value from your constructor or move Random class object creation outside of the loop :
public static void main(String[] args) {
int[] arr = new int[2];
Random rand = new Random();
for(int i = 0; i <= 1; i++) {
int zahlen = rand.nextInt(6) + 1;
arr[i] = zahlen;
}
System.out.println(Arrays.toString(arr));
}
Here I moved creation of Random instance outside of the loop so only one object is created and I am not passing seed to the constructor. I could pass the seed but in this case it is not needed as I don't need to create more instances of Random and I dont need them to generate same results.
*
int[] wuerfel = new int[2];
//It will loop once while assigning a random number to the array
Random rand = new Random();
for(int i = 0; i <= 1; i++) {
int zahlen = rand.nextInt(6) + 1;
wuerfel[i] = zahlen;
}
System.out.println(Arrays.toString(wuerfel));
* try this one create Random object with passing parameter
This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
best way to pick a random subset from a collection?
(10 answers)
Closed 7 years ago.
I am trying to get this code to run without duplicates but am having no success researching this area.
Its the start of a question I am doing which will ask the user to input the missing element. However, when I generate random elements I am getting duplicates
import java.util.Random;
public class QuestionOneA2 {
public static void main(String[] args) {
String[] fruit = {"orange", "apple", "pear", "bannana", "strawberry", "mango"};
Random numberGenerator = new Random();
for (int i = 0; i < 5; i++) {
int nextRandom = numberGenerator.nextInt(6);
System.out.println(fruit[nextRandom]);
}
}
}
There are many different approaches you can consider, depending on how flexible the algorithm should be.
Taking 5 random elements from a list of 6, is the same as selection 1 element from the list of 6 that you don't choose. This is a very inflexible, but very easy.
Another approach could be to delete the element from the list, and decrease the maximum random number. In this cause I would advice to not use a String[].
When you generate a random number, I suggest adding it into an array.
Then, when you generate your next number, do some sort of search (google for something efficient) to check if that number is already in the array and thus, has been used already.
If it is, generate a new one, if its not, use it.
You can do this by nesting it in a while loop.
Although, from what I can tell from your question, you would be better off just creating a copy of your fruit array using an ArrayList and then, when you generate a random number to select a fruit, simply remove this fruit from this new list and decrement the range of random numbers you are generating.
You can use a Set to validate if the random generated number is duplicate or not. You just have to keep generating randomNumber until you find a unique random and then add it to the Set to prevent the duplicates.
Here is a quick code snippet:
public static void main(String[] args) {
String[] fruit = {"orange", "apple", "pear", "bannana", "strawberry", "mango"};
Random numberGenerator = new Random();
/* Generate A Random Number */
int nextRandom = numberGenerator.nextInt(6);
Set<Integer> validate = new HashSet<>();
/* Add First Randomly Genrated Number To Set */
validate.add(nextRandom);
for (int i = 0; i < 5; i++) {
/* Generate Randoms Till You Find A Unique Random Number */
while(validate.contains(nextRandom)) {
nextRandom = numberGenerator.nextInt(6);
}
/* Add Newly Found Random Number To Validate */
validate.add(nextRandom);
System.out.println(fruit[nextRandom]);
}
}
Output:
mango
apple
strawberry
pear
orange
You can wrap int into 'Interger' and add it to Set. Set holds no duplicates so there will be only unique values in it. So then just check if a Set already has given Integer with Set.contains(Integer).
my personal solution :
private static int[] randomIndexes(int len) {
int[] indexes = new int[len];
for (int i = 0; i < len; i++) {
indexes[i] = i;
}
for (int i = len - 1, j, t; i > 0; i--) {
j = RANDOM.nextInt(i);
t = indexes[j];
indexes[j] = indexes[i];
indexes[i] = t;
}
return indexes;
}
See it in action : https://gist.github.com/GautierLevert/a6881cff798e5f53b3fb
If I understand you correctly, then you want to choose n-1 elements at random from a list of n elements. If yes, then I recommend to choose just one at random and take all the others.
Arrays.shuffle(fruit);
int notThis = numberGenerator.nextInt(6);
for(int i = 0; i < fruit.length; i++)
if(i!=notThis) System.out.println(fruit[i]);
Copy your array into List<String>, then shuffle it, then just pick elements one by one:
List<String> copy = new ArrayList<>(Arrays.asList(fruit));
Collections.shuffle(copy);
for (String f : copy)
System.out.println(f);
I think it will be easier using an ArrayList, and also controlling the generation of the random number as shown below.
import java.util.Random;
public class QuestionOneA2 {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("orange");
fruits.add("apple");
fruits.add("pear");
fruits.add("bannana");
fruits.add("strawberry");
fruits.add("mango");
Random numberGenerator = new Random();
int nextRandom;
for (int i = 0; i < 6 ; i++) {
nextRandom = numberGenerator.nextInt(6 - i);
System.out.println(fruits.get(nextRandom));
fruits.remove(nextRandom);
}
}
}
fruit.remove(fruit[nextRandom]);
Maybe, is it the remove sub-method?
I need to assign different number from 1 to 8 to JButton Array. But the elements of array has to be different.
Random random = new Random();
JButton[] number = {jButton1,jButton2,jButton3,jButton4,jButton5,jButton6,jButton7,jButton8,jButton9};
for(int i = 0; i<data.lentgh; i++)
{
number[i].setText(1+random.nextInt(9)+" ");
}
With this code, the elements of array can be different and sometimes some of elements can be same. I searched the internet but I couldn't find.
How can I fix this? Thank you.
You can do it without random()
for(int i = 0; i<data.lentgh; i++) // I think data should be replaced by number
{
number[i].setText((i+1)+"");
}
It is not necessary that random() will always generate different no. Most of the time you will get no. which is already generated.
Maybe you can use LinkedHashSet to store the random number and then later you can iterate over the set and set the text of the button.
Random random = new Random();
JButton[] number = { jButton1, jButton2, jButton3, jButton4, jButton5,
jButton6, jButton7, jButton8, jButton9 };
Set<Integer> set = new LinkedHashSet<Integer>();
while (set.size() != 9) {
set.add(1+random.nextInt(9));
}
int i = 0;
for (Integer s : set) {
number[i].setText(s + " ");
panel.add(number[i]);
i++;
}
I want to get n unique random elements from my array.
For example:
if n = 4;
I want to randomly get
array[0], array[3], array[7], array[2]
The problem is getting a random integer will lead to collisions easily (psuedocode):
for n times
{
r = generateRandomInteger within n-1
list.push(array[r]); //array[r] can be the same.
}
collisions abound, especially on small arrays.
What's a particularly elegant way to solve this?
You can use a Set instead of a List which will eliminate the duplicates. Accordingly you'll need to change your loop condition as well. Something like this
while set.size() is less than n
{
r = generateRandomInteger within n-1
set.add(array[r]); //if its the same, it won't be added to the set and the size won't increase
}
You can do this two way : i suggest you to use first one .
First by using SET :
for n times
{
r = generateRandomInteger within n-1
// you can use SET instead of LIST cause SET not allow duplication.
set.push(array[r]); //array[r] can be the same.
}
Second by using LIST :
for n times
{
r = generateRandomInteger within n-1
if(!list.contains(array[r]))
list.push(array[r]); //array[r] can be the same.
}
You can add all random ints to a list and generate a new random, till the list doesnt contains this random int. Thats not the best performance, but it works.
List<Integer> randoms = new ArrayList<Integer>()
for(int i=0; i<n;i++){
while(randoms.contains(r)) {
r = Random.nextInt(array.length-1);
}
randoms.add(r);
list.push(array[r]);
}
Using a Set is probably the best thing to do.
If you want unique elements from array (i.e. the values of array[]) then use R.J's solution. If you want unique indices:
while set.size() is less than n
{
r = generateRandomInteger within n-1
set.add(r);
}
foreach(r: set)
{
list.add(array[r]);
}
Be carefull if you want more elements then the length of the array, since you will get an infinite loop:
if(n>array.length)
{
print("Cannot get more then ... elements!");
return null;
}
int n = 4;
for (int i = 0; i < n; i++)
{
int index = RandomBetweenInclusive(i, array.length() - 1); //made up function
int temp = array[i];
array[i] = array[index];
array[index] = array[i];
}
//array values between indices 0 and n-1 will be random and unique values of array
What I usually do in this scenario is push all the items I want to select-from into a collection
var selectFrom = original.clone; // or build array
var selected = new collection;
Then I go about removing random elements in the selectFrom collection
for (i = 0; i < toSelect; i++)
{
var rndItem = selectFrom[ rand() * selectFrom.length ];
selected.add(rndItem);
selectFrom.remove(rndItem);
}
This way I select randomly from what remains and do not have to worry about clashes in random numbers / indexs.