Java: How to add variable in a loop together, multiple times - java

public class R {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
int x = 0;
int y = 0;
int j = 0;
int distance = 0;
while (trials>j) {
j = j + 1;
int i = -1;
double counter = 1.0 * distance;
double sum = (distance + counter);
while (i<=n) {
i = i + 1;
if (i == n) {
distance = ((x*x) + (y*y));
}
if (i<n) {
int random = (int )(Math.random() * 4 + 1);
if (random == 1) x = x + 1;
if (random == 2) y = y + 1;
if (random == 3) x = x - 1;
if (random == 4) y = y - 1;
}
}
}
double average= (sum)/(trials);
System.out.println("mean " + "squared " + "distance " + "= " + average);
}
}
Hey guys I'm wondering how it's possible to compute a value within a loop, and then every single time the loop finishes (and the value in computed) to average them together. I can't wrap my head around the concept and I tried doing it in the code above but I can't quite figure it out.
As you can see there are two while loops, and inside one of them a random value (distance) is computed. So essentially I need to average the distances together, but I can't imagine how it's possible to add the distances that are computed each time together into one number. Let's say the loop goes through one time and outputs a singular distance, how would I go about adding a new distance (for the new loop) together with the old one, and then keep doing that for each trial?

You just have to divide the total distance per trials.
public class R {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
int x = 0;
int y = 0;
int j = 0;
int distance = 0, distance_total = 0;
while (trials>j) {
j = j + 1;
int i = -1;
distance = 0;
while (i<=n) {
i = i + 1;
if (i == n) {
distance += ((x*x) + (y*y));
}
if (i<n) {
int random = (int )(Math.random() * 4 + 1);
if (random == 1) x = x + 1;
if (random == 2) y = y + 1;
if (random == 3) x = x - 1;
if (random == 4) y = y - 1;
}
}
distance_total += distance;
}
System.out.println(distance_total/j);
}
}

Related

Java program not outputting correct values

I'm trying to create a simple program that determines if a number can be written as n^x and what n and x are. Ex: 81 = 3^4. My program correctly identifies numbers that can be written as n^x but the values for n and x are way off. (this is just supposed to be an exercise). The logic in my coding is kind of confusing so here's basically what it is. First it finds a number that can divide into a (the chosen number), then it figures out if the a can be divided by the number until it reaches 1. Then it figures out how many times it takes to reach 1. I can't find any problems with the logic. Here's my code.
public static void main(String[] args) {
Scanner scan1 = new Scanner(System.in);
int a = scan1.nextInt();
scan1.close();
int i = 2;
boolean y = false;
int x = 0;
for (; i <= Math.sqrt(a); i++) {
if (a % i == 0) {
int n = i;
for (; n <= a; n *= i) {
if (a % n != 0) {
y = false;
break;
}
x++;
y = true;
}
}
}
if (y == true) {
System.out.println(a + " = " + i + " ^ " + x);
}
else {
System.out.println("Your number cannot be represented as n^x");
}
}
public static void main(String[] args) {
Scanner scan1 = new Scanner(System.in);
int a = scan1.nextInt();
scan1.close();
int i = 2;
boolean y = false;
int x = 0;
for(; i <= Math.sqrt(a); i++) {
if (a % i == 0) {
int n = i;
for (; n <= a; n *= i) {
if (a % n != 0) {
y = false;
}
y = true;
x = n;
break;
}
}
}
i--;
if (y == true) {
System.out.println(a + " = " + i + " ^ " + x);
}
else {
System.out.println("Your number cannot be represented as n^x");
}
}
Use a do-while for the outer loop and you won't need i--; at the end.

How to solve for eigenvectors of a 2x2 Matrix using Java

I'm trying to solve for the eigenvectors of a 2x2 matrix. As of right now, I'm only considering real matrices whose eigenvectors and eigenvalues are also real. I'm currently having issues solving for the eigenvectors.
This is what I have so far:
public double[] getBasis(double[][] basis){
double a = basis[0][0];
double b = basis[0][1];
double c = basis[1][0];
double d = basis[1][1];
double eigenvalue1 = ((a+d) + Math.sqrt( Math.pow(a-d,2) + 4*b*c))/2;
double eigenvalue2 = ((a+d) - Math.sqrt( Math.pow(a-d,2) + 4*b*c))/2;
double tempx;
double tempy;
int counter = 1;
for (double y = -1000; y <= 1000; y++) {
for (double x = -1000; x <= 1000; x++) {
if (((a-eigenvalue1)*x + b*y == 0) && (c*x + (d-eigenvalue1)*y == 0)) {
tempx = x;
tempy = y;
System.out.println("Eigenvector1: (" + x + "," + y + ")");
System.out.println("Eigenvalue1: "+ eigenvalue1);
}
}
}
for (double y = -10; y <= 10; y++) {
for (double x = -10; x <= 10; x++) {
if (((a-eigenvalue2)*x + b*y == 0) && (c*x + (d-eigenvalue2)*y == 0)) {
tempx = x;
tempy = y;
System.out.println("Eigenvector2: (" + x + "," + y + ")");
System.out.println("Eigenvalue2: " + eigenvalue2);
}
}
}return eigenvector1;
}
}
This method should have an input of a 2x2 array and i want it to output the two normalized eigenvectors. How would I be able to output both the eigenvectors?Additionally, I'm not allowed to use any packages that can solve for the eigenvectors or values. Basic math and arithmetic is perfectly acceptable.
Output:
Eigenvector1: (0.0,0.0)
Eigenvector1: (1.0,1.0)
Eigenvector1: (2.0,2.0)
Eigenvector1: (3.0,3.0)
Eigenvector1: (4.0,4.0)
Eigenvector1: (5.0,5.0)
Eigenvector1: (6.0,6.0)
Eigenvector1: (7.0,7.0)
Eigenvector1: (8.0,8.0)
Eigenvector1: (9.0,9.0)
Eigenvector1: (10.0,10.0)
Eigenvector2: (0.0,0.0)
How would I be able to choose only one vector for eigenvector 1 and eigenvector 2. Additionally, If the matrix had input (1,1,1,-1) such that it was a 2x2 matrix then the eigenvalues should be the square root of positive and negative 2. I'm able to get that far. However, once I attempt to calculate the eigenvectors I don't get a value for an eigenvector.
**Edited: I added the errors and took out the infinite loop I got stuck on before
**
There is no need to solve the linear system for the eigenvectors with a trial-and-error loop.
The equation
(a-e)*x+b*y == 0
has always the solution
x = b, y = -(a-e)
which you then would have to normalize. You will need to check if the first equation has the coefficients all zero, then you have to use the second equation
c*x + (d-e)*y == 0
with solution
x = -(d-e), y = c
If also the second equation has all zero coefficients, then any vector is an eigenvector, as the matrix is the diagonal matrix diag([e, e]).
This should result in some code like
e = eigenvalue1;
x = b; y = e-a;
r = Math.sqrt(x*x+y*y)
if( r > 0) { x /= r; y /= r; }
else {
x = e-d; y = c;
r = sqrt(x*x+y*y)
if( r > 0) { x /= r; y /= r; }
else {
x = 1; y = 0;
}
}
System.out.println("Eigenvector1: (" + x + "," + y + ")");
e = eigenvalue2;
x = b; y = e-a;
r = Math.sqrt(x*x+y*y)
if( r > 0) { x /= r; y /= r; }
else {
x = e-d; y = c;
r = sqrt(x*x+y*y)
if( r > 0) { x /= r; y /= r; }
else {
x = 0; y = 1;
}
}
System.out.println("Eigenvector2: (" + x + "," + y + ")");
According to your edit comments, I think this revised code should produce what you want. I've removed your temp variables and I'm returning your computed basis values as a 2 element array. Excuse me if I've misnamed anything, my maths is a little rusty.
public static void main(String[] args) {
// the input matrix
double[][] matrix = {
{1.0, 1.0},
{1.0, -1.0}
};
// compute the basis
double[] basis = getBasis(matrix);
System.out.println("Basis: (" + basis[0] + ", " + basis[1] + ")");
}
public double[] getBasis(double[][] matrix){
double a = matrix[0][0];
double b = matrix[0][1];
double c = matrix[1][0];
double d = matrix[1][1];
double eigenvalue1 = ((a+d) + Math.sqrt( Math.pow(a-d,2) + 4*b*c))/2;
double eigenvalue2 = ((a+d) - Math.sqrt( Math.pow(a-d,2) + 4*b*c))/2;
// store the basis in a 2 element array
double[] basis = new double[2];
for (double y = -1000; y <= 1000; y++) {
for (double x = -1000; x <= 1000; x++) {
if (((a-eigenvalue1)*x + b*y == 0) && (c*x + (d-eigenvalue1)*y == 0)) {
System.out.println("Eigenvector1: (" + x + "," + y + ")");
basis[0] = eigenvalue1;
}
}
}
for (double y = -10; y <= 10; y++) {
for (double x = -10; x <= 10; x++) {
if (((a-eigenvalue2)*x + b*y == 0) && (c*x + (d-eigenvalue2)*y == 0)) {
System.out.println("Eigenvector2: (" + x + "," + y + ")");
basis[1] = eigenvalue2;
}
}
}
return basis;
}
Output:
Basis: (1.4142135623730951, -1.4142135623730951)

How can I optimize my java implementation of Held-Karp algorithm to shorten the running time?

I use Java implemented Held-KarpTSP algorithm algo to solve a 25 cities TSP problem.
The program passes with 4 cities.
When it runs with 25 cities it won't stop for several hours. I use jVisualVM to see what's the hotspot, after some optimization now it shows
98% of time is in real computing instead in Map.contains or Map.get.
So I'd like to have your advice, and here is the code:
private void solve() throws Exception {
long beginTime = System.currentTimeMillis();
int counter = 0;
List<BitSetEndPointID> previousCosts;
List<BitSetEndPointID> currentCosts;
//maximum number of elements is c(n,[n/2])
//To calculate m-set's costs just need to keep (m-1)set's costs
List<BitSetEndPointID> lastKeys = new ArrayList<BitSetEndPointID>();
int m;
if (totalNodes < 10) {
//for test data, generate them on the fly
SetUtil3.generateMSet(totalNodes);
}
//m=1
BitSet beginSet = new BitSet();
beginSet.set(0);
previousCosts = new ArrayList<BitSetEndPointID>(1);
BitSetEndPointID beginner = new BitSetEndPointID(beginSet, 0);
beginner.setCost(0f);
previousCosts.add(beginner);
//for m=2 to totalNodes
for (m = 2; m <= totalNodes; m++) {// sum(m=2..n 's C(n,m)*(m-1)(m-1)) ==> O(n^2 * 2^n)
//pick m elements from total nodes, the element id is the index of nodeCoordinates
// the first node is always present
BitSet[] msets;
if (totalNodes < 10) {
msets = SetUtil3.msets[m - 1];
} else {
//for real data set, will read from serialized file
msets = SetUtil3.getMsets(totalNodes, m-1);
}
currentCosts = new ArrayList<BitSetEndPointID>(msets.length);
//System.out.println(m + " sets' size: " + msets.size());
for (BitSet mset : msets) { //C(n,m) mset
int[] candidates = allSetBits(mset, m);
//mset is a BitSet which makes sure begin point 0 comes first
//so end point candidate begins with 1. candidate[0] is always begin point 0
for (int i = 1; i < candidates.length; i++) { // m-1 bits are set
//set the new last point as j, j must not be the same as begin point 0
int j = candidates[i];
//middleNodes = mset -{j}
BitSet middleNodes = (BitSet) mset.clone();
middleNodes.clear(j);
//loop through all possible points which are second to the last
//and get min(A[S-{j},k] + k->j), k!=j
float min = Float.MAX_VALUE;
int k;
for (int ki = 0; ki < candidates.length; ki++) {// m-1 calculation
k = candidates[ki];
if (k == j) continue;
float middleCost = 0;
BitSetEndPointID key = new BitSetEndPointID(middleNodes, k);
int index = previousCosts.indexOf(key);
if (index != -1) {
//System.out.println("get value from map in m " + m + " y key " + middleNodes);
middleCost = previousCosts.get(index).getCost();
} else if (k == 0 && !middleNodes.equals(beginSet)) {
continue;
} else {
System.out.println("middleCost not found!");
continue;
// System.exit(-1);
}
float lastCost = distances[k][j];
float cost = middleCost + lastCost;
if (cost < min) {
min = cost;
}
counter++;
if (counter % 500000 == 0) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException iex) {
System.out.println("Who dares interrupt my precious sleep?!");
}
}
}
//set the costs for chosen mset and last point j
BitSetEndPointID key = new BitSetEndPointID(mset, j);
key.setCost(min);
currentCosts.add(key);
// System.out.println("===========================================>mset " + mset + " and end at " +
// j + " 's min cost: " + min);
// if (m == totalNodes) {
// lastKeys.add(key);
// }
}
}
previousCosts = currentCosts;
System.out.println("...");
}
calcLastStop(lastKeys, previousCosts);
System.out.println(" cost " + (System.currentTimeMillis() - beginTime) / 60000 + " minutes.");
}
private void calcLastStop(List<BitSetEndPointID> lastKeys, List<BitSetEndPointID> costs) {
//last step, calculate the min(A[S={1..n},k] +k->1)
float finalMinimum = Float.MAX_VALUE;
for (BitSetEndPointID key : costs) {
float middleCost = key.getCost();
Integer endPoint = key.lastPointID;
float lastCost = distances[endPoint][0];
float cost = middleCost + lastCost;
if (cost < finalMinimum) {
finalMinimum = cost;
}
}
System.out.println("final result: " + finalMinimum);
}
You can speed up your code by using arrays of primitives (it's likely to have to better memory layout than a list of objects) and operating on bitmasks directly (without bitsets or other objects). Here is some code (it generates a random graph but you can easily change it so that it reads your graph):
import java.io.*;
import java.util.*;
class Main {
final static float INF = 1e10f;
public static void main(String[] args) {
final int n = 25;
float[][] dist = new float[n][n];
Random random = new Random();
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
dist[i][j] = dist[j][i] = random.nextFloat();
float[][] dp = new float[n][1 << n];
for (int i = 0; i < dp.length; i++)
Arrays.fill(dp[i], INF);
dp[0][1] = 0.0f;
for (int mask = 1; mask < (1 << n); mask++) {
for (int lastNode = 0; lastNode < n; lastNode++) {
if ((mask & (1 << lastNode)) == 0)
continue;
for (int nextNode = 0; nextNode < n; nextNode++) {
if ((mask & (1 << nextNode)) != 0)
continue;
dp[nextNode][mask | (1 << nextNode)] = Math.min(
dp[nextNode][mask | (1 << nextNode)],
dp[lastNode][mask] + dist[lastNode][nextNode]);
}
}
}
double res = INF;
for (int lastNode = 0; lastNode < n; lastNode++)
res = Math.min(res, dist[lastNode][0] + dp[lastNode][(1 << n) - 1]);
System.out.println(res);
}
}
It takes only a couple of minutes to complete on my computer:
time java Main
...
real 2m5.546s
user 2m2.264s
sys 0m1.572s

How would I speed up this program?

I am currently attempting to solve a ProjectEuler problem and I have got everything down, except the speed. I am almost certain the reason the program executes so slowly is due to the nested loops. I would love some advice on how to speed this up. I am a novice programmer, so I am not familiar with a lot of the more advanced methods/topics.
public class Problem12 {
public static void main(String[] args) {
int num;
for (int i = 1; i < 15000; i++) {
num = i * (i + 1) / 2;
int counter = 0;
for (int x = 1; x <= num; x++) {
if (num % x == 0) {
counter++;
}
}
System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
}
}
}
EDIT : Below is the new code that is exponentially faster. Removed the constant line printing as well to speed it up even more.
public class Problem12 {
public static void main(String[] args) {
int num;
outerloop:
for (int i = 1; i < 25000; i++) {
num = i * (i + 1) / 2;
int counter = 0;
double root = Math.sqrt(num);
for (int x = 1; x < root; x++) {
if (num % x == 0) {
counter += 2;
if (counter >= 500) {
System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
break outerloop;
}
}
}
}
}
}
For starters, when looking at divisors, you never need to go further than the root square of the number, because each divisor below the square root has an equivalent above.
n = a * b => a <= sqrt(n) or b <= sqrt(n)
Then you need to count the other side of the division:
double root = Math.sqrt(num);
for (int x = 1; x < root; x++) {
if (num % x == 0) {
counter += 2;
}
}
The square root is special because it counts only once if it is integer:
if ((double) ((int) root) == root) {
counter += 1;
}
You just need to factorize the number. p^a * q^b * r^c has (a+1)*(b+1)*(c+1) divisors. Here is some basic implementation using this idea:
static int Divisors(int num) {
if (num == 1) {
return 1;
}
int root = (int) Math.sqrt(num);
for (int x = 2; x <= root; x++) {
if (num % x == 0) {
int c = 0;
do {
++c;
num /= x;
} while (num % x == 0);
return (c + 1) * Divisors(num);
}
}
return 2;
}
public static void test500() {
int i = 1, num = 1;
while (Divisors(num) <= 500) {
num += ++i;
}
System.out.println("\nFound: [" + i + "] - " + num);
}

divide bags of candies among three children evenly

I have n bags of candies such that no two bags have the same number of candies inside (i.e. it's a set A[] = {a0,a1,a2,...,ai,...,aj} where ai != aj).
I know how many candies is in each bag and the total number M of candies I have.
I need to divide the bags among three children so that the candies are distributed as fairly as possible (i.e. each child gets as close to M/3 as possible).
Needless to say, I may not tear into the bags to even out the counts -- then the question would be trivial.
Does anyone have any thoughts how to solve this -- preferably in Java?
EDIT:
the interviewer wanted me to use a 2-D array to solve the problem: the first kid gets x, the second kid y, the third gets the rest: S[x][y].
This after I tried following:
1] sort array n lg n
2] starting with largest remaining bag, give bag to kid with fewest candy.
Here is my solution for partitioning to two children (it is the correct answer). Maybe it will help with getting the 3-way partition.
int evenlyForTwo(int[] A, int M) {
boolean[] S = new boolean[M+1];
S[0]=true;//empty set
for(int i=0; i<A.length; i++)
for(int x=M; x >= A[i]; x--)
if(!S[x])
S[x]=S[x-A[i]];
int k = (int) M/2;
while(!S[k])
k--;
return k;//one kid gets k the other the rest.
}//
The problem you describe is known as the 3-Partition problem and is known to be NP-hard. The problem is discussed a bit on MathOverflow. You might find some of the pointers there of some value.
Here is a little solution, crude but gives correct results. And you can even change the number of children, bags, etc.
public class BagOfCandies {
static public void main(String...args) {
int repeat = 10;
int childCount = 3;
int bagsCount = childCount + (int) (Math.random() * 10);
for (int k=0; k<repeat; k++) {
int candyCount = 0, n=0;
int[] bags = new int[bagsCount];
for (int i=0; i<bags.length; i++) {
n += 1 + (int) (Math.random() * 2);
bags[i] = n;
candyCount += n;
}
shuffle(bags); // completely optional! It works regardless
boolean[][] dist = divideBags(bags, childCount);
System.out.println("Bags of candy : " + Arrays.toString(bags) + " = " + bags.length);
System.out.println("Total calculated candies is " + candyCount);
int childCandySum = 0;
for (int c=0; c<childCount; c++) {
int childCandies = countSumBags(bags, dist[c]);
System.out.println("Child " + (c+1) + " = " + childCandies + " --> " + Arrays.toString(dist[c]));
childCandySum += childCandies;
}
System.out.println("For a total of " + childCandySum + " candies");
System.out.println("----------------");
}
}
static private void shuffle(int[] bags) {
for (int i=0, len=bags.length; i<len; i++) {
int a = (int)Math.floor(Math.random()*len);
int b = (int)Math.floor(Math.random()*len);
int v = bags[a];
bags[a] = bags[b];
bags[b] = v;
}
}
static private boolean[][] divideBags(int[] bags, int childCount) {
int bagCount = bags.length;
boolean[][] dist = new boolean[childCount][bagCount];
for (int c=0; c<childCount; c++)
Arrays.fill(dist[c], false);
for (int i=0; i<bagCount; i+=childCount)
for (int j=i, c=0; c<childCount && j<bagCount; j++, c++)
dist[c][j] = true;
if (childCount == 1) return dist; // shortcut here
int sumDiff = 1;
int oldDiff = 0;
while (sumDiff != oldDiff) {
oldDiff = sumDiff;
sumDiff = 0;
// start comparing children in pair
for (int child1=0; child1<childCount-1; child1++) {
for (int child2=child1+1; child2<childCount; child2++) {
int count1 = countSumBags(bags, dist[child1]);
int count2 = countSumBags(bags, dist[child2]);
int diff = Math.abs(count1 - count2);
// a difference less than 2 is negligeable
if (diff > 1) {
// find some bags with can swap to even their difference
int c1=-1, c2=-1, cdiff;
boolean swap = false;
for (int i=0; i<bagCount-1; i++) {
for (int j=i; j<bagCount; j++) {
if (dist[child1][i] && dist[child2][j]) {
cdiff = Math.abs((count1 - bags[i] + bags[j]) - (count2 + bags[i] - bags[j]));
if (cdiff < diff) {
c1 = i; c2 = j;
diff = cdiff;
swap = true;
}
}
if (dist[child1][j] && dist[child2][i]) {
cdiff = Math.abs((count1 - bags[j] + bags[i]) - (count2 + bags[j] - bags[i]));
if (cdiff < diff) {
c1 = j; c2 = i;
diff = cdiff;
swap = true;
}
}
}
}
if (swap) {
//System.out.println("Swaping " + c1 + " with " + c2);
dist[child1][c1] = false; dist[child1][c2] = true;
dist[child2][c1] = true; dist[child2][c2] = false;
}
}
//System.out.println("Diff between " + child1 + "(" + countSumBags(bags, dist[child1]) + ") and " + child2 + "(" + countSumBags(bags, dist[child2]) + ") is " + diff);
sumDiff += diff;
}
}
//System.out.println("oldDiff="+oldDiff+", sumDiff="+sumDiff);
}
return dist;
}
static private int countSumBags(int[] bags, boolean[] t) {
int count = 0;
for (int i=0; i<t.length; i++) {
if (t[i]) {
count+=bags[i];
}
}
return count;
}
}
I don't know if this the result you were looking for, but it seems to be, from my understanding of the question.

Categories