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);
}
}
Related
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
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
I'm trying to create a Java program that will calculate a cosine value with the following equation:
The code to my program is located below. I don't appear to have any errors in my program however no matter what values that I set x and k to, I get the answer Infinity and I cannot figure out what I've done wrong.
The way that the code works, is that the console asks you for a value for x and then a value for k. Then the idea is to have Java compare the result of the equation (the method cosine in the script) with the Math.cos() function.
The method cosine is split up into two parts, cosinenumerator and cosinedenominator which is then divided with each other to become cosineresult at the end.
The loop for cosinedenominator is supposed to emulate a "factorial" in the equation.
Any help would be greatly appreciated.
import java.util.Scanner;
public class Cosine {
public static void main(String[] args) {
Scanner consolecosine = new Scanner(System.in);
System.out.println("Enter x value:");
double x = consolecosine.nextDouble();
System.out.println("Enter k value:");
int k = consolecosine.nextInt();
double cosineresult = cosine(x, k);
System.out.println("Using the Math.cos function yields: " + Math.cos(90));
System.out.println("Using the Taylor expansion equation yields: " + cosineresult);
}
public static double cosine(double x, int k) {
double cosineresult = 0;
double cosinenumerator = 0;
double cosinedenominator =0;
int i = 0;
int j = 0;
for(i = 0; i <= k; i++) {
cosinenumerator += Math.pow((-1),i) * Math.pow(x, (2*i));
}
for(j = 0; j <= (2*i); j++) {
cosinedenominator *= (2*j);
}
cosineresult = cosinenumerator / cosinedenominator;
return cosineresult;
}
}
Here's a working version (note that x is in radians; not degrees):
cosine(Math.PI, 15) yields -1.0000000000000002, which is about right.
public static double cosine(double x, int k) {
double cosineresult = 0;
double cosinedenominator = 1; // initial value 0! = 1; overflows at k = 86
int j = 2; // next multiplier in denominator factorial (skip 1)
for (int i = 0; i <= k; i++) {
double cosinenumerator = Math.pow((-1),i) * Math.pow(x, (2 * i));
// Continue calculation of factorial from last value
while (j <= 2 * i) {
cosinedenominator *= j++;
}
cosineresult += cosinenumerator / cosinedenominator;
}
return cosineresult;
}
Basically, I implemented a Random walk program in Java. And I know the distance should converge to l * (n ^ 0.5)(l is the step length, n is the total steps). If let l equals to 1, then d = n ^ 0.5 or in other words: d = sqrt(n).
But, strangly, although I cannot find any error in my code, it just converges to unexpected value. For example, given l = 1, n = 100, d should converge to 10, but actually it converges to 8.86 after 1000000 times experiments.
Here is my code:
public class RandomWalk {
private int x = 0;
private int y = 0;
private final Random random = new Random();
private void move(int dx, int dy) {
x += dx;
y += dy;
}
private void randomWalk(int m) {
for (int i = 0; i < m; i++)
randomMove();
}
private void randomMove() {
boolean xOry = random.nextBoolean();
boolean plusOrminus = random.nextBoolean();
int delta = plusOrminus ? 1 : -1;
int dx = xOry ? delta : 0, dy = xOry ? 0 : delta;
move(dx, dy);
}
public double distance() {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
public static double randomWalkMulti(int m, int n) {
double totalDistance = 0;
for (int i = 0; i < n; i++){
RandomWalk walk = new RandomWalk();
walk.randomWalk(m);
totalDistance += walk.distance();
}
return totalDistance/n ;
}
}
I've thought some possiblities. First I think it may be caused by that the generated boolean by random has bias. Second I think it may be caused by float precision lost. But as this is just a very simple use case, I don't think these two situations are possible.
Could any one tell me why it doesn't work as expected?
I don't think it's true that the distance should average out to √n. According to https://math.stackexchange.com/questions/103142/expected-value-of-random-walk, the square of the distance should average out to n, but that's not the same thing (since the average of the square roots of a set of numbers is not the same as the square root of their average).
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).