This question already has answers here:
Generating Unique Random Numbers in Java
(21 answers)
Closed 8 years ago.
I am doing something where I have to choose a couple random numbers, without choosing the same number again. I have tried many ways, but they will not work. I checked if the random number exists in my int[], and reset the int to another random, but what is that other random also exists, I tried fixing that but I ran into problems.
Here's my current code:
p.sendMessage("debug over max");
Random r = new Random();
for (int i=0;i<max + 1;i++) {
int ran = r.nextInt(arenaAmount);
if (ran == 0) ran = 1;
arenas[i] = ran;
}
Thats what I have so far,
so how can I make sure it doesn't have the same number. If there is another thread already please link me to it.
Thanks, Joey.
A simple solution would be to add the already generated numbers to a Set and generate random numbers until you hit one that isn't already in that Set.
But that's probably not a very good solution, check the accepted answer here for a thorough explanation.
As mentioned by Giovanni Botta in the comments, here's another simple solution that's probably better than the Set based one.
make a arenas a Set
Random r = new Random();
int ran = r.nextInt();
while( ! arenas.add(ran) ) {
ran = r.nextInt();
}
add will fail on an attempted re-entry of a value.
You could create a list of integers from 1 to maxValue, shuffle it and get the numElements first elements:
List<Integer> shuffledList(int maxValue, int numElements) {
if (numElements >= maxValue) {
throw new IllegalArgumentException("The number of elements in the list must be less than maxValue.");
}
List<Integer> numbers = range(1, maxValue);
Collections.shuffle(numbers);
return numbers.subList(0, numElements);
}
List<Integer> range(int from, int to) {
List<Integer> numbers = new ArrayList<>(to - from);
for (int i = from; i < to; i++) {
numbers.add(i);
}
return numbers;
}
This way, you are sure to get different numbers without the Set overhead. Making a call like shuffledList(10, 5) would, for example, return a list like [8, 7, 5, 1, 2], with 5 elements, where the smallest possible element is 1 and the greatest possible element is 9.
Also, if you are using Java 8 you can discard the range function and do this instead:
List<Integer> numbers = IntStream.range(1, maxValue)
.boxed()
.collect(Collectors.toList());
Related
This question already has answers here:
How can I generate a list or array of sequential integers in Java?
(9 answers)
Closed 5 years ago.
I am relatively new to Java programming and am trying to create an array with values from (2017 - 3017).
I was wondering if there is a way to create an array and have it pre-filled with these values so instead of doing:
int[] anArray = {2017, 2018, 2019, 2020... 3017}
which seems extremely long-winded, I can simply define a range of integers I wish to add to the array.
I know there are similar question to this one on the site, however none of them have answers that help me.
Thanks!
Edit: I forgot to mention I am using Java 7 and therefore cannot use IntStream.
How about this:
int[] anArray = IntStream.rangeClosed(2017, 3017).toArray(); //closed includes upper bound
Java 7 would simply require a loop to fill the array:
int min = 2017, max = 3017;
int count = max - min + 1; //we're including upper bound
int[] anArray = new int[count];
for (int i = 0; i < count; i++, min++) {
anArray[i] = min; //reused and incremented min
}
Well it is answered. But just to point out another way in java .. you can count the number of integers that will be coming and use iterator to fill the array.Let me know if you have any doubts in this In short I am saying to do like the following:
int arr[] = new int[1001];
for(int i=2017;i<=3017;i++){
arr[i-2017]=i;
}
This question already has an answer here:
Finding all the number combos in array that add up to input number
(1 answer)
Closed 6 years ago.
I'm currently working on the following question from a interviewing book:
You are given a random array of 50 unique integers ranging from 1 to 100 inclusive. Write a method using Java that takes in a positive integer as a parameter and returns an array of all the number combinations that add up to that value.
For example, given an array of integers [3,6,1,9,2,5,12] and being passed the integer value 9, you would return [[3,6],[6,1,2],[9],[3,1,5]]. Order of returning the results in the array does not matter, though you should return unique sets (ie. [6,3] and [3,6] are the same and only one should be returned). Also, the individual results should be in the order they are found (ie [6,1,2] should be returned, not [1,2,6]).
I've made decent progress on it, but I fear I may solving this the wrong way.
import java.util.*;
public class findCombinations {
public static void main(String[] args) {
int number;
int[] list = new int[10];
Scanner reader = new Scanner(System.in);
//fill the array
for (int i = 0; i < list.length; i++) {
number = (int)(Math.random() * 10) + 1;
list[i] = number;
for (int j = 0; j < i; j++) { //remove duplicates
if (list[i] == list[j]) {
i--;
break;
}
}
}
Arrays.sort(list);
//test output
for (int i = 0; i < list.length; i++) {
System.out.println(list[i]);
}
System.out.println("Enter a number: ");
int input = reader.nextInt();
ArrayList<Integer> trimmedList = new ArrayList<Integer>();
//cut out the numbers that are impossible to use
for (int i = 0; i < list.length; i++) {
if (list[i] <= input) {
trimmedList.add(list[i]);
}
}
//test output
printList(trimmedList);
ArrayList<Integer> comboList = new ArrayList<Integer>();
System.out.println("Finding combinations...");
for (int i = 0; i < trimmedList.size(); i++) {
int current = trimmedList.get(i);
if (current == input) { System.out.println(current); }
else if (current < input) {
comboList.add(current);
if (isCombo(comboList, input)) {
printList(comboList);
}
else { continue; }
}
else { continue; }
}
}
public static boolean isCombo(ArrayList<Integer> list, int input) {
ArrayList<Integer> combo = new ArrayList<Integer>();
int sum = 0;
for (int i : list)
sum += i;
if (sum == input) { return true; }
else { return false; }
}
public static void printList(ArrayList<Integer> list) {
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
}
}
I know this is incomplete but I wanted to ask if anyone had any suggestions or improvements I could make on this? I sorted my list and trimmed out all the integers that won't possibly be used, but now the hard part is finding all the combos.
There are many different approaches to solve this problem, each with their own merits, so I wouldn't worry too much about whether your answer is the 'right' one or not...so long as it actually solves the problem! Also, an interviewer will likely be more interested in your thought-process, and the strategies you use, rather than a 100% perfect solution written in the span of a few minutes on a whiteboard.
Here's a couple of things to consider:
As you noticed, you can immediately eliminate any integers larger than your target value.
You're essentially generating arbitrarily-sized subsets of your starting array—so Set is likely the most useful data type to work with. {2, 3} and {3, 2} should be seen as identical when you're generating your response set.
Integer partitioning is an NP-Complete problem. It's hard. I think you've taken the correct approach of starting with the array, rather than with the target value.
There are many algorithms for generating combinations of integers from a larger set. Check out this SO answer for a few of them. You can generate k sized combinations from your (already-filtered) starting set, for k from 1-50.
Actually...there are more direct ways to get the power set of your starting set. Consider the inherent structure of a power set (shown below). By enumerating a few examples, you'll notice a natural recurrence in your strategy for identifying the subsets.
As you're generating these combinations, discard any whose elements don't sum to your target value.
Image Source: https://en.wikipedia.org/wiki/Power_set
Since this is a learning exercise, you will benefit most if you can solve this for yourself. So ...
Hints:
Sorting the numbers first is on the right track
I would use recursion to iterate the solutions. Given a partial sum, only numbers less than a certain number are possible candidates to be added to the sum ...
Work out the algorithm in your head >before< you start coding it.
And I agree with what #nbrooks says on the topic of what the interviewers are looking for. You need to be able to think ... and explain your thinking to the interviewer ... at the algorithmic level. That is what will distinguish the excellent candidates from the ordinary ones.
I realize generating your array of random numbers is not part of the problem statement, but I think your difficulties begin here.
First of all, use a Set<Integer> type collection to collect your generated numbers; break when the set reaches the desired size. If generated order is important, use a LinkedHashSet.
Set<Integer> origSet = new HashSet<Integer>(); // fill with random numbers
At some point, you have a list of numbers for which the order matters. Maintain this list as a List<Integer>. The list preserves the order of your original list so that you can produce the number combinations in the right order (i.e., 6 precedes 1, 1 precedes 2).
List<Integer> origList = new ArrayList<Integer>(origSet); // use indexOf method to find index of a number
You create a second list that is sorted; this list is the one used by your recursion algorithm.
List<Integer> sortedList = new ArrayList<Integer>(origList); // sort this
You don't need to trim the list because a recursive algorithm will trim any branch with no feasible solution.
A recursive algorithm can generate the combos in fewer lines of code. Reordering takes a few more lines.
This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
Closed 7 years ago.
So I am generating random coordinates on a given grid that contains x number of rows and y number of columns. Let's say I want to generate 25 random numbers on a 8 by 6 grid.(8 columns, 6 rows)
I wrote piece of code like this and it is only partially working because this code does not excludes duplicates:
int intputRows =6;
int inputColumns=8;
Random randomNumGenerator = new Random();
for(int i=0;i<25;i++){
int randomRows = randomNumGenerator.nextInt(inputRows);
int randomColumns = randomNumGenerator.nextInt(inputColumns);
}
My question is, how do I avoid to generate duplicate numbers? I understand there are ways like put those in a List structure and shuffle, but could I done it with Random generator?
Just use a Set:
int intputRows =6;
int inputColumns=8;
HashSet<Integer> set = new HashSet<>();
Random randomNumGenerator = new Random();
int temp;
for(int i=0;i<25;i++){
temp = randomNumGenerator.nextInt(inputRows);
if(set.add(temp))
int randomRows = temp;
temp = randomNumGenerator.nextInt(inputRows);
if(set.add(temp))
int randomColumns = temp;
}
You still have to implement an else, in case it already exists, but I just gave you the idea.
Simple add the numbers to a Set, for example a HashSet, which cannot contain duplicate values, until your Set hat the desired length.
Set<Integer> randomNumbers = new HashSet<Integer>();
while(randomNumbers.size() < 25) {
randomNumbers.add( randomNumGenerator.nextInt(inputRows) );
}
Of course some checks would be nice to test that there is a chance that the code will finish, etc.
I want to ask how to generate a random number in java , i know it is done by random.nextint() but i want to check if the number is not what i wanted then it should be rejected and a new random number should be generated .
I want something like this :
Integer[] in = {1,2,3,4,5};
int a = new Random().nextInt(10);
for(int i=0;i<in.length ;i++)
if(a==in[i])
//new random number
if the number is present in the above array (in) then new random number should be generated
Just put it in a do-while loop:
int a;
do {
a = new Random().nextInt(10);
} while (Arrays.asList(in).contains(a));
I would avoid not generating a number you didn't want in the first place.
You can do either
int a = random.nextInt(5);
if (a > 0) a += 5;
or use a selection
int[] valid = { 0, 6, 7, 8, 9 }; // 0 to 9 but not 1,2,3,4,5
int a = valid[random.nextInt(valid.length)];
Simply call the method again. That is, if the number generated fits the if criteria then call a = new Random().nextInt(10);
Or, if your for loop ever regenerates a random number, you could just have the if statement do nothing ex: if(xyz){}; which of course would be pointless, and I think the original solution is probably what you seek.
To avoid any loops and retrying, try this:
int [] in = {1,2,3,4,5};
// generate integers from 0 up to the size of your array of allowed numbers:
int index = new Random().nextInt(in.length);
int a = in[index]; // use the random integer as index for your array of allowed numbers
I'm trying to write an alternative version of the Random().nextInt() method that doesn't generate the same number two times in a row. I searched on StackOverflow but, curiously, the methods I found managed to work only when the range of the random values was sufficiently great (greater than 4 if I'm not being wrong).
To be more specific, I'm trying to generate an int[] of 6 random integers k (0 <= k <= 3) in which every element is different both from its successor and predecessor.
Thank you very much.
Possible solution: after generating the next random number, compare it to the previous one. If they are the same, discard the last one and generate a new one.
Here's my quick pseudocode version for you
Generate a random number
Compares that number with the previous number.
If it is the same then repeat steps 1 and 2.
If it is different store the number.
return the number
Note: be sure to not have a range of numbers with only one integer inside or else you might get stuck in a loop.
There is certainly a better/different way of doing this.
Thinking about what I'd do in Python. Something like based on the range you want the ints to be in e.g. 1.100 create an arraylist of those integers and then access the list at random and pop/remove the element from the list. Or create a static list of random numbers then cast to a set to remove duplicates, then wire the nextInt() up to the set.
I've come up with this:
private ArrayList<Integer> MyRandom(int size, int k)
{
ArrayList<Integer> array = new ArrayList<Integer>();
array.add(new Random().nextInt(k));
while (array.size() <= size)
{
int val = new Random().nextInt(k);
if (array.get(array.size() - 1) != val && (!(val == 1 && array.get(array.size() - 1) == 0)) &&
(!(val == 0 && array.get(array.size() - 1) == 1))) array.add(val);
}
return array;
}
Random rand = new Random();
int last = rand.nextInt(3);
for(int i = 0; i < k; i++) {
last = (last +1 + rand.nextInt(2)) % 4
array.add(last)
}
Advantage: you really only generate O(k) values...