Check every permutation of a number for primality - java

I'm working on this problem https://projecteuler.net/problem=49 .
This is the function to check every permutation of a number(4 digit) passed to it, and check them for primality, and if there are more than 2 (ie 3) print the numbers.
the output I'm getting is a never ending sequence of numbers. What am I doing wrong?
P.s- pretty sure it has to do with the repetition of digits, can't figure out how to work around it.
void checkperm(int a) {
int w, x, y, z = 0;
int count = 0;
w = a % 10;
x = (a % 100 - w) / 10;
y = (a % 1000 - (10 * x + w) / 100);
z = a - (y * 100 + x * 10 + w)/1000;
System.out.println(w+x+y+z); /*test*/
int[] data;
data = new int[] { w, x, y, z };
int[] num = new int[100];
for (int m = 0; m < 4; m++) {
for (int n = 0; n < 4; n++) {
for (int o = 0; o < 4; o++) {
for (int p = 0; p < 4; p++) {
if (true) {
int gnaw = 1000 * data[m] + 100 * data[n] + 10 * data[o] + data[p];
if (checkprime(gnaw)) {
num[count] = gnaw;
count++;
}
}
}
}
}
}
if (count > 2)
for (int h = 0; h < 4; h++) {
System.out.println(num[h]);
}
}

the way you're calculating w, x, y and z is wrong.
what it should be -
int temp = a;
w = temp%10;
temp = temp/10;
x = temp%10;
temp = temp/10;
y = temp%10;
temp = temp/10;
z = temp;
This is just logic correction from your code. Ideally all this should happen in a loop.
This will help assuming your rest of code is logically correct (which I haven't gone through).

Related

Algorithm to calculate values based on linear equations

I am working to calculate values of various Paycodes in a PayStructure based on linear equations using java. My different equations are as below:
CTC = Fixed Value
Basic = CTC * 0.4
HRA = Basic/2
ConveyanceAllowance = Fixed Value
ProvidentFund = Basic * 0.12
Gratuity = Basic * .0481
OtherAllowance = (CTC - (Basic + HRA + ConveyanceAllowance + ProvidentFund + Gratuity))
I have tried using the solution given here. But this solution will only work in case all the calculated values are integers and in my case, the values could contain decimal figures as well. My modified code as per the above conditions is as below:
public class PayStructure {
public static void main(String[] args) {
findAndprintSolutions(1, 1000000);
}
private static void findAndprintSolutions(int from, int to) {
for (int a = from; a < to; a++) {
for (int b = from; b < to; b++) {
for (int c = from; c < to; c++) {
for (int d = from; d < to; d++) {
for (int e = from; e < to; e++) {
for (int f = from; f < to; f++) {
for (int g = from; g < to; g++) {
if (isSolution(a, b, c, d, e, f, g))
printSolution(new int[] { a, b, c, d, e, f, g });
}
}
}
}
}
}
}
}
private static boolean isSolution(int a, int b, int c, int d, int e, int f, int g) {
if (a != 100000)
return false;
if (b != a * (.4))
return false;
if (c != b / 2)
return false;
if (d != 10000)
return false;
if (e != b * (.12))
return false;
if (f != b * (.0481))
return false;
if (g != (a - (b + c + d + e + f)))
return false;
return true;
}
private static void printSolution(int[] variables) {
StringBuilder output = new StringBuilder();
for (int variable : variables) {
output.append(variable + ", ");
}
output.deleteCharAt(output.length() - 1);
output.deleteCharAt(output.length() - 1);
System.out.println(output.toString());
}
}
Moreover the above mentioned code will be terminated as the maximum value of CTC could be millions and depending on the number of variables, time complexity will end up to be millions^NumberOfVariables. Is there any other possibility to calculate the values based on the given equations? The number of equations and variables could vary but there will be a solution to calculate value of each variable, so any inputs for a generic solution would be better.
E.g.: If CTC = 100000 and ConveyanceAllowance = 10000, the code should return the output as:
Basic = 40000
HRA = 20000
ProvidentFund = 4800
Gratuity = 1924
OtherAllowance = 23276
Maybe your best bet would be to figure out how to get this into the form of a system of linear equations of the form c[1]x[1] + c[2]x[2] … + c[n]x[n] = 0. From there, you can solve the system using widely established techniques for linear systems. See the Wikipedia page for lots of information. You could either have the users provide input to your method in this form, or you could do a small amount of processing on each equation to transform it (e.g., if all the equations have one variable on the LHS as in your example, flip the sign and put it on the end of the RHS).
Explaining the theory of solving a system of linear equations is beyond the scope of this answer but, basically, your system will either be uniquely determined if there is one valid assignment, overdetermined if no valid assignment exists, or underdetermined if infinitely many assignments are possible. If there is a unique assignment you will get numbers; if the system is underdetermined you'll at least get a set of constraints that must hold of any of the infinitely many solutions; if underdetermined, you'll get nothing and know why.
Use the some linear algebra library for Java. Solve the system of linear equations using matrix operations as documented here, for instance. Your deeply nested loop is too slow, there are much better algorithms available.
This is how I solved this. Firstly I created equations by taking all the variables to the left side and values & 0 to the right side:
CTC = 1000000
(0.4)CTC - Basic = 0
(0.5)Basic-HRA = 0
ConvAll = 10000
(0.12)Basic-PF = 0
(0.0481)Basic - Gratuity = 0
CTC - (Basic + HRA + ConvAll + PF+ Gratuity + OtherAll) = 0
Then I created a matrix like this:
|1 0 0 0 0 0 0| |CTC | = |1000000|
|0.4 -1 0 0 0 0 0| |Basic | = |0 |
|0 0.5 -1 0 0 0 0| |HRA | = |0
|0 0 0 1 0 0 0| |ConvAll | = |10000 |
|0 0.12 0 0 -1 0 0| |PF | = |0 |
|0 0.0481 0 0 0 -1 0| |Gratuity| = |10000 |
|1 -1 -1 -1 -1 -1 -1| |OtherAll| = |0 |
After this, I calculated the product of (inverse of above 1st matrix) and (right most matrix) and got the corresponding values of each component using the below code:
public class Matrix
{
static int n = 0;
public static void main(String argv[]) {
Scanner input = new Scanner(System.in);
System.out.println("Enter the dimension of square matrix: ");
n = input.nextInt();
double a[][] = new double[n][n];
System.out.println("Enter the elements of matrix: ");
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
a[i][j] = input.nextDouble();
double d[][] = invert(a);
System.out.println();
System.out.println("Enter the equation values: ");
System.out.println();
double b[][] = new double[n][1];
for (int i = 0; i < n; i++) {
b[i][0] = input.nextDouble();
}
double e[][] = multiplyMatrix(d, b);
System.out.println();
System.out.println("The final solution is: ");
System.out.println();
for (int i = 0; i < n; i++) {
for (int j = 0; j < 1; j++) {
System.out.printf(e[i][j] + " ");
}
System.out.println();
}
input.close();
}
public static double[][] invert(double a[][]) {
int n = a.length;
double x[][] = new double[n][n];
double b[][] = new double[n][n];
int index[] = new int[n];
for (int i = 0; i < n; ++i)
b[i][i] = 1;
// Transform the matrix into an upper triangle
gaussian(a, index);
// Update the matrix b[i][j] with the ratios stored
for (int i = 0; i < n - 1; ++i)
for (int j = i + 1; j < n; ++j)
for (int k = 0; k < n; ++k)
b[index[j]][k] -= a[index[j]][i] * b[index[i]][k];
// Perform backward substitutions
for (int i = 0; i < n; ++i) {
x[n - 1][i] = b[index[n - 1]][i] / a[index[n - 1]][n - 1];
for (int j = n - 2; j >= 0; --j) {
x[j][i] = b[index[j]][i];
for (int k = j + 1; k < n; ++k) {
x[j][i] -= a[index[j]][k] * x[k][i];
}
x[j][i] /= a[index[j]][j];
}
}
return x;
}
// Method to carry out the partial-pivoting Gaussian
// elimination. Here index[] stores pivoting order.
public static void gaussian(double a[][], int index[]) {
int n = index.length;
double c[] = new double[n];
// Initialize the index
for (int i = 0; i < n; ++i)
index[i] = i;
// Find the rescaling factors, one from each row
for (int i = 0; i < n; ++i) {
double c1 = 0;
for (int j = 0; j < n; ++j) {
double c0 = Math.abs(a[i][j]);
if (c0 > c1)
c1 = c0;
}
c[i] = c1;
}
// Search the pivoting element from each column
int k = 0;
for (int j = 0; j < n - 1; ++j) {
double pi1 = 0;
for (int i = j; i < n; ++i) {
double pi0 = Math.abs(a[index[i]][j]);
pi0 /= c[index[i]];
if (pi0 > pi1) {
pi1 = pi0;
k = i;
}
}
// Interchange rows according to the pivoting order
int itmp = index[j];
index[j] = index[k];
index[k] = itmp;
for (int i = j + 1; i < n; ++i) {
double pj = a[index[i]][j] / a[index[j]][j];
// Record pivoting ratios below the diagonal
a[index[i]][j] = pj;
// Modify other elements accordingly
for (int l = j + 1; l < n; ++l)
a[index[i]][l] -= pj * a[index[j]][l];
}
}
}
public static double[][] multiplyMatrix(double a[][], double b[][]) {
double c[][] = new double[n][1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < 1; j++) {
for (int k = 0; k < n; k++) {
c[i][j] = c[i][j] + a[i][k] * b[k][j];
}
}
}
return c;
}
}
Thank you all for the leads.

Matrix multiplication issue

I have this problem, i have a NxM matrix and i want to multiply it by a 3x3 matrix just as a convolutional matrix multiplication
example in this link
This are the code of the matrix:
int width = img.getWidth();
int height = img.getHeight();
int matrix[][] = new int[width][height];
int edgeMatrix[][] = {
{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}
};
This is the code of the cycle:
for (int x = 0; x < width; x++) {
w = 0;
holderX = x;
for (w = 0; w < 3; w++) {
v = 0;
if (w > 0)
x++;
for (v = 0; v < 3; v++) {
sum = sum + matrix[v][x] * edgeMatrix[v][w];
if (w == 2 && v == 2)
x = holderX;
}
}
}
This cycle already multiply the first "row" of 3 of the matrix.
T tried in a different ways to achieve this but i just cant get that when the matrix reach the end of the width automatically the N value increase one and then starts over again and in the same time the value still working on the internal matrix multiplication.
Thanks for the help.
You dont need holderX, but need one more loop.
int width = img.getWidth();
int height = img.getHeight();
int input[][] = img.getPixels(); // or whatever api you use
int output[][] = new int[height][width];
int kernel[][] = {
{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}
};
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int accumulator = 0;
for (int v = 0; v < 3; v++) {
for (int w = 0; w < 3; w++) {
int sy = y + v - 1;
int sx = x + w - 1;
if (sy >= 0 && sy < height && sx >= 0 && sx < width)) {
accumulator += input[sy][sx] * kernel[v][w];
}
}
}
output[sy][sx] = accumulator;
}
}

Program to generate and print all the "anagrams" of a number without using array

This is a Java program to generate and print all the possible "Anagrams" of a four digit number without using an array. Here is what I've been able to do so far:
import java.util.*;
class Anag {
public static void main() {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int d = n % 10;
n = n / 10;
int c = n % 10;
n = n / 10;
int b = n % 10;
n = n / 10;
int a = n;
int w = a, x = b, y = c, z = d, co, i, j;
System.out.println(w * 1000 + x * 100 + y * 10 + z * 1);
for (i = 1; i <= 4; i++) {
for (j = 1; j <= 3; j++) {
if (j % 3 == 1) {
co = w;
w = x;
x = co;
System.out.println(w * 1000 + x * 100 + y * 10 + z * 1);
}
if (j % 3 == 2) {
co = x;
x = y;
y = co;
System.out.println(w * 1000 + x * 100 + y * 10 + z * 1);
}
if (j % 3 == 0) {
co = y;
y = z;
z = co;
System.out.println(w * 1000 + x * 100 + y * 10 + z * 1);
}
}
}
}
}
Using the above code, I've been able to generate 12 "Anagrams", but I cannot figure out how to generate the remaining 12 (there should be 24 in total). Does anyone have any ideas?
The following algorithm should work for you. In short, you shiftrotate the number and for every 4 anagrams you swap first two digits, but after the 12th anagram you swap 1st and 3rd digit.
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int d = n % 10;
n = n / 10;
int c = n % 10;
n = n / 10;
int b = n % 10;
n = n / 10;
int a = n;
int t;
for (int i = 0; i < 24; i++) {
System.out.println(a * 1000 + b * 100 + c * 10 + d);
if (i == 11) {
t = a;
a = c;
c = t;
}
if (i % 4 == 3) {
t = a;
a = b;
b = t;
} else {
t = a;
a = b;
b = c;
c = d;
d = t;
}
}
}

Get absolute difference from a picture and template. [Template matching]

I have the two methods which should write pixel values of the absolute difference of a template and the same size patch from the original picture into the pixel where both patch and template coordinates are 0,0.
Here are my 2 methods.
private void normalizeAndDraw(double biggest, double[] temporaryPixels, int[] dstPixels ){
double normalize = 255 / biggest;
for (int c = 0; c < temporaryPixels.length; c++) {
int value = (int) (temporaryPixels[c] * normalize);
dstPixels[c] = 0xFF000000 | (value << 16) | (value << 8) | value;
}
}
private void getAbsolutePicture(int srcPixels[], int srcWidth, int srcHeight, int dstPixels[], int dstWidth, int dstHeight, int templatePixels[], int tmpHeight, int tmpWidth) {
double temporaryPixels[] = new double[dstHeight * dstWidth];
double biggest = 0;
double sumR = 0;
for (int j = 0; j < tmpHeight; j++) {
for (int i = 0; i < tmpWidth; i++) {
int posTmp = j * tmpWidth + i;
sumR += templatePixels[posTmp] & 0xFF;
}
}
for (int y = 0; y < dstHeight; y++) {
for (int x = 0; x < dstWidth; x++) {
double sumI = 0;
for (int j = 0; j < tmpHeight; j++) {
for (int i = 0; i < tmpWidth; i++) {
int pos = (y + j) * dstWidth + (x + i);
sumI += srcPixels[pos] & 0xFF;
}
}
double absDifference = Math.abs(sumI - sumR);
biggest = Math.max(absDifference, biggest);
temporaryPixels[y * dstWidth + x] = absDifference;
}
}
normalizeAndDraw(biggest, temporaryPixels, dstPixels);
}
They get called like this.
getAbsolutePicture(srcPixels, srcWidth, srcHeight, dstPixels, dstWidth, dstHeight, templatePixels, templateWidth, templateHeight);
If values are written into the dstPixels array they will automatically be displayed.
Unfortunately instead of the correct solution which looks like this
http://i.stack.imgur.com/cqlD3.png
I get a result which looks like this
http://i.stack.imgur.com/2Cjhz.png
I am pretty sure that my error lies in the calculation of sumR and sumI but I just cant figure it out?
What exactly is wrong in my code?
My code was actually okay. The biggest problem was that when I called getAbsolutePicture() I mixed up tmpWdith and tmpHeight.

Java code optimization on matrix windowing computes in more time

I have a matrix which represents an image and I need to cycle over each pixel and for each one of those I have to compute the sum of all its neighbors, ie the pixels that belong to a window of radius rad centered on the pixel.
I came up with three alternatives:
The simplest way, the one that recomputes the window for each pixel
The more optimized way that uses a queue to store the sums of the window columns and cycling through the columns of the matrix updates this queue by adding a new element and removing the oldes
The even more optimized way that does not need to recompute the queue for each row but incrementally adjusts a previously saved one
I implemented them in c++ using a queue for the second method and a combination of deques for the third (I need to iterate through their elements without destructing them) and scored their times to see if there was an actual improvement. it appears that the third method is indeed faster.
Then I tried to port the code to Java (and I must admit that I'm not very comfortable with it). I used ArrayDeque for the second method and LinkedLists for the third resulting in the third being inefficient in time.
Here is the simplest method in C++ (I'm not posting the java version since it is almost identical):
void normalWindowing(int mat[][MAX], int cols, int rows, int rad){
int i, j;
int h = 0;
for (i = 0; i < rows; ++i)
{
for (j = 0; j < cols; j++)
{
h = 0;
for (int ry =- rad; ry <= rad; ry++)
{
int y = i + ry;
if (y >= 0 && y < rows)
{
for (int rx =- rad; rx <= rad; rx++)
{
int x = j + rx;
if (x >= 0 && x < cols)
{
h += mat[y][x];
}
}
}
}
}
}
}
Here is the second method (the one optimized through columns) in C++:
void opt1Windowing(int mat[][MAX], int cols, int rows, int rad){
int i, j, h, y, col;
queue<int>* q = NULL;
for (i = 0; i < rows; ++i)
{
if (q != NULL)
delete(q);
q = new queue<int>();
h = 0;
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][rx];
}
}
q->push(mem);
h += mem;
}
}
for (j = 1; j < cols; j++)
{
col = j + rad;
if (j - rad > 0)
{
h -= q->front();
q->pop();
}
if (j + rad < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][col];
}
}
q->push(mem);
h += mem;
}
}
}
}
And here is the Java version:
public static void opt1Windowing(int [][] mat, int rad){
int i, j = 0, h, y, col;
int cols = mat[0].length;
int rows = mat.length;
ArrayDeque<Integer> q = null;
for (i = 0; i < rows; ++i)
{
q = new ArrayDeque<Integer>();
h = 0;
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][rx];
}
}
q.addLast(mem);
h += mem;
}
}
j = 0;
for (j = 1; j < cols; j++)
{
col = j + rad;
if (j - rad > 0)
{
h -= q.peekFirst();
q.pop();
}
if (j + rad < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][col];
}
}
q.addLast(mem);
h += mem;
}
}
}
}
I recognize this post will be a wall of text. Here is the third method in C++:
void opt2Windowing(int mat[][MAX], int cols, int rows, int rad){
int i = 0;
int j = 0;
int h = 0;
int hh = 0;
deque< deque<int> *> * M = new deque< deque<int> *>();
for (int ry = 0; ry <= rad; ry++)
{
if (ry < rows)
{
deque<int> * q = new deque<int>();
M->push_back(q);
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int val = mat[ry][rx];
q->push_back(val);
h += val;
}
}
}
}
deque<int> * C = new deque<int>(M->front()->size());
deque<int> * Q = new deque<int>(M->front()->size());
deque<int> * R = new deque<int>(M->size());
deque< deque<int> *>::iterator mit;
deque< deque<int> *>::iterator mstart = M->begin();
deque< deque<int> *>::iterator mend = M->end();
deque<int>::iterator rit;
deque<int>::iterator rstart = R->begin();
deque<int>::iterator rend = R->end();
deque<int>::iterator cit;
deque<int>::iterator cstart = C->begin();
deque<int>::iterator cend = C->end();
for (mit = mstart, rit = rstart; mit != mend, rit != rend; ++mit, ++rit)
{
deque<int>::iterator pit;
deque<int>::iterator pstart = (* mit)->begin();
deque<int>::iterator pend = (* mit)->end();
for(cit = cstart, pit = pstart; cit != cend && pit != pend; ++cit, ++pit)
{
(* cit) += (* pit);
(* rit) += (* pit);
}
}
for (i = 0; i < rows; ++i)
{
j = 0;
if (i - rad > 0)
{
deque<int>::iterator cit;
deque<int>::iterator cstart = C->begin();
deque<int>::iterator cend = C->end();
deque<int>::iterator pit;
deque<int>::iterator pstart = (M->front())->begin();
deque<int>::iterator pend = (M->front())->end();
for(cit = cstart, pit = pstart; cit != cend; ++cit, ++pit)
{
(* cit) -= (* pit);
}
deque<int> * k = M->front();
M->pop_front();
delete k;
h -= R->front();
R->pop_front();
}
int row = i + rad;
if (row < rows && i > 0)
{
deque<int> * newQ = new deque<int>();
M->push_back(newQ);
deque<int>::iterator cit;
deque<int>::iterator cstart = C->begin();
deque<int>::iterator cend = C->end();
int rx;
int tot = 0;
for (rx = 0, cit = cstart; rx <= rad; rx++, ++cit)
{
if (rx < cols)
{
int val = mat[row][rx];
newQ->push_back(val);
(* cit) += val;
tot += val;
}
}
R->push_back(tot);
h += tot;
}
hh = h;
copy(C->begin(), C->end(), Q->begin());
for (j = 1; j < cols; j++)
{
int col = j + rad;
if (j - rad > 0)
{
hh -= Q->front();
Q->pop_front();
}
if (j + rad < cols)
{
int val = 0;
for (int ry =- rad; ry <= rad; ry++)
{
int y = i + ry;
if (y >= 0 && y < rows)
{
val += mat[y][col];
}
}
hh += val;
Q->push_back(val);
}
}
}
}
And finally its Java version:
public static void opt2Windowing(int [][] mat, int rad){
int cols = mat[0].length;
int rows = mat.length;
int i = 0;
int j = 0;
int h = 0;
int hh = 0;
LinkedList<LinkedList<Integer>> M = new LinkedList<LinkedList<Integer>>();
for (int ry = 0; ry <= rad; ry++)
{
if (ry < rows)
{
LinkedList<Integer> q = new LinkedList<Integer>();
M.addLast(q);
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int val = mat[ry][rx];
q.addLast(val);
h += val;
}
}
}
}
int firstSize = M.getFirst().size();
int mSize = M.size();
LinkedList<Integer> C = new LinkedList<Integer>();
LinkedList<Integer> Q = null;
LinkedList<Integer> R = new LinkedList<Integer>();
for (int k = 0; k < firstSize; k++)
{
C.add(0);
}
for (int k = 0; k < mSize; k++)
{
R.add(0);
}
ListIterator<LinkedList<Integer>> mit;
ListIterator<Integer> rit;
ListIterator<Integer> cit;
ListIterator<Integer> pit;
for (mit = M.listIterator(), rit = R.listIterator(); mit.hasNext();)
{
Integer r = rit.next();
int rsum = 0;
for (cit = C.listIterator(), pit = (mit.next()).listIterator();
cit.hasNext();)
{
Integer c = cit.next();
Integer p = pit.next();
rsum += p;
cit.set(c + p);
}
rit.set(r + rsum);
}
for (i = 0; i < rows; ++i)
{
j = 0;
if (i - rad > 0)
{
for(cit = C.listIterator(), pit = M.getFirst().listIterator();
cit.hasNext();)
{
Integer c = cit.next();
Integer p = pit.next();
cit.set(c - p);
}
M.removeFirst();
h -= R.getFirst();
R.removeFirst();
}
int row = i + rad;
if (row < rows && i > 0)
{
LinkedList<Integer> newQ = new LinkedList<Integer>();
M.addLast(newQ);
int rx;
int tot = 0;
for (rx = 0, cit = C.listIterator(); rx <= rad; rx++)
{
if (rx < cols)
{
Integer c = cit.next();
int val = mat[row][rx];
newQ.addLast(val);
cit.set(c + val);
tot += val;
}
}
R.addLast(tot);
h += tot;
}
hh = h;
Q = new LinkedList<Integer>();
Q.addAll(C);
for (j = 1; j < cols; j++)
{
int col = j + rad;
if (j - rad > 0)
{
hh -= Q.getFirst();
Q.pop();
}
if (j + rad < cols)
{
int val = 0;
for (int ry =- rad; ry <= rad; ry++)
{
int y = i + ry;
if (y >= 0 && y < rows)
{
val += mat[y][col];
}
}
hh += val;
Q.addLast(val);
}
}
}
}
I guess that most is due to the poor choice of the LinkedList in Java and to the lack of an efficient (not shallow) copy method between two LinkedList.
How can I improve the third Java method? Am I doing some conceptual error? As always, any criticisms is welcome.
UPDATE Even if it does not solve the issue, using ArrayLists, as being suggested, instead of LinkedList improves the third method. The second one performs still better (but when the number of rows and columns of the matrix is lower than 300 and the window radius is small the first unoptimized method is the fastest in Java)
UPDATE2 Which tool can I use to profile my code and have a richer understanding of which instruction takes the most time? I'm on Mac OS X and using NetBeans Profiler just shows me that the three methods end up with different times (It seems I'm not able to scope within each method)
UPDATE3 I'm scoring the times in java using System.nanoTime() can this lead to inaccurate estimates?:
long start, end;
start = System.nanoTime();
simpleWindowing(mat, rad);
end = System.nanoTime();
System.out.println(end-start);
start = System.nanoTime();
opt1Windowing(mat, rad);
end = System.nanoTime();
System.out.println(end-start);
start = System.nanoTime();
opt2Windowing(mat, rad);
end = System.nanoTime();
System.out.println(end-start);
LinkedList is a very bad choice for a list with where you do random access.
For each get(int) scans the list until the request index is reached.
get(1) is quite fast, but get(100) is 100 times slower and get(1000) is a 1000 times slower than get(1)
You should change that to use ArrayList instead and initialize the ArrayList with the expected size to avoid unnecessary resizing of the internal Array.
Edit
While my coments about get() and LinkedList are correct, they do not apply in this context. I somehow overlooked that there is no random access to the list.
Use an int[] instead of a List.
Lists store Objects requiring a conversion from int to Integer and back.
I indeed implemented two optimized versions for that routine:
the first one, as User216237 suggested, makes use of an array of int as a queue to cache the summed column values as the algorithm scans the image by columns
the other one implements a Summed Area Table in order to compute every rectangualar area of sums by accessing this table just four times (It is independent from the window radius).
One technique can be arbitrary faster than the other according to the specific domain in which it is implemented. In mine, the summed area table had to be computed several times and so it resulted slower than the first method for a radius value lesser than 20 pixel.
About timing your code: System.nanoTime() is ok (i don't think you can get better since it's using OS timers as far as i know), but:
don't try to measure too short of a task, then the accuracy isnt so good. I think anything less than a few milliseconds will give you potential trouble. References, anyone?
measure multiple times, and take the median of the measurements. Outside effects can severely slow the execution, making your estimation useless. Taking the mean doesn't work too well because it is sensitive to such outliers.
many JVMs have JIT compiler, you may want to execute your code multiple times before you measure, so the compiler doesn't kick in somewhere in the middle of your measurement and half of your measurements are suddenly 10x faster than the rest. Better measure after your VM has "warmed up".

Categories

Resources