I've been battling with this for some time and seem to be getting nowhere. The set up is so; I have a 2D array. For this array I need to iterate through each value and return the diagonal neighbours (5 values). These neighbours will be put into a new 1D [5] array and bubblesorted. The middle value (median) will then be returned and put into a new array of medians.
So far I have methods for extracting the diagonal neighbours:
//get diagonals from original DEM
double [] getDiagonals(int i, int j) {
double [] tempArray = new double [5];
tempArray[0] = data[i -1][j +1];
tempArray[1] = data[i -1][j -1];
tempArray[2] = data[i][j];
tempArray[3] = data[i +1][j -1];
tempArray[4] = data[i +1][j +1];
return tempArray;
}
I've then used this method in an iteration to get diagonals for each value in the original array:
//get diagonals for each
double [] [] bubbles(){
double [] [] datap = new double [298] [298];
for (int i = 1; i < data.length; i++){
for (int j = 1; j < data[i].length; j++) {
if ((i > 0) && (j > 0)) {
if ((i < data.length-1) && (j < data.length-1)){
double [] tempArray = getDiagonals(i, j);
//do something with the tempArray
I think this is where I'm coming unstuck. Through testing the getDiagonals method works fine. I'm struggling to get the tempArray out of the bubbles() method. If I set the output to be the tempArray it only returns the 5 values calculated for the bottom right corner of the original array.
I've tried calling other methods into the bubbles() method in order to do all the processing there and return a new array:
//get diagonals for each
double [] [] bubbles(){
double [] [] datap = new double [298] [298];
for (int i = 1; i < data.length; i++){
for (int j = 1; j < data[i].length; j++) {
if ((i > 0) && (j > 0)) {
if ((i < data.length-1) && (j < data.length-1)){
double [] tempArray = getDiagonals(i, j);
double sorted [] = sort(tempArray);
double median = sorted[2];
for (int z = 0; z < datap.length; z++){
for (int y = 0; y < datap[z].length; y++){
datap[z][y] = median;
}
}
}
}
}
}
return datap;
}
Again this fails and the output datap is just zeros. The sort() method above passed out the diagonals to a bubble sort method (which I know works on its
I guess my question is how to process within a method that is iterating and populate a new array?
I hope this makes sense but if you need more details please let me know. And yes, the sort I'm using is a bubble sort. I know they are rubbish but this is for a course I'm doing so it has to be used. And yes, I'm pretty new to java.
Any help would be greatly appreciated (and I'll even reference you if I need to use some code you provide ;)
The main issue that I see, is that with each traversal through your inner loop of:
for (int i = 1; i < data.length; i++){
for (int j = 1; j < data[i].length; j++) {
Where you call:
double [] tempArray = getDiagonals(i, j);
You are resetting all of the values of datap to be the current calculated median. To fix, you would need some way to indicate only the indices of the particular datap value that you want to populate.
You need to replace this section of your code:
for (int z = 0; z < datap.length; z++){
for (int y = 0; y < datap[z].length; y++){
datap[z][y] = median;
}
}
You could declare int y, z at the top of the method and do something like this:
if (y < datap.length){
if (z == datap.length[y] - 1){
y++;
z = 0;
}
datap[y][z] = median;
z++;
}
That way you are only assigning to the specific index in datap that you are trying to reach, instead of resetting each of its values.
Finally cracked it. To populate the whole array the following code works a peach.
//Diagonal to 1dArray and sorting
double [] [] bubbles()
{
double [][] tempArray = new double [300][300];
int y = 0;
int z = 0;
double median = 0;
for (int i = 0; i < data.length; i++)
{
for (int j = 0; j < data[i].length; j++)
{
if ((i > 0) && (j > 0))
{
if ((i +1 < data[i].length) && (j +1 < data[j].length))
{
double [] diagonals = getDiagonals(i, j);
//Need to sort here
median = diagonals[2];
tempArray[i][j] = median;
}
}
}
}
return tempArray;
}
The sorting was taken out and I haven't tested with it back in yet; but so far this is providing new values for all the cells in the temp array.
Related
I found this implementation of radix sort LSD for strings :
public static void sort(String[] input, int w) {
String[] aux = new String[input.length];
//ascii chars
int R = 256;
int n = input.length;
for(int d = w-1; d >= 0; d--) {
int[] count = new int[R+1];
//update the frequency at i+1 index
for(int i=0; i<n; i++) {
count[input[i].charAt(d) + 1] ++;
}
//transform the frequency into indices
for(int r=0; r< R; r++) {
count[r+1] += count[r];
}
//redistribute
for(int i=0; i<n; i++) {
aux[count[input[i].charAt(d)]++] = input[i];
}
for(int i=0; i<n; i++) {
input[i] = aux[i];
}
}
}
But I don't understand two things :
why here we have count[input[i].charAt(d) + 1] ++; rather than count[input[i].charAt(d)] ++; ?
why we don't redistribute the characters inversely ? I think it's way simpler (my implementation) :
public static void sort(String[] arr, int lenStr) {
int R = 256;
int len = arr.length;
String[] arrSorted = new String[len];
for (int d = lenStr - 1; d >= 0; d--) {
// frequency count of each character
int[] count = new int[R + 1];
for (int i = 0; i < len; i++) {
count[arr[i].charAt(d)]++;
}
for (int i = 1; i < count.length; i++) {
count[i] += count[i - 1];
}
for (int i = len - 1; i >= 0; i--) {
count[arr[i].charAt(d)]--;
arrSorted[count[arr[i].charAt(d)]] = arr[i];
}
for (int i = 0; i < len; i++) {
arr[i] = arrSorted[i];
}
}
}
I think most of it comes down to personal preference.
why here we have count[input[i].charAt(d) + 1] ++; rather than count[input[i].charAt(d)] ++; ?
Their count[x+1] means, after the second inner loop, how many times character x and any character prior to it appear. For example, we might have the initial counts:
count[0] = 0
count[1] = 2
count[2] = 3
Then after the second for loop we will have:
count[0] = 0
count[1] = 2
count[2] = 5
This means that character 0 takes the positions between count[0] and count[1], character 1 takes the positions between count[1] and count[2] and in general, character x takes the positions between count[x] and count[x+1] This allows them to do this:
for(int i=0; i<n; i++) {
aux[count[input[i].charAt(d)]++] = input[i];
}
Which is a nice one liner that ties everything together neatly IMO, because count[x] changes to mean at what position should we next place character x in our sorted array.
Your implementation works just as well and can also be turned into a one liner:
for (int i = len - 1; i >= 0; i--) {
arrSorted[--count[arr[i].charAt(d)]] = arr[i];
}
If you think it's simpler then you can use it, I don't see any downsides (assuming you've tested it well enough). It's a pretty complex algorithm and once you understand one way of doing it, you tend to stick with it. This is just the implementation that stuck I guess. Simplicity is highly subjective here, personally I think your version is just as complex.
My goal is to create an adjacency matrix generator (the only value elements can have is 0 or 1; it has to be symmetric, meaning element in [i][j] == element [j][i]) in Java.
I have some code, but the result is an nx5 matrix (if I establish n = 13, the resulting matrix is a 13x5 matrix). It is symmetric and the values of elements is bounded between 0-1, so that is not an issue. Another problem is I don't really know how to have an array without doubles, which is more of an aesthetical problem + ideally, the diagonal would be filled with "-" instead of zeroes, as it is now.
Random random = new Random();
double[][] array = new double[n][n];
for (int i = 0; i < array.length; i++)
{
for (int j = 0; j <= i; j++)
{
int x = random.nextInt(2);
array[i][j] = x;
if (i != j)
{
array[j][i] = x;
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j || (i + j + 1) == n)
{
array[i][j] = 0;
}
}
}
for (double[] a : array)
{
System.out.println(Arrays.toString(a));
}
}
I am solving a challenge to rotate array to left by n number of iterations.
Code is pretty much working but lags on very very huge input.
How to more improve efficiency
// Complete the rotLeft function below.
static int[] rotLeft(int[] a, int iterations) {
for(int i=0;i<iterations;i++)
{
int[] temp=Arrays.copyOfRange(a, 1, a.length);
temp=Arrays.copyOf(temp,a.length);
temp[a.length-1]=a[0];
a=temp;
}
return a;
}
Suggestions are welcome.
Thanks
Instead on shifting iterations you can calculate the final position directly.
finalIndex=(index-iterations+a.length) % a.length
+a.length is added to ensure that the finalIndex is always a not negattive value.
If you apply this to your algorithm, you get rid of the loop and do the whole thing in one step.
This reduced time complexity of the algorithm from O(a.length*iterations) to O(a.length).
There are few flaws in the code.
First, you do redundant work - if iterations > a.length - then after a.length iterations the array just returns back to itself.
Second, each iteration creates a whole new copy of the array!
Third, the new location of each element in the array can be predetermined by looking only on the array length, the number of iterations required, and the index of this element, no need to repeatidly go over iterations.
When taking these into considerations, this can boil down to something in the form of:
static int[] rotLeftEfficient(int[] a, int iterations) {
iterations = iterations % a.length;
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
int newIndex = (i - iterations + a.length) % a.length;
b[newIndex] = a[i];
}
return b;
}
This boils down to O(n) solution - where n is the number of elements in the array, with decent constants as well.
Here is a rotate in place (doesn't use a second array), with O(a.length) time complexity. On my system (Intel 3770K 3.5ghz), it can rotate a 2^28 = 268,435,456 element array in .17 (rotate 76) to .85 seconds (rotate 1). The swaps are done in sequential access sequences, which is cache friendly.
// rotate in place
public static void rolip(int[] a, int r){
r = r % a.length;
if(r == 0)
return;
int t;
int n = a.length - r;
int i = 0;
int j;
while(true){
if(r <= n){ // shift left r places
for(j = i+r; i < j; i++){
t = a[i]; // swap(a[i], a[i+r])
a[i] = a[i+r];
a[i+r] = t;
}
n -= r;
if(n == 0)
break;
} else { // shift right n places
i += r;
for(j = i+n; i < j; i++){
t = a[i]; // swap(a[i], a[i-n])
a[i] = a[i-n];
a[i-n] = t;
}
i -= n+r;
r -= n;
if(r == 0)
break;
}
}
}
Simple rotate using a second array. On my system (Intel 3770K 3.5ghz), it can rotate a 2^28 = 268,435,456 element array in .11 to .50 seconds.
public static void rol(int[] a, int r){
r = r % a.length;
if(r == 0)
return;
int n = a.length - r;
int i;
int j;
if(r <= n){ // if left rotate
int[] b = new int[r]; // save elements
for(j = 0; j < r; j++)
b[j] = a[j];
for(i = 0; i < n; i++) // shift elements
a[i] = a[j++];
for(j = 0; j < r; j++) // copy saved elements
a[i++] = b[j];
} else { // else right rotate
int[] b = new int[n]; // save elements
i = 0;
for(j = r; j < a.length; j++)
b[i++] = a[j];
i = j-1; // shift elements
for(j = i-n; j >= 0; j--)
a[i--] = a[j];
for(j = 0; j < n; j++) // copy saved elements
a[j] = b[j];
}
}
You don't need to do it for every iteration. Instead you can create a formula to figure out where every element would go.
For example, let's say that the size of your array is n.
Then, if you need to move your array to the left by 1 iteration, then an element at position p would be at (p + 1) % n position.
For i iterations, every element would be at (p + i) % n location. So, a loop for every iteration is not needed.
static int[] rotLeft(int[] a, int iterations) {
int[] answer = new int[a.length];
for(int i=0;i<a.length;i++)
{
answer[i] = a[(i - iterations + a.length) % (a.length)];
}
return answer;
}
What about this:
static int leftRotate(int arr[], int iterations,
int k)
{
/* To get the starting point of
rotated array */
int mod = k % iterations;
// Prints the rotated array from
// start position
for(int i = 0; i < iterations; ++i)
System.out.print(arr[(i + mod) % iterations]
+ " ");
System.out.println();
}
leftRotate(arr, iterations, arr.length);
Ref: https://www.geeksforgeeks.org/print-left-rotation-array/
I have trouble converting negative array elements into absolute. So far ive made array containing both negative and positive, but i have to convert them into absolute, in order to calculate array square root. Any suggestions?
public static void main(String[] args) {
int min = -100;
int max = 100;
int[] array = new int[201];
for (int i = 0; i < array.length; i++) {
array[i] = min + (int) (Math.random() * ((max - min) + 1));
//System.out.println(array[i]);
}
int[] array2 = new int[array.length];
for (int j = 2; j < array.length; j += 3) {
array2[j] = array[j];
//System.out.println(array[j]);
double[] result = new double[array2.length];
for (int i = 0; i < array2.length / 3; i++) {
array2[i] = Math.abs(i);
result[j] = Math.sqrt(array[j]);
System.out.println(array[i]);
}
your third-last line is wrong, you need:
result[j] = Math.sqrt(array2[j]);
You're calling Math.abs() on i (the index) not on the array element. Also, you are storing the result of abs into array2[i] and then calling Math.sqrt() on a different array and element (array[j]). Also check if your for loop indexes iterate the fields in the way you want (to me the for loop statements seem somewhat strange).
You have to clearly describe your intentions,
it is no clear that you want each third element of the array and not every one of them.
However there are multiple ways to achive the result.
You can create a List to store square root of each third element
List<Double> result1 = new ArrayList<>();
for (int j = 2; j < array.length; j += 3) {
result1.add(Math.sqrt(Math.abs(array[j])));
}
If you would like to use arrays make it like so
double[] result2 = new double[array.length / 3];
for (int j = 2; j < array.length; j += 3) {
result2[j / 3] = Math.sqrt(Math.abs(array[j]));
}
In both examples we call Math.abs to get the absolute value and Math.sqrt to get square root.
Here is the full code
public static void main(String args[])
{
int min = -100;
int max = 100;
int[] array = new int[201];
for (int i = 0; i < array.length; i++) {
array[i] = min + (int) (Math.random() * ((max - min) + 1));
}
List<Double> result1 = new ArrayList<>();
for (int j = 2; j < array.length; j += 3) {
result1.add(Math.sqrt(Math.abs(array[j])));
}
double[] result2 = new double[array.length / 3];
for (int j = 2; j < array.length; j += 3) {
result2[j / 3] = Math.sqrt(Math.abs(array[j]));
}
System.out.println(result1);
System.out.println(Arrays.toString(result2));
}
static double [][] initialArray = {{7.432, 8.541, 23.398, 3.981}, {721.859, 6.9211, 29.7505, 53.6483}, {87.901, 455.72, 91.567, 57.988}};
public double[] columnSum(double [][] array){
int index = 0;
double temp[] = new double[array[index].length];
for (int i = 0; i < array[i].length; i++){
double sum = 0;
for (int j = 0; j < array.length; j++){
sum += array[j][i];
}
temp[index] = sum;
System.out.println("Index is: " + index + " Sum is: "+sum);
index++;
}
return temp;
}
public static void main(String[] args) {
arrayq test = new arrayq();
test.columnSum(initialArray);
}
I want to get the sum of all the columns, but I keep getting an outofbounds exception. This is the output I get:
Index is: 0 Sum is: 817.192
Index is: 1 Sum is: 471.18210000000005
Index is: 2 Sum is: 144.7155
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at NewExam.arrayq.columnSum(arrayq.java:11)
Your outer for loop condition is giving you problems. Here's your loop: -
for (int i = 0; i < array[i].length; i++)
Now, when i reaches the value 3, you are trying to access array[3].length. This will throw you IndexOutOfBounds exception.
Since the size of every internal arrays are same, you can change your loop to: -
for (int i = 0; i < array[0].length; i++)
Or, even better, just store the array[0].length in some variable before hand. But that will not make much of a difference.
I would also suggest you to use a better way to calculate the sum of columns. Avoid iterating over rows first. Keep the iteration a normal one probably like this: -
public double[] columnSum(double [][] array){
int size = array[0].length; // Replace it with the size of maximum length inner array
double temp[] = new double[size];
for (int i = 0; i < array.length; i++){
for (int j = 0; j < array[i].length; j++){
temp[j] += array[i][j]; // Note that, I am adding to `temp[j]`.
}
}
System.out.println(Arrays.toString(temp));
return temp; // Note you are not using this return value in the calling method
}
So, you can see that how your problem is highly simplified. What I did is, rather than assigning the value to the array, I added the new value of array[i][j] to the existing value of temp[j]. So, gradually, the value of array[i][j] for all i's (rows) gets summed up in temp[j]. This way you don't have to use confusing iteration. So, just add the above code to your method, and remove the old one.
This method will also work fine, even if you have jagged-array, i.e., you inner arrays are not of same size. But just remember to define the size of temp array carefully.
Also note that, I have used Arrays.toString(temp) method to print the array.
Problem with your code is when it tries to fetch arr[3].length as there does not exist simple solution like sum = sum+arr[i][j] where i refers to row and j refers to column.
int row = arr.length;
int col = arr[0].length;
for(int j = 0; j < cols; j++)
{
int sum = 0;
for(int i = 0; i < rows; i++)
{
sum = sum + input[i][j];
}
}
for (int i = 0; i < array[i].length; i++)
for(int i=0;i<size;i++)
i & size must never be change in the loop
So close. The problem is that you are using array[i].length in your for loop. I changed it from array[i].length to array[0].length and your problem is gone. You need j there but you don't actually HAVE it yet.
You COULD do something like this although there isn't really any point if you know how you are going to get your array. Differently sized lists still would break the code for calculating sum though, you'd have to change that as well.
for (int i = 0, j = 0; i < initialArray[j].length; i++) {
for (; j < initialArray.length; j++) {
System.out.println(i + " " + j);
}
j = 0;
}
And here is your modified program.
public class Main {
static double[][] initialArray = { { 7.432, 8.541, 23.398, 3.981 }, { 721.859, 6.9211, 29.7505, 53.6483 }, { 87.901, 455.72, 91.567, 57.988 } };
public double[] columnSum(double[][] array) {
int index = 0;
double temp[] = new double[array[index].length];
for (int i = 0; i < array[0].length; i++) {
double sum = 0;
for (int j = 0; j < array.length; j++) {
sum += array[j][i];
}
temp[index] = sum;
System.out.println("Index is: " + index + " Sum is: " + sum);
index++;
}
return temp;
}
public static void main(String[] args) {
new Main().columnSum(initialArray);
}
}
for index = 3, i is also equal with 3 and you have array[i].length in your code, but array have 3 item so you get Exception on array[3].length expression
try it
public double[] columnSum(double [][] array){
double temp[] = new double[array[0].length];
for (int i = 0; i < array[0].length; i++){
double sum = 0;
for (int j = 0; j < array.length; j++){
sum += array[j][i];
}
temp[i] = sum;
System.out.println("Index is: " + i + " Sum is: "+sum);
}
return temp;
}