How do you keep a running count in an array? - java

The method is called loadArray(), and this method will load an array with a specified number of random values and update the subscripts in the array to reflect the number of times a random number was generated. The values will be between (0, values.length-1). The signature is public static void loadArray(int[] values, int times).

Well, as you commented, essentially you want a function to count how many times a value appears in a array and, after, updates the array (respective element) with the apearing countings.
In others words you want to update the values with their respective "frequency" that appears in the array.
To to do this I suggest to you a approach using the Map structure.
How does it work, then?
Excluding the array generation step (thinking only in counting step) we can imagine just put each value of the passed array into a map just checking if the value was previously inserted or not.
Then, maps are structures that can holds some information while associate that information to a key, this is the known format "key/value".
Implementation
Ok, to implement this, lets consider a method that generates a array with random numbers, counts it and, after, returns a updated array as we need:
public static int[] count(int arrayLength, int rangeOfRandom) {
//generates the randons
Random generator = new Random();
int[] array = new int[arrayLength];
for (int i = 0; i < array.length; i++) {
array[i] = generator.nextInt(rangeOfRandom);
}
System.out.println("The generated array was: " +
Arrays.toString(array));
//counts each value
HashMap<Integer, Integer> aux = new HashMap<>();
for (int i = 0; i < array.length; i++) {
//if the map DOES NOT contains the current array value
if (!aux.containsKey(array[i])){
aux.put(array[i], 1); //puts it with "1 counter"
} else {
//if not...
//...overrides the existing value with itself PLUS 1
aux.put(array[i], aux.get(array[i]) + 1);
}
}
//updates the array
int[] nArray = new int[array.length];
for (int key : aux.keySet()){
for (int i = 0; i < array.length; i++) {
if (array[i] == key){
nArray[i] = array[i] + aux.get(key);
}
}
}
//here we return the updated array
return nArray;
}
By doing
System.out.println("The result array is: " +
Arrays.toString(count(5, 10)));
You get a output like this:
The generated array is: [0, 6, 6, 8, 7]
The result array is: [1, 8, 8, 9, 8]
As you can see, these operations are very elementar, and you can easly refactor it to receive/return other king of parameter and/or types.
For a related discussion, you can check this question.
Obs.: the method I posted is not optimized, it is only for didatic use.

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.

Random number from an array

I tried to generate a sorted list of random data with no duplicates in descending order for my array. It also returns number of duplicates, but it keeps printing out nothing but zero .... Can anyone help me please :(
// 2. Ask the user for size of arbitrary numbers.
System.out.print("Please enter a size for arbitray numbers: ");
int size = indata.nextInt();
int [] SortedNumbers = new int [size];
// 3. Process arbitrary numbers and remove all duplicates
int numDuplicates = generate_data(SortedNumbers);
// 4. Print the numbers and number of duplicates
printArray(SortedNumbers, numDuplicates);
and here is the random method
public static int generate_data (int [ ] list){
int duplicates = 0;
Random random = new Random();
System.out.println(n[random.nextInt(n.length)]);
return duplicates;
}
here is the print_array method
public static void printArray(int [] list, int duplicates) {
// Additional code required
System.out.println("\nSize of array: " + list.length + " .Numbers of duplicates: " + duplicates); for (int i = 0; i<list.length; i++){
System.out.printf("%7d", list[i]);
if ((i + 1) % 10 == 0){
System.out.println();
}
}
}
random.nextInt(n.length)
gives you a random index of your array.
But printing the value corresponding to this index, will always give you 0. As you never store any other value in the array.
You should rather do something like this :
int[] list = new int[10];
int duplicates = 0;
Random random = new Random();
for (int i = 0; i < list.length; i++) {
int nextVal = random.nextInt(list.length);
System.out.println("list["+i+"] = "+ nextVal);
// test duplicates
for (int index = 0; index < i; index++) {
if (list[index] == nextVal) {
duplicates++;
break;
}
}
list[i] = nextVal;
}
return duplicates;
Your generate_data method always returns 0, since the local field duplicates is initialized with a 0 value and never changed.
The n field referenced by your generate_data method (which you haven't posted) is likely to be an int[], but its elements might not have been initialized (hence the print out will print default value 0, if within array index).
Hence your numDuplicates local field is always 0 too.
Notes
Your Random initialization is not performing. You should initialize a static Random object in your class and re-use it, instead of re-initializing every time in your generate_data method.
You probably want to have a look at coding conventions for Java in terms of field naming
You might want to post the code in your printArray method as well

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

Categories

Resources