Generating random distinct pair with no diagonals - java

I want to generate two random pair of integer with no duplicate in an array of length 8 and I don't want any pair in the same diagonal
public static int[] randomizer(int[] v){
int [] a= new int[8];
for (int i = 0; i < a.length; i++) {
a[i] = (int)(Math.random()*9);
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
i--;
break;
}
}
}
a[0] = v[0] ;
return a;
}
This is what I have done so far.

If I understood you correctly you want to generate two random sequences of integers with the length of 8 each. Both sequences should not have any number in common, so you want 16 unique random numbers.
Next comes the requirement with the diagonal part - I don't get it. Please specify it more precice, a small example would be nice.
Meanwhile let's solve the first part. Generating 16 unique integers is quite easy. You generate a random number and memorize it. If it was already generated before than reject it and try again. For a fast contains access and add you should use a HashSet. Let's take a look at the following snippet:
public static Set<Integer> randomUniqueNumbers(int amount, int upperBound){
final HashSet<Integer> numbers = new HashSet<>();
final Random rnd = new Random();
// Stop when generated enough numbers
while (numbers.size() < amount) {
final int randomNumber = rnd.nextInt(upperBound);
// Try to add it to the set.
// The method will do nothing if the number was contained already.
numbers.add(randomNumber);
}
return numbers;
}
The method will generate amount many unique numbers and store them in a Set<Integer> that can be iterated and used by your method. The numbers are between 0 (inclusive) and upperBound (exclusive) like with (int)(Math.random() * upperBound) you used.
Note that it is possible that the while-loop does not halt, for example when extremely unlucky or the given parameters contradict. If that is a problem you can count the number of unsuccessful tries and abort with break once it goes beyond a defined upper limit of tries.
You want 16 of those numbers and store them in two arrays of length 8 each. Here's is how you can do this:
final int[] firstSequence = new int[8];
final int[] secondSequence = new int[8];
// Exchange with the correct upperBound, I assume it is 9
final Set<Integer> numbers = randomUniqueNumbers(16, 9);
Iterator<Integer> numberIter = numbers.iterator();
// Fill the first sequence
for (int i = 0; i < 8; i++) {
firstSequence[i] = numberIter.next();
}
// Fill the second sequence
for (int i = 0; i < 8; i++) {
secondSequence[i] = numberIter.next();
}
I think that covers most of your question. Please specify more precise what is missing and I will update the answer.
Also note that randomUniqueNumbers(16, 9) can not halt. It will run forever since it is not possible to generate 16 different numbers out of {0, 1, 2, 3, 4, 5, 6, 7, 8} which are only 9 numbers. Also note that when both parameters are close it will be drastically faster to use another approach where you pre-define {0, 1, 2, 3, 4, 5, 6, 7, 8} and now just permutate this set and then iterate it, like Collections.shuffle(numbers) and then for(Integer number : numbers) { ... }.

Related

array with random ints but no duplicates and first number showing [duplicate]

This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
Closed 1 year ago.
This is probably already asked, but it is a little difficult for me to understand. I created a for loop to add random integers into my array, but when the integer is already in the array, restart the loop. But I keep on getting the same integers into the array + when there already is a duplicate, the array size increases. Does anyone know what I'm doing wrong?
Random r = new Random();
int[] tes = new int[5];
for (int i = 0; i < tes.length; i++) {
int q = r.nextInt(10);
for (int j = 0; j < i; j++) {
if (q == tes[j]){
i=i-1;
}
}
tes[i] = q;
System.out.println(tes[i]);
}
and the output:
If you want a collection without duplicates you should use a Set:
Random r = new Random();
int desirableSize = 5;
Set<Integer> uniques = new HashSet<>(desirableSize);
while(uniques.size() < desirableSize){
uniques.add(r.nextInt(10));
}
System.out.println(uniques);
The add method already ensures that a value is not added if it already exist on the set.
boolean add(E e)
Adds the specified element to this set if it is not already present (optional operation).
I have used HashSet, however if the insertion order is important for you, use instead LinkedHashSet:
As pjs have pointed out the aforementioned approach is good when:
desirableSize is much less than the pool size, but if the
desirableSize is a substantial proportion of pool size you're better
off shuffling the pool and selecting the first desirableSize elements.
Something as follows:
int start = 0;
int end = 10;
int size = 5;
List<Integer> collect = IntStream.rangeClosed(start, end)
.boxed()
.limit(size)
.collect(Collectors.toList());
Collections.shuffle(collect);
System.out.println(collect);
The rational is the following (quoting pjs):
With rejection-based schemes such as repeated attempts to add to a
set, the expected number of iterations is O(poolsize *
log(desirableSize)) with O(desirableSize) storage for the set.
Shuffling is O(poolsize) but requires O(poolsize) storage for the
shuffle. As desirableSize -> poolsize, shuffling wins on expected
iterations and becomes competitive on storage. With partial shuffling
implementations, the number of iterations for shuffling is
O(desirableSize) although the storage remains the same.
Or more informally, the higher it is the unique finite set of numbers that will be pickup from a finite set of possible numbers, the more desirable it is to use the second approach.
For instance, if one generates numbers from 0 to 1000 and is only interested in 5 numbers, since the probability of picking randomly the same numbers is lower, one is better off with the first approach. However, if you would be (instead) interested in 800 numbers, then one would be better off generating and shuffling the 1000 numbers, and extracting the 800 unique values from them.
Memory-wise the first approach is better then second approach, however performance-wise it depends in the context as we have already described.
i dont see a problem.
Your System.out.println(tes[i]); is in loop
your array has only following ints: 5,9,2,7,1
make println in own loop
for (int i = 0; i < tes.length; i++) {
System.out.println(tes[i]);
}
because you make i=i-1; one value is printed many times
I managed to solve it in a different way:
List<Integer> tes = new ArrayList<>(5);
Random r = new Random();
for (int i = 0; i < 5; i++) {
int testNummer = r.nextInt(10);
if(!tes.contains(testNummer)) {
tes.add(testNummer);
System.out.println(testNummer);
}else{
i=i-1;
}
}
this way is more efficient, I have noticed.
Some logic problem
Increment i variable when you store value in array and don't decrement i variable just break inner loop when found duplicate.
when duplicate found then restart outer loop. use if else condition for that
try below code and for simple understanding i have changed outer loop in while
int i = 0;
while(i<5)
{
int q = r.nextInt(10);
System.out.println("random value generated"+ q );
int j=0;
for (;j < i; j++)
{
if (q == tes[j])
{
System.out.println("duplicate value found"+ q );
break;
}
}
if(j!=i)
{
continue;
}
else
{
if(j==i)
{
tes[i] = q;
i=i+1;
}
}
System.out.println("value at "+ tes[i]);
}
If you want an easy way to generate unique values you can do it with a stream.
Random r = new Random();
int minVal = 1;
int upperBound = 20;
int count = 10;
As long as count is less than upperBound - minVal it will finish without duplicates. For very large counts with the appropriate range, it may take some time.
int[] unique = r.ints(minVal, upperBound).distinct().limit(count).toArray();
System.out.println(Arrays.toString(unique));
Prints something like this.
[14, 1, 7, 13, 5, 16, 2, 8, 12, 4]
An easy way to generate random numbers of a fixed range is to simply shuffle the array.
Integer[] vals = new Integer[20];
for (int i = 0; i < vals.length; i++) {
vals[i] = i+1;
}
// Object array will be shuffle since it backs up the list.
Collections.shuffle(Arrays.asList(vals));
System.out.println(Arrays.toString(vals));
Prints something like
[7, 20, 5, 10, 17, 18, 3, 13, 11, 1, 2, 8, 4, 9, 19, 12, 15, 16, 6, 14]

Randomly prints elements in an array

Is there a way where you can use Math.random to prints the element in a given array?
int[] list = new int[] {1,2,3};
So the output will be like
2,1,3
or
3,1,2
or
2,3,1
Perhaps you can approach it by shuffling your array then print it. If the original should not be modified, you can make a copy and then shuffle the copy.
There are well-known algorithms for shuffling array (or a deck of cards). One can be found here. An implementation in java looks like this:
static void shuffleArray(int []array) {
int length = array.length;
for (int i = length -1; i > 0; i--) {
// generate a random 0 <= j < i
int j = (int)(Math.random() * i);
// swap elements at i and j
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
The approach proposed in most answers is extremely inefficient, as it works in O(N2) time. Think about it: at first you'll generate unused indexes with one attempt, but closer to the end, when almost all array is processed, it will require nearly N steps to generate next unused index.
The optimal O(N) approach is to create shuffled array of indexes (0..N) where each index appears only once and then process your original array in the order of shuffled indexes. Each step requires O(N) time, so the whole algorithm is O(N).
int[] input = new int[]{5, 4, 3, 6, 2, 1};
int []indices = new int[input.length];
//Fisher-Yates shuffle
Random rnd = new Random();
for (int i = 0; i < indices.length; i++) {
int j = rnd.nextInt(i + 1);
indices[i] = indices[j];
indices[j] = i;
}
for (int i : indices) {
System.out.println(input[i]);
}
I didn't use Collections.shuffle, as it would require usage of Collection and thus wrapped Integer elements, which is very inefficient comparing to the plain int array.
Also, if you are ok with modifying your original array, you can just shuffle it in place (using the same Fisher-Yates shuffle) and then consume it while traversing.
UPD: Replaced shuffling array of indices with shuffled initialization.
Since you have java 8, you can take advantage of the beautiful Stream API.
In short, you can do:
new Random().ints(1, 500).limit(500).forEach(p -> System.out.println(list[p]));
Where 1 is the lowest int generated (inclusive) and 500 is the highest (exclusive). limit means that your stream will have a length of 500, maybe in that argument you want to put list.length.
For your case:
int[] list = new int[] {1,2,3,4,5,6};
new Random().ints(0, list.length).limit(10).forEach(p -> System.out.println(list[p]));
Prints: 5 2 5 4 6 3 3 5 6 4 (Obviously will not print the same numbers for you)
Create a random integer that may be as high as the length of the array - 1. If the random integer is equal to a previous used random integer -- known by storing used integers in an array -- create a new random integer. Otherwise, print the string correlated with that index specified by the random integer. If the length of the array storing the used random integers is equal to the length of the array of strings, stop the process.
This should print all your strings only once each and randomly.
Here is the solution
public static void main(String[] args) {
int[] list = new int[] { 1, 2, 3 };
int[] aux = new int[list.length];
int countTimes = 0;
while (countTimes < list.length) {
int position = new Random().nextInt(list.length);
if (aux[position] != list[position]) {
System.out.println(list[position]);
aux[position] = list[position];
countTimes++;
}
}
}
As I said in the comments. This answer will work.. All you need to do is track the indices that it accessed so you don't repeat them or remove that element from the array.
void printRandom(int[] array) {
if (array.length == 0)
return;
Random rand = new Random();
int rnd = rand.nextInt(array.length);
int element = array[rnd];
array = ArrayUtils.removeElement(array, element);
System.out.print(element);
printRandom(array);
}
Just repeat this process until all elements are removed. Obviously add checks to prevent errors and keep in mind I haven't used JAVA in a long time so post back if you have issues!
Lastly keep in mind this deletes the array so you may want to wrap this code in a function and then copy the array as a local variable so you can reuse the original as needed
In this case we can print random value from array using like below :
Steps:
Create list object of Integer to hold printed indices
Get random number and check whether this index is already printed or not
if not printed then add it in list and print value from array using this index
if list size and array length is equal then terminate the loop
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomIndices {
public static void main(String[] args) {
int[] list = new int[]{1, 2, 3};
Random random = new Random();
List<Integer> randomIndices = new ArrayList<>(); //to hold indices which are already printed
boolean isRemain = true;
while (isRemain) {
int randomIndex = random.nextInt(list.length);
if (!randomIndices.contains(randomIndex)) { //check random index value of array is printed or not
randomIndices.add(randomIndex);
System.out.println(list[randomIndex]);
}
if (randomIndices.size() == list.length) {
isRemain = false;
}
}}
}
Implement a simple "do while" statement to prevent duplicate numbers from showing up out of your array (I used a StringArray - but an IntegerArray would work the same way - as a side note, I can place the complete code up here but didn't want to do so if it didn't apply. I use a drop-down to select how many random words to generate - then display that set of true RANDOM words (non-repeated):
final Random rand1 = new Random();
final Random rand2 = new Random();
final int rndInt1 = rand1.nextInt(getResources().getStringArray(R.array.words).length);
int rndInt2 = rand2.nextInt(getResources().getStringArray(R.array.words).length);
if (rndInt1 == rndInt2){
do {
rndInt2 = rand2.nextInt(getResources().getStringArray(R.array.words).length);
}while (rndInt1 == rndInt2);//if indexes are equal - re-run the array search
}
outString = getResources().getStringArray(R.array.words)[rndInt1];
outString += ", " + getResources().getStringArray(R.array.words)[rndInt2];//concatenate the list
textWord = (TextView) findViewById(R.id.textWords);//An empty text field in my layout
textWord.setText(outString);//Set that empty text field to this string of random array elements

Random number generation with no duplicate values for insertion sort [duplicate]

This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
Closed 8 years ago.
Hello i have been working on insertion sort on set of numbers. i am able to add them to the array for performing the sorting but i was not able to generate unique values with large set of numbers to performing sorting(i:e)for 1000 values .is there any possibility i can generate unique random numbers for performing the sorting without adding values to the array?
public class InsertionBinary
{
public static void main(String Args [])
{
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 24};
print(nums);
insertionsort(nums);
print(nums);
int loc = binarySearch(nums, 3);
System.out.println("2 is in position" + loc);
}
private static void swap(int[] list, int from, int to)
{
int temp = list[from];
list[from] = list[to];
list[to] = temp;
}
private static void print(int[] list)
{
for (int i = 0; i < list.length - 1; i++)
System.out.
print(list[i] + ", ");
System.out.println(list[list.length - 1]);
}
private static void insertionsort(int[] list)
{
int key;
int spot;
for (int pass = 1; pass < list.length; pass++)
{
key = list[pass];
for (spot = pass - 1; spot >= 0 && list[spot] > key; spot--)
list[spot + 1] = list[spot];
list[spot + 1] = key;
}
}
}
If all you want is a set of unique numbers for sorting, I would say the easiest approach would be to generate an array of size N containing the numbers 0 though N-1 (or 1 through N if you prefer) using a loop:
int size = 1000;
int[] nums = new int[size];
for(int i = 0; i < size; i++) {
nums[i] = i;
}
Then all you need to do is shuffle it, which you can do using your already-implemented swap() method and this helpful answer:
Random shuffling of an array
This has the advantage that it will run in O(n) time (instead of potentially infinite time if you're picking random numbers and then only inserting them if they're not already there).
Edit: You could also use Java's built-in shuffle method https://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#shuffle(java.util.List)
you can use Math.random() and also add one condition that will check, array contains that number or not, if not contains then add otherwise don't add.
One simple solution is using Set generate your random numbers and insert them in a Set, set wont allow duplicate numbers, something like this :
Random rnd= new Random();
Set<Integer> randomSet = new LinkedHashSet<Integer>();
while (randomSet.size() < 1000)
{
Integer randomNum = rnd.nextInt(max) + 1;
randomSet.add(randomNum);
}
but it may take infinite time to generate a set like this in theory, but its probability is very low.

Randomly "shaking" an array to assign new random spots

What Im trying to do is take my array coins[]. And basically rearrange each coin to a different position. This is what i have so far. When I do this though, nothing happens. Meaning all the values stay the same. Except for the last one. That one changes.
public void shake()
{
for (int i = 0; i < coins.length; i++)
{
int index = Coin.RANDOM.nextInt(coins.length);
Coin temp = coins[index];
coins[index] = coins[i];
coins[i] = temp;
System.out.print(coins[i] + ", ");
}
}
I instantiate random like this:
public static long SEED = System.currentTimeMillis();
public static Random RANDOM = new Random(SEED);
Please notice that this line
System.out.print(coins[swap] + ", ");
displays the already moved (swapped) coin. Maybe you were thinking about displaying the new coin at i index: coins[i] (which wouldn't be correct anyway, as the already displayed coin still can be swapped in the next iterations). Probably it's better to create a second for loop to display final coin values.
But this isn't only problem here. To randomly shuffle an array you should use Fisher-Yates algorithm which is slightly different than your method. You can find Java implementation of this algorithm on SO.
If you had a List<Coin> instead of Coin[] (list instead of array) you could use the Collections.shuffle method and be sure that the algorithm is correct and you'll always get random result.
As you are using swap as index with which you will be swapping the current value you can edit your Random number generator to generate random numbers between certain range (say 0 - coins.length) and then you can change your implementation to something like this
public void shake()
{
Coin temp;
for (int i = 0; i < coins.length; i++)
{
//int swap = Coin.RANDOM.nextInt(coins.length);
temp = coins[swap];
coins[swap] = coins[i];
coins[i] = temp;
System.out.print(coins[i] + ", ");
}
}
For the commented line in your code check THIS to update your random number generator to generate numbers between two values. Then each time you generate swap(index) between i+1 - coins.length and continue this till you fully exhaust the array. This ensures that you don't make a swap at the index the value for which you have already displayed. But I am not completely confident that this would indeed be a random shuffle as in the beginning of the loop you have more choices for the swap index then you would have sometime later in the loop and the shake is not completely random. This solution is only in case you want to strictly implement your own shake method without using the Collections.shuffle as #Tomek mentioned.
why don't you using Collections? its so simple to assign random indexes to each value in array or ArrayList.
Collections.shuffle(coins);//if coins is array
Collections.shuffle(Arrays.asList(coins));//if coins is an ArrayList
You might use Knuth's shuffling algorithm which rearranges the array so that a result is a uniformly random permutation. Algorithm is simple but works like a charm:
Iterate over array and in iteration i pick random integer swap between 0 and i
Swap array[i] and array[swap]
Note that in your implementation random is generated between 0 and 11, which doesn't seem to produce good shuffling.
Here is a code example with shuffling for array of integers:
import java.util.Random;
public class Test {
public static long SEED = System.currentTimeMillis();
public static Random RANDOM = new Random(SEED);
public static void shuffle(int[] numbers)
{
for (int i = 0; i < numbers.length; i++)
{
int swap = RANDOM.nextInt(i + 1);
int temp = numbers[swap];
numbers[swap] = numbers[i];
numbers[i] = temp;
}
for (int i = 0; i < numbers.length; i++) {
System.out.print(numbers[i] + ", ");
}
}
public static void main(String[] args) {
shuffle(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
}
}
Output for test run is:
5, 11, 6, 1, 3, 10, 9, 2, 4, 7, 8,
Use this method and pass your array in parameter
Collections.shuffle(arrayList);
This method return void so it will not give you a new list but as we know that array is passed as a reference type in Java so it will shuffle your array and save shuffled values in it. That's why you don't need any return type.
You can now use arraylist which is shuffled.
Sourse: https://stackoverflow.com/a/16112539/4291272

I'm getting strange output from java program

I've some strange situation here and i thought that you may help me. I have an int array populated with numbers from 1 to 10. I want to generate random number from this array and save it to another int array. I used class Random to pick any number and since random throws 0 also i modify it like that ( so it throws numbers from 1 to 10 )
randNum = rand.nextInt(numbers.length-min+1)+min;
Following code makes sure that if it generates same random number, it skips it. Program is actually working and i'm getting in another array randomly positioned numbers from 1 to 10. That's what i wanted. But sometimes i'm missing one number from 1 - 10 AND iam Getting ZERO instead. Why??
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
int[] usednum = new int[10];
Random rand = new Random();
int randNum;
int min = 1;
for (int x = 0; x<numbers.length; x++) {
for (int i = 0; i<usednum.length; i++) {
randNum = rand.nextInt(numbers.length-min+1) + min;
for (int f = 0; f<usednum.length; f++) {
if (usednum[f] == randNum) {
break;
} else if (usednum[f] == 0) {
usednum[x] = randNum;
}
}
}
}
for (int c = 0; c<usednum.length; c++) {
System.out.println(usednum[c]);
}
You're inner-most for loop only checks if the current random number is in the usednum[] array. And the for loop immediately outer of that only checks 10 times total. It gives up too quickly because it only tries 10 random numbers. If all 10 are already used, nothing will get stored in that slot of usednum[] (thus it will be 0), try adding a while loop around that and get rid of the extraneous outer-most for loop:
for(int i = 0; i<usednum.length; i++) {
while(usednum[i]==0) {
randNum = rand.nextInt(numbers.length-min+1)+min;
for(int f = 0; f<usednum.length; f++) {
if(usednum[f] == randNum) {
break;
} //if
else if (usednum[f] == 0) {
usednum[i] = randNum;
}
}
}
}
Also note that the assignment is for usednum[i] = randNum;.
This is essentially replacing the middle for loop (the one that goes from i=0 to 9) with the while loop.
If your goal is simply to shuffle an array of numbers, try this instead:
Integer[] numbers = {1,2,3,4,5,6,7,8,9,10};
Collections.shuffle(Arrays.asList(numbers));
It will have the same effect. Unless you are completing a homework assignment that forces you to solve the issue in a more manual fashion, just make use of the standard Java libraries.
The shuffle method writes changes through to the underlying Integer array, thanks to the special type of List returned by Arrays.asList(...). Note you have to use an array of Integer not int (see Why does Collections.shuffle() fail for my array?).
You are generating used numbers through an entire pass, so it doesn't generate a zero is just fails to generate a value it should.
you have one for loop too much.
remove the loop with the i iterator and the program should do what you want.
Oh and remove the -min+1 from the random generator, -1+1=0
Your array usednum is consisted of zeros at the beginning. In some cases, your program doesn't change that initial value, but breaks before at the line:
if(usednum[f] == randNum)
and does that during all iterations with same value x. X increments and there goes your chance to change the zero value.
Edit - followed it and re-wrote it:
List<Integer> numbers = new LinkedList<Integer>(Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }));
int[] usednum = new int[10];
Random rand = new Random();
int n = numbers.size();
for (int i = 0; i < n; i++) {
int randNum = rand.nextInt(numbers.size());
usednum[i]=numbers.get(randNum);
numbers.remove(randNum);
}
for (int c:usednum) {
System.out.println(c);
}
Actually, you are never using the content of the array numbers. Try changing the array to something like int[] numbers = { 10, 22, 23, 42, 53, 18, 7, 8, 93, 10 };. You will get similar output.
Jon Lin's answer describe why your code is not working but does not address this issue. I think you will want to change your code to something like:
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int[] usednum = new int[10];
Random rand = new Random();
int selectedCount = 0;
while (selectedCount < numbers.length) {
int randNum = numbers[rand.nextInt(numbers.length)];
boolean contains = false;
for (int x = 0; x < selectedCount; x++) {
if (usednum[x] == randNum) {
contains = true;
break;
}
}
if (!contains) {
usednum[selectedCount] = randNum;
selectedCount++;
}
}
for (int c = 0; c < usednum.length; c++) {
System.out.println(usednum[c]);
}

Categories

Resources