Find Number Of Square Roots Between Two Numbers - java

I have written this function for finding the number of Square Roots between two numbers (inclusive).
static int FindRoot(int no1, int no2) {
int res = 0;
for (int x = no1; x <= no2; x++) {
for (int y = 1; y <= no2; y++) {
if (y * y == x)
res++;
}
}
return res;
}
This will work fine, but I was thinking about it's performance.
Because in this case the inner For loop will execute from starting position(1), so it'll take time if someone passes a large number range to the method.
So, my question is:
Is there any other way i can find this with better performance?
P.S.- I can't use Math.sqrt() function

static int FindRoot(int no1, int no2) {
int res = 0;
int x = 0;
// Ignore squares less than no1
while(x*x < no1) {
x++;
}
// Count squares up to and including no2
while(x*x <= no2) {
res++;
x++;
}
return res;
}

You can get away with having a single for loop by getting rid of the outer loop
static int findRoot(int lo, int hi) {
int numRoots = 0;
for (int x = 0, x2 = 0; x2 <= hi; x++, x2 = x * x) {
if (x2 >= lo) {
numRoots++;
}
}
return numRoots;
}
here you effectively just do your inner loop once, incrementing numRoots when x2 (x-squared) is between lo and hi, and terminating the loop when x2 is greater than hi (instead of when x is greater than hi like in your code).

It'll work as well.
static int FindRoot2(int no1, int no2) {
int res = 0;
int inner=1;
for (int x = no1; x <= no2; x++) {
for (int y = inner; y <= no2; y++) {
if (y * y == x)
{
inner=y;
res++;
}
}
}
return res;
}
In this case inner loop will not start executing from 1.

There are many reasons why your current algorithm is ineffecient, but the biggest one is that the inner for loop is not necessary.
The idea behind the algorithm you're looking for, is to start at the lowest perfect square higher than or equal to no1, then go to the next perfect square and the next and the next, keeping track of how many you hit, until the perfect square you're on is higher than no2.
static int FindRoot(int no1, int no2) {
int res = 0;
int x = 1;
// This loop gets x to the first perfect square greater than
// or equal to no1
while( (x * x) < no1 ) {
x++;
}
// This loop adds 1 to res and increases x
// as long as x^2 is less than or equal to no2
for(; (x * x) <= no2; x++, res++) { }
return res;
}

Related

Issue finding euler's number in java

i have to find e, which is 1/0! + 1/1! + 1/2! + 1/3!... + 1/n! given n as a parameter and i'm having trouble getting the correct answer.
public double Factorial(int n) {
long fact = 1;
for (int i = 1; i <= n; ++i) {
fact *= i;
}
return fact;
}
public double euler(int n) {
double y = 0;
for (int x = 0; x <= n; x++) {
double e = 1 / Factorial(n);
y = y + e;
}
return y;
when i input 10, this outputs 2.7557319223985893E-6 when i should be getting 2.7182818011463845. i ran through the code a few times but i can't figure out the issue. any help is appreciated.
The answer given in the comments addresses the problem. And since you have the algorithm down you may be interested in the following:
A factorial method is not necessary. Since each subsequent value of n! is n! * (n+1) you can work it into your main loop as follows.
// initialize fact to 0!
double fact = 1;
// first Euler term 1/0!
double y = fact;
for (int x = 1; x <= n; x++) {
// next factorial
fact *= x;
// subsequent terms
y += (1 / fact);
}
System.out.println(y);
Prints
2.7182818011463845
And Euler's number is also the limit of (1 + r)(1/r) as r approaches 0.
double r = .000000001;
System.out.println(Math.pow(1 + r, 1/r));
2.71828205201156

How to get all the neihbors neighbors of a point in a 2d array?

I am trying to get all the neighbors of a combination of simple one character strings in a 2d array. Meaning, my output looks like this currently in a 3x5:
A B C
D E F
A S D
F S A
G S A
So the neighbor of (1,0) should be = A B E S A .
Currently I have the following:
public void getNeighborsOfPoint(int x, int y) {
for (int xx = -1; xx <= 1; xx++) {
for (int yy = -1; yy <= 1; yy++) {
if (xx == 0 && yy == 0) {
continue; // You are not neighbor to yourself
}
if (Math.abs(xx) + Math.abs(yy) > 1) {
continue;
}
if (isOnMap(x + xx, y + yy)) {
System.out.println(grid[x+xx][y+yy]);
}
}
}
public boolean isOnMap(int x, int y) {
return x >= 0 && y >= 0 && x < length && y < width;
}
However it is only returning A E A in the example I provided.(it is not returning the ones cross-wise)
What is the right code to make it work? Note that the input will not always be 3 x 5. It may be a lot of different combination of x and y s.
The diagonals aren't included because of this code:
if (Math.abs(xx) + Math.abs(yy) > 1) {
continue;
}
When it's on the diagonal Math.abs(xx) == 1 && Math.abs(yy) == 1. So their sum will be greater than 1. You're skipping over the diagonals by having this code here.
The reason you're not getting the diagonals in your current group is that second if statement. You need to cover, for example, (2, 1) which is when xx is 1 and yy is 1. But abs(1) + abs(1) = 2 and 2 > 1, so you don't include it.
As a refactoring exercise, it might be a little cleaner if you have the inside of that for loop simplified to one conditional.
if (expression) {
continue
};
// other stuff
is equivalent to
if (!expression) {
// other stuff.
}
And for you, expression (in psuedocode) is not(xx=0 and yy=0) and isOnMap(xx, yy)
In a loop, the continue keyword means that you will skip to the next iteration of the loop. In your case, you have :
if (Math.abs(xx) + Math.abs(yy) > 1) {
continue;
}
if (isOnMap(x + xx, y + yy)) {
System.out.println(grid[x+xx][y+yy]);
}
So if the first condition is verified, you will not print any answer, meaning that your program won't consider A(xx, yy) to be a neighbord.
In your ABESA example, B and S are ignored because of this.
If you want to use 2d arrays with variable number of rows and columns you have to pass them as parameters in your's isOnMap method like below:
public static boolean isOnMap(int x, int y, int length, int width) {
return x >= 0 && y >= 0 && x < length && y < width;
}
You can handle the special cases of your 2d array (when one or both rownumber and columnnumber of your element are equal to 0) rewriting your getNeighborsOfPoint method in this way:
public static void getNeighborsOfPoint(int x, int y, char[][] grid) {
final int length = grid.length;
final int width = grid[0].length;
if (isOnMap(x, y, length, width)) {
for (int i = Math.max(0, x - 1); i < Math.min(length, x + 2); ++i) {
for (int j = Math.max(0, y - 1); j < Math.min(width, y + 2); ++j) {
if (i != x || j != y) {
System.out.println(grid[i][j]);
}
}
}
}
}

How do I get a program that has to loop over 10000 times to run?

I'm writing a program in java that basically simulates a random walk by moving 1 x or y value for each step. Ex. starts at (0, 0), using Math.random, I can x++ or y-- which changes the x or y coordinate by one value. This walk terminates once the absolute value of both the x and y value added together gives me the number inputted (by command line argument). There are two command line integers, the first being the number just mentioned and the second being the trials, which is the number of times I have to simulate this walk. By the end of this program, a step counter keeps track of how many steps were taken in each trial, and it is then averaged to give the average number of steps it took for each trial to add up to the number.
The problem I am having is that when I run my program, no error shows up or anything, it just doesn't run which gives me the idea that the runtime is just too long and there are too many iterations to go through. The input for the trials variable is going to be around 100000 to 1000000. I would appreciate any help or ideas on fixing this problem.
Here is my code for the program:
public class RandomWalkers {
public static void main(String [] args) {
int r = Integer.parseInt(args[0]);
double trials = Double.parseDouble(args[1]);
double avgSteps = 0;
double totalSteps = 0;
int x = 0;
int y = 0;
int steps;
for(int j = 0; j < trials; j++ ) {
int trialDistance = 0;
for(steps = 0; trialDistance != r; steps++) {
double random = Math.random();
if(random < 0.25) {
x++;
} else if((0.25 < random) && (random < 0.50)) {
x--;
} else if((0.50 < random) && (random < 0.75)) {
y++;
} else if((0.75 < random) && (random < 1.00)) {
y--;
} else {}
totalSteps = totalSteps + steps;
trialDistance = Math.abs(x) + Math.abs(y);
}
}
avgSteps = totalSteps / trials;
System.out.println("average number of steps = " + avgSteps);
}
}
ok so here an updated version.
public class RandomWalkers {
public static void main(String[] args) {
int radius = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
walk(radius, trials);
}
public static void walk(int radius, int trials) {
//not really a radius, but nvm
int totalSteps = 0;
for (int t = 0; t < trials; t++) {
//you need to reset the x and y for every trial!
int x = 0;
int y = 0;
int steps = 0;
while (Math.abs(x) + Math.abs(y) != radius) {
double random = Math.random();
if (random < 0.25) {
x++;
} else if (random < 0.50) {
x--;
} else if (random < 0.75) {
y++;
} else {
y--;
}
steps++;
}
//take this out of the loop or increase only by one!
totalSteps += steps;
}
double avgSteps = totalSteps / (double) trials;
System.out.println("average number of steps = " + avgSteps);
}
}
i moved everthing to another method (doesnt change anything) but what you can change:
remove the first part of the else if's cause if the random is smaller than .25 it wont even trigger the else. You can also change the last one to a normal "else".
take the "totalsteps = totalsteps + steps" out of the loop -> you dont want to add it with every step.
i guess its better to handle the trials as an int and only cast it to a double for the calculation of the avg.
you need to update the x,y and steps with every trial, else the second trial would be immediatly done with the result of the first
it should be fast enough to make 1mil trials or whatever, just be carefull with the "radius" its going to increase the time dramatically

Divide and Conquer Closest Pair Algorithm

I'm trying to create an algorithm that returns the closest pair from randomly generated points. I have finished the algorithm, however the divide and conquer method of the algorithm is not much faster than the brute-force method. What can I do to optimize the code so that it returns at (n log n) time?
import java.util.*;
import java.lang.*;
import static java.lang.Math.min;
import static java.lang.StrictMath.abs;
public class closestPair {
private static Random randomGenerator; // for random numbers
public static class Point implements Comparable<Point> {
public long x, y;
// Constructor
public Point(long x, long y) {
this.x = x;
this.y = y;
}
public int compareTo(Point p) {
// compare this and p and there are three results: >0, ==0, or <0
if (this.x == p.x) {
if (this.y == p.y)
return 0;
else
return (this.y > p.y)? 1 : -1;
}
else
return (this.x > p.x)? 1 : -1;
}
public String toString() {
return " ("+Long.toString(this.x)+","+Long.toString(this.y)+")";
}
public double distance(Point p) {
long dx = (this.x - p.x);
long dy = (this.y - p.y);
return Math.sqrt(dx*dx + dy*dy);
}
}
public static Point[] plane;
public static Point[] T;
public static Point[] Y;
public static int N; // number of points in the plane
public static void main(String[] args) {
// Read in the Size of a maze
Scanner scan = new Scanner(System.in);
try {
System.out.println("How many points in your plane? ");
N = scan.nextInt();
}
catch(Exception ex){
ex.printStackTrace();
}
scan.close();
// Create plane of N points.
plane = new Point[N];
Y = new Point[N];
T = new Point[N];
randomGenerator = new Random();
for (int i = 0; i < N; ++i) {
long x = randomGenerator.nextInt(N<<6);
long y = randomGenerator.nextInt(N<<6);
plane[i] = new Point(x, y);
}
Arrays.sort(plane); // sort points according to compareTo.
for (int i = 1; i < N; ++i) // make all x's distinct.
if (plane[i-1].x >= plane[i].x) plane[i].x = plane[i-1].x + 1;
//for (int i = 1; i < N; i++)
// if (plane[i-1].y >= plane[i].y) plane[i].y = plane[i-1].y + 1;
//
//
System.out.println(N + " points are randomly created.");
System.out.println("The first two points are"+plane[0]+" and"+plane[1]);
System.out.println("The distance of the first two points is "+plane[0].distance(plane[1]));
long start = System.currentTimeMillis();
// Compute the minimal distance of any pair of points by exhaustive search.
double min1 = minDisSimple();
long end = System.currentTimeMillis();
System.out.println("The distance of the two closest points by minDisSimple is "+min1);
System.out.println("The running time for minDisSimple is "+(end-start)+" mms");
// Compute the minimal distance of any pair of points by divide-and-conquer
long start1 = System.currentTimeMillis();
double min2 = minDisDivideConquer(0, N-1);
long end1 = System.currentTimeMillis();
System.out.println("The distance of the two closest points by misDisDivideConquer is "+min2);
System.out.println("The running time for misDisDivideConquer is "+(end1-start1)+" mms");
}
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
if (plane[i].distance(plane[j]) < midDis){
midDis = plane[i].distance(plane[j]);
}
}
}
return midDis;
}
static void exchange(int i, int j) {
Point x = plane[i];
plane[i] = plane[j];
plane[j] = x;
}
static double minDisDivideConquer(int low, int high) {
// Initialize necessary values
double minIntermediate;
double minmin;
double minDis;
if (high == low+1) { // two points
if (plane[low].y > plane[high].y) exchange(low, high);
return plane[low].distance(plane[high]);
}
else if (high == low+2) { // three points
// sort these points by y-coordinate
if (plane[low].y > plane[high].y) exchange(low, high);
if (plane[low].y > plane[low+1].y) exchange(low, low+1);
else if (plane[low+1].y > plane[high].y) exchange(low+1, high);
// compute pairwise distances
double d1 = plane[low].distance(plane[high]);
double d2 = plane[low].distance(plane[low+1]);
double d3 = plane[low+1].distance(plane[high]);
return ((d1 < d2)? ((d1 < d3)? d1 : d3) : (d2 < d3)? d2 : d3); // return min(d1, d2, d3)
} else { // 4 or more points: Divide and conquer
int mid = (high + low)/2;
double lowerPartMin = minDisDivideConquer(low,mid);
double upperPartMin = minDisDivideConquer(mid+1,high);
minIntermediate = min(lowerPartMin, upperPartMin);
int k = 0;
double x0 = plane[mid].x;
for(int i = 1; i < N; i++){
if(abs(plane[i].x-x0) <= minIntermediate){
k++;
T[k] = plane[i];
}
}
minmin = 2 * minIntermediate;
for (int i = 1; i < k-1; i++){
for(int j = i + 1; j < min(i+7,k);j++){
double distance0 = abs(T[i].distance(T[j]));
if(distance0 < minmin){
minmin = distance0;
}
}
}
minDis = min(minmin, minIntermediate);
}
return minDis;
}
}
Use the following method with the change for minDisSimple. You can get more performance.
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
double temp;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
temp = plane[i].distance(plane[j]);
if (temp < midDis) {
midDis = temp;
}
}
}
return midDis;
}
Performance wise for small amount of points simple method is good but larger amount of points Divide and Conquer is good. Try number of points with 10, 100, 1000, 10000, 100000, 1000000.
One critical aspect in the minDisDivideConquer() is that the loop that constructs the auxiliary array T iterates through all the N points. Since there are O(N) recursive calls in total, making this pass through all the N points every time leads to a complexity of O(N^2), equivalent to that of the simple algorithm.
The loop should actually only consider the points with indices between low and high. Furthermore, it could be split into two separate loops that start from mid (forward and backward), and break when the checked distance is already too large.
Another possible improvement for the minDisDivideConquer() method, in the "4 or more points" situation is to prevent looking into pairs that were already considered in the recursive calls.
If my understanding is correct, the array T contains those points that are close enough on x axis to the mid point, so that there is a chance that a pair of points in T generates a distance smaller than those from the individual half sets.
However, it is not necessary to look into points that are both before mid, or both after mid (since these pairs were already considered in the recursive calls).
Thus, a possible optimization is to construct two lists T_left and T_right (instead of T) and check distances between pairs of points such that one is on the left of mid, and the other to the right.
This way, instead of computing |T| * (|T| - 1) / 2 distances, we would only look into |T_left| * |T_right| pairs, with |T_left| + |T_right| = |T|. This value is at most (|T| / 2) * (|T| / 2) = |T| ^ 2 / 4, i.e. around 2 times fewer distances than before (this is in the worst case, but the actual number of pairs can also be much smaller, inclusively zero).

Java Nested Loops Issue

so I've been working on this code for a while now, and I've reached a standstill. It's a project for school and it came in two parts, the first part was no issue at all.
A drunkard begins walking aimlessly, starting at a lamp post. At each time step, the drunkard forgets where he or she is, and takes one step at random, either north, east, south, or west, with probability 25%. How far will the drunkard be from the lamp post after N steps?
Write a program RandomWalker.java that takes an integer command-line argument N and simulates the motion of a random walker for N steps. After each step, print the location of the random walker, treating the lamp post as the origin (0, 0). Also, print the square of the final distance from the origin.
My code for this part of the problem was:
import java.util. *;
import java.math. *;
public class RandomWalker {
public static void main(String args[]){
int N = Integer.parseInt(args[0]);
Random rand = new Random();
int x = 0;
int y = 0;
int XorY;
int dist;
int count =0;
while(count<N){
XorY = rand.nextInt(2);
dist = rand.nextInt(2);
if(XorY==0){
if(dist==0)
dist = -1;
x += dist;
System.out.println("("+x+", " +y+")");
}
else{
if(dist==0)
dist = -1;
y += dist;
System.out.println("("+x+", " +y+")");
}
count ++;
}
System.out.println("Squared Distance = " + (x*x + y*y));
}
}
For the second part of the problem-
Write a program RandomWalkers.java that takes two command-line arguments N and T. In each of T independent experiments, simulate a random walk of N steps and compute the squared distance. Output the mean squared distance (the average of the T squared distances.)
% java RandomWalkers 100 10000
squared distance = 101.446
% java RandomWalkers 100 10000
mean squared distance = 99.1674
% java RandomWalkers 200 1000
mean squared distance = 195.75
The code I came up with is-
import java.util.*;
import java.math.*;
public class RandomWalkers {
public static void main(String args[]) {
Random rand = new Random();
int N = Integer.parseInt(args[0]);
int T = Integer.parseInt(args[1]);
double avgDist =0;
int stepCount =0;
int trialCount =0;
int x = 0;
int y = 0;
int XorY;
int dist;
while(trialCount<T){
while(stepCount<N){
XorY = rand.nextInt(2);
dist = rand.nextInt(2);
if(XorY==0){
if(dist==0)
dist = -1;
x += dist;
}
else{
if(dist==0)
dist = -1;
y += dist;
}
stepCount ++;
}
avgDist += ((x*x) + (y*y));
trialCount++;
}
System.out.println("Mean Squared Distance = " + avgDist/(double)trialCount);
}
}
I have been stumped here for a really long time, the code compiles and runs but it seems that all it is giving me is a single trial value, and not the desired average. Any help is appreciated, thank you very much. (Also sorry for the improper formatting, I am new here and tried my best).
The solution with the nested while loop inside the for loop is shown below. You have to reset the x, y and distance variables after each trial. Or, even better, to define and initialize them to 0 at the beginning of the for loop, like so:
public class RandomWalkers {
public static void main(String[] args) {
int r = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
double steps = 0.0;
for (int j = 0; j < trials; j++) { // run one experiment
int x = 0;
int y = 0;
int distance = 0;
while (distance < r) { // simulate one random walking
double i = Math.random();
if (i < 0.25) {
y += 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
if (i >= 0.25 && i < 0.5) {
x += 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
if (i >= 0.5 && i < 0.75) {
y -= 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
if (i >= 0.75 && i < 1) {
x -= 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
}
}
System.out.println("average number of steps = " + steps / trials);
}
}

Categories

Resources