How to get the sequence of numbers back after random number generation - java

Am in the middle of an encryption algorithm, I have written the code to randomly shuffle a series of numbers in java.
Here is the code:
public class permute6 {
public static void main(String args[])
{
Random rand = new Random();
int arr[] = {10,20,30,40,50,60,70,80};// Original Array
System.out.println("Original array is" );
for(int k = 0; k<arr.length;k++ )
System.out.print(arr[k] + "\t" );
System.out.println(" ");
int max = arr.length - 1;
int min = 0;
int rnum;
int larr = arr.length - 1;
int[] parr = new int[arr.length];// to store the permuted array
int flag = 0;// 'flag' to flag the recurring number
int plen = parr.length - 1;
for(int i = 0 ; i < arr.length ; i++)
{
rnum = (rand.nextInt((max-min)+1) + min);// roll for the
random number
parr[plen] = arr[rnum];
arr[rnum] = arr[larr];
larr--;// to reduce the size of the original array
plen--;// to make the parr to act like a stack
max--;
}
System.out.println("Permuted array is" );
for(int k = 0; k<arr.length;k++ )
System.out.print(parr[k] + "\t" );
System.out.println();
}
}
If the initial array is {10,20,30,40,50,60,70,80}
then one of the shuffled result is
50 20 30 10 60 80 70 40
Now if I transmit this array, then how to get back the original sequence at the destination side? What can be done to keep track of the sequence?
What is missing here....Any help is appreciated!!

You can submit two arrays to destination parr and temp;
parr: [50 20 30 10 60 80 70 40]
and
temp(It is basically difference of permuted array from original e.g. parr-arr):
like {50, 20, 30, 10, 60, 80, 70, 40} - {10,20,30,40,50,60,70,80}
temp = {40,0,0,-30,10,20,0,-40}
Now,
At destination again get difference of parr and temp "parr-temp"
{50, 20, 30, 10, 60, 80, 70, 40} - {40,0,0,-30,10,20,0,-40}
= {10,20,30,10-(-30),50,60,70,40-(-40)}
You will get your original sequence without sending original array at destination
Another solution came into mind related to previous one but it will avoid transferring two arrays to destination. Merge both temp and parr into a single array say newArr = {50,40,20,0,30,0,10,-30,60,10,80,20,70,0,40,-40}
and at destination just subtract each element from the next element and you will get your original array using only one array.

Related

Array generation - Regular, or 2D?

I'll try to keep this as short and concise as possible.
I'm working on a project, and I'm stuck on a rather early speedbump.The project involves creating 10 arrays of randomly generated integers (from 0 to 99), where each array has a different number of elements (n). After we have several pools of ints to work with, I need to enact different sorting algorithms on said arrays - but I haven't even made it that far yet.
I've successfully made a for-loop generate an array where each int is random. The loop then restarts with a new value for 'n', and generates another array of random integers.
My code is as follows:
import java.util.Arrays;
public class Testing {
public static void arrayGenerator() {
int[] elements = { 100, 250, 500, 750, 1000, 1250, 2500, 3750, 5000, 6250 }; // 10 different values for 'n' to work with.
int n; // Number of elements per array.
int i; // Index of n, ie. 0 = 100, 1 = 250, 2 = 500, etc.
int k; // Index of element in generated array.
//Generate a separate array of random numbers for each value of 'n'.
for (i = 0; i < elements.length; i++) {
n = elements[i];
int[] sortableArray = new int[n];
//Populate each array with random numbers ranging from 0 to 99.
for (k = 0; k < n; k++) {
sortableArray[k] = (int) (Math.random() * 100);
}
System.out.println(Arrays.toString(sortableArray));
}
}
public static void main(String[] args) {
Testing arrGen = new Testing();
arrGen.arrayGenerator();
}
}
The 'System.out.println(Arrays.toString(sortableArray))' was just to see if the numbers were generating (and the correct amount of numbers was generating).Here's where I've ground to a halt. If I understand correctly, each subsequent array is overwriting the previous one - so by the end I don't have 10 arrays, I have one, where n = 5000.
I've looked into using a 2D array, an ArrayList, or a Map, but my efforts were in vain (ie., I'm not too sure how to go about that).When I tried to form a 2D array, in which I'd try to use "(int) (Math.random() * 100)" to set the value for [k], I'd consistently get NullPointExceptionErrors. Which means I was doing something incorrectly, but I'm not sure what.
Later in my project, I need to be able to take all these arrays, sort them (individually), take note of the time taken to sort them... etc. But for now I'm having trouble storing them in the first place.
I'm sure the solution is quite simple, but I've just been stumped for the last while, and I can't seem to reach the solution. If anyone could guide me towards an optimal solution, I'd really appreciate it!
Thanks for reading!
EDIT - For extra clarity, here was my feeble attempt at using a 2D array (replacing both for-loops from the code above):
for (i = 0; i < elements.length; i++) {
n = elements[i];
//Populate each array with random numbers ranging from 0 to 99.
for (k = 0; k < n; k++) {
int[][] sortableArray = new int[i][n];
sortableArray[i][k] = (int) (Math.random() * 100);
However, this was the result:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at ie.gmit.dip.Testing.arrayGenerator(Testing.java:22)
at ie.gmit.dip.Testing.main(Testing.java:32)
Where the error directs to this line:
sortableArray[i][k] = (int) (Math.random() * 100);
I'm stumped. Any and all insight is greatly appreciated!
Thanks.
Just store your array in a list before the end of the for-loop:
import java.util.Arrays;
public class Testing {
public static void arrayGenerator() {
int[] elements = { 100, 250, 500, 750, 1000, 1250, 2500, 3750, 5000, 6250 }; // 10 different values for 'n' to work with.
int n; // Number of elements per array.
int i; // Index of n, ie. 0 = 100, 1 = 250, 2 = 500, etc.
int k; // Index of element in generated array.
//Create a list to store all your arrays
LinkedList<int[]> listOfArrays = new LinkedList<int[]>();
//Generate a separate array of random numbers for each value of 'n'.
for (i = 0; i < elements.length; i++) {
n = elements[i];
int[] sortableArray = new int[n];
//Populate each array with random numbers ranging from 0 to 99.
for (k = 0; k < n; k++) {
sortableArray[k] = (int) (Math.random() * 100);
}
listOfArrays.add(sortableArray);
System.out.println(Arrays.toString(sortableArray));
}
}
public static void main(String[] args) {
Testing arrGen = new Testing();
arrGen.arrayGenerator();
}
}

Adding 1 to an Array index each loop [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 4 years ago.
So, I'm working on a problem that has me adding two die rolls 'X' amount of times, then recording the frequency in an array, here is what I have
int [] counters = new int [11];
for (int i = 0; i <1001; i++){
//have to add +1 so I don't get 0
++counters[((die1.nextInt(6)+1)+(die2.nextInt(6)+1))];
}
System.out.print(counters);
And I'm getting this error:
java.lang.ArrayIndexOutOfBoundsException: 12
//have to add +1 so I don't get 0
No you really don't.
In Java arrays are 0-based. Meaning an array of 11 elements has indices 0 .. 10.
Random.nextInt(n) returns a value between 0 and n-1.
Therefore the expression ((die1.nextInt(6)+1)+(die2.nextInt(6)+1)) will be between 2..12.
Either increase the size of the array to 13 so that 12 fits (the first 2 elements will remain unused), or simply remove +1's:
Random die1 = new Random(), die2 = new Random();
int [] counters = new int [11];
for (int i = 0; i <1001; i++){
++counters[die1.nextInt(6)+die2.nextInt(6)];
}
Also you can't print an array with print(). A possible solution is to print each element individually:
for (int i = 0; i < counters.length; ++i) {
System.out.print((i+1) + ":" + counters[i] + " ");
}
System.out.println();
You have two dice, and the result of a die roll can be from 0 to 5. I assume the 1001 means you want to roll the two dice 1001 times. Please let me know if I missed anything here.
In this case your min roll would be a 0, and max 10. But, adding 1 to both dice rolls before accessing would mean your index goes from 2 to 12 which causes your ArrayIndexOutOfBoundsException.
Just don't add anything to the roll. Remember java arrays start from 0, so a range of 0 to 10 is fine.
Quick example:
public static class Die {
static Random rand = new Random();
public static int nextInt(int val) {
return rand.nextInt(val);
}
}
public static void main(String[] args) {
int[] counters = new int [11];
for (int i = 0; i <1001; i++){
//no need to add anything
++counters[Die.nextInt(6) + Die.nextInt(6)];
}
System.out.print(Arrays.toString(counters));
}
Example output:
[27, 60, 81, 106, 157, 175, 120, 109, 81, 55, 30]
Which we can translate to mean that a "2" was rolled 27 times, "3" 60 times, etc.

RodCutting: when the rod is bigger than the array length

How can I modify the methods cutRod and bottomUpCutRod to hold lengths that are bigger than the array length. For example, currently p has length 11, how can I cut the rod of length 15, 20 , etc, having this same array. For example
p = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
if I call cutRod(p,10), I get 30, but it crashes of course in cutRod(p,15) or
cutRod(p,20). (same applies for bottomUpCutRod). Any ideas how to do this?. This is dynamic programming problem, my idea to implement bottomUpCutRod method is to traverse p and for each element calculate every permutation of itself and its neighbors and update if necessary the resulting array, r.
public class Main {
private static final double MINUS_INFINITY = Double.NEGATIVE_INFINITY;
public static void main(String[] args) {
// price array
double[] p = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
// test cutRod
cutRod(p,10);
// test bottomUpCutRod
bottomUpCutRod(p,10);
}//end of main
// an optimal cut for a rod of length n
// p is the price array
// use recursion
private static double cutRod(double[] p, int value) {
double[] r = new double[value+1];
double out = 0;
// initialize r to NEGATIVE_INFINITY;
for (int i = 1; i < r.length; i++)
r[i] = MINUS_INFINITY;
// call the helper method
out = helpCutRod(p,r.length-1,r);
// print r
System.out.println("Result ");
System.out.println("r[" + (r.length-1) + "] = " + r[r.length-1]);
return out;
}//end of method
// helpCutRod computes an optimal cut for a rod
// p is the price array and r[i] is the optimal cut for a rod of length i
// n is the length of the rod that is currently being computed
private static double helpCutRod(double[] p, int n, double[] r) {
double q = MINUS_INFINITY;
if (r[n] >= 0) // the whole r was computed
return r[n];
if (n == 0)
q = 0;
else {
for (int i = 1; i <= n; i++) {
q = RodCutting.max(q, p[i] + helpCutRod(p,n-i,r));
}
r[n] = q;
}
return q;
}
// use the bottom-up approach
// do NOT use recursion
private static double bottomUpCutRod(double[] p, int len) {
// r[i] is the optimal cut for a rod of length i
double[] r = new double[len+1];
r[0] = 0;
for (int j = 1; j < p.length; j++) {
// compute r[j]
double q = MINUS_INFINITY;
// r[j] is the maximum over i of p[i] + r[j-i]
// where 1<= i <= j
for (int i = 1; i <= j; i++)
q = max(q, p[i] + r[j-i]);
// update value of r[j]
r[j] = q;
}//end of for outer
// print r
System.out.println("The r array from the bottomUpCutRod:");
System.out.println("r[" + len + "] = " + r[len]);
return r[len] ;
}//end of method
public static double max(double a, double b){
if(a<=b){
return b;
}else{
return a;
}
}//end of max
}//end of class
If I understand the rod cutting problem correctly, your price array, p, tells the prices at which you can sell rod pieces of lenghts 0 through p.length - 1. So if the array length is 11, you know the prices of pieces up to length 10 even if you have an inital rod of length 15, 20 or 30. Since you don’t know the prices for lengths 11 and above, I assume you can safely set them to 0. I would then expect the algorithm to cut up your rod into pieces for which you know a positive price.
If all of this is correct, the solution is easy. To calculate, say, cutRod(p, 15), first do
p = Arrays.copyOf(p, 15 + 1);
This will copy p into a new array with indices 0 through 15, padded with zeores. Now run your methods. Similarly for other initial lengths, of course.
With this modification, your program prints for a rod length of 15:
Result
r[15] = 43.0
The r array from the bottomUpCutRod:
r[15] = 43.0
I assume it’s found pieces at 10, 3 and 2 yielding prices 30 + 8 + 5 = 43, but I haven’t checked.
EDIT: If the rod is very much longer than the price array, it is probably wasteful to have it calculate results with cuts longer than the maximum of the price array. So instead of the above quick fix, it is in fact possible to modify your methods to accept a shorter price array and a longer initial rod.
In the recursive helpCutRod(), change the for loop to:
for (int i = 1; i <= Math.min(n, p.length - 1); i++) {
This will make sure that only pieces for which we have prices will be considered.
For bottomUpCutRod(), two changes are needed:
The first for loop needs to run until j equals len:
for (int j = 1; j < r.length; j++) {
And again, the inner for loop should not pass the bounds of p:
for (int i = 1; i <= Math.min(j, p.length - 1); i++)
With these three modifications instead of the extension of the p array, the program prints the same results as above.

Duplicate array in java and need to print rest of array element

Please look in to the below code. It print the only duplicate elements in array. I need to print also rest of array element, please try to help me.
public class DuplicateArray {
public static void main(String args[]) {
int array[] = { 10, 20, 30, 20, 40, 40, 50, 60, 70, 80 };// array of ten elements
int size = array.length;
System.out.println("Size before deletion: " + size);
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if ((array[i]== array[j])) { // checking one element with all the element
System.out.println(array[i]);
}
}
}
Ouput:
20
40
Here I need to print the rest of array element ?
In Java 8, you can easily remove duplicates from an integer array using IntStream.
int[] noDuplicates = IntStream.of(array).distinct().toArray();
To print them instead of putting them in an array, use
IntStream.of(array).distinct().forEach(System.out::println);
You can use Set to solve this.
List<Integer> list = Arrays.asList(ArrayUtils.toObject(array));
Set<Integer> set = new HashSet<Integer>(list);
List<Integer> withoutDuplicates = new ArrayList<Integer>(set);
int[] newArrayWithoutDuplicates = ArrayUtils.toPrimitive(withoutDuplicates.toArray(new int[withoutDuplicates.size()]));
Finally, you have the array without duplicates.
Your question as to what you want to do isn't very clear but what I think is you want is to print the array elements without repetition.
If this is indeed the case, the following code will do it.(The explanation of the code is given after the output)
public class DuplicateArray {
public static void main(String args[]) {
int array[] = { 10, 20, 30, 20, 40, 40, 50, 60, 70, 80 };// array of ten elements
int size = array.length;
System.out.println("Size before deletion: " + size);
boolean duplicateElement=false;//this becomes true if there is a duplicate element in the array before the occurrence of this element
for (int i = 0; i < size; i++, duplicateElement=false) {
for (int j = 0; j < i; j++) {
if ((array[i]== array[j])) { // checking one element with all the elements
duplicateElement=true; //Duplicate element found in array
break;
}
}
if(!duplicateElement)
System.out.println(array[i]);
}
}
}
Output:
10
20
30
40
50
60
70
80
Now, the idea in this code is instead of starting the inner loop from i+1 and going till array.size, start it from 0 and go till i. duplicateElement is a flag variable the value of which becomes true if a duplicate element of array[i] is present in the array at position < i. However, when it's the first occurrence of the duplicate element, there is no other same element before array[i], only after. Hence the repetitive elements are also printed just once

How would you make an array of 10000 with only values of 1-1000 inclusive?

"Each of the functions should be run with array inputs, of size 100, 1000 and 10000; where each
value in any array should be an integer from 1 – 1000 inclusive. Each sorting function should be
run on arrays of the following types: random numbers, sorted lists and almost sorted lists"
Below I have created three arrays.
First one fills Array of 10000 randomly with integers from 1-1000.
Second fills array of 10000 with integers from 1-10000.
Third Shuffles array of 10000 which include integers from 1-10000.
My problem is I can't get my 2nd and 3rd Array of 10000 to only include values from 1-1000.
Is is even possible? I'm new to this. Any help will be appreciated!!
int [] inputTenThousand = new int[10000]; // Random 10000
for (int a = 0; a < inputTenThousand.length; a++) {
inputTenThousand [a] = (int) (Math.random () * 1000);
}
int [] inputTenThousand2 = new int[10000] // Sorted 10000
for (int a = 0; a < inputTenThousand2.length; a++) {
inputTenThousand2[a] = a + 1;
}
List<Integer> TenThousandList = new ArrayList<Integer>();
for (int i = 1; i < 10001; i++) {
TenThousandList.add(i);
}
Collections.shuffle(TenThousandList);
int[] inputTenThousand3 = new int[TenThousandList.size()]; // Almost Sorted 10000
for (int i = 0; i < TenThousandList.size(); i++) {
inputTenThousand3[i] = TenThousandList.get(i);
}
for (int i = 0; i < inputTenThousand3.length; i++) {
inputTenThousand3[i] = TenThousandList.get(i);
}
You can come very close using the code you already have, by just adding the modulo operator for the second and third lists. Adding elements "mod 1000" ensures that you have no values in the list greater than 1000. (You have to add one to the resulting values to shift the range up from 0-999 to 1-1000).
inputTenThousand2[a] = (a % 1000) + 1;
Of course, this doesn't preserve the sorted order you created originally, but once you generate these arrays, you'll notice a very clear pattern. Your array is now just the numbers 1-1000, repeated ten times. This makes picturing what the array would look like sorted very easy:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
...
1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000]
So, we can just construct that nice sorted list in the first place:
int [] inputTenThousand2 = new int[10000]; // 10000 sorted integers
for (int v = 0; v < 1000; v++) { // loop from 0 to 999
for (int i = 0; i < 10; i++) {
inputTenThousand2[(10*v) + i] = v + 1; // Set ten elements per value of the outer loop
}
}
You can then copy this list into a third list and "slightly unsort" it for your third case!
Of course, depending on what you have access to (this looks like an assignment, so maybe you don't have sorting readily available), it's likely to be easier to just create the first list as you have it already, then copy it and sort it for the second case.

Categories