My assignment says to do the following:
Search2: Search for a solution to x*x + y*y - 12x -10y + 36 = 0. Search from 0 to 10 in both x and y, searching every y value before moving to the next x. Print the first three solutions found. (Note - a labelled break is handy here!)
I can't figure out the logic for this. I think I have to use more than 2 loops but not sure.
This is what I have so far (It just repeats (6,0)):
for (int j = 0; j <= 10; j++) {
for (int i = 0; i <= 10; i++) {
while (((i * i) + (j * j) - (12 * i) - (10 * j) + 36) == 0) {
System.out.println("(" + i + ", " + j + ")");
}
}
}
UPDATE
Here is the solution:
int t = 0;
for (int i = 0; i <= 10; i++) {
if (t == 3) {
break;
}
for (int j = 0; j <= 10; j++) {
if (((i * i) + (j * j) - (12 * i) - (10 * j) + 36) == 0) {
System.out.println("(" + i + ", " + j + ")");
t++;
}
}
}
Not a bad attempt. Because you're so close, I'll show you a working solution. Basically, you need to do three things:
Change while to if
Use a variable to count the number of times you find the solution, so you can stop at three
Add a label so you can break out of the outer loop from within the inner loop
I also recommend you use variable names the same as the problem - ie x and y - for clarity.
int count = 0;
outerLoop:
for (int y = 0; y <= 10; y++) {
for (int x = 0; x <= 10; x++) {
if (x * x + y * y - 12 * x - 10 * y + 36 == 0) {
System.out.println("(" + x + ", " + y + ")");
if (++count == 3)
break outerLoop;
}
}
}
When executed, this code produces:
(6, 0)
(3, 1)
(9, 1)
Sorry for spoon-feeding you, but part of the lesson here is good coding style and practice.
You're using an extra while loop that runs indefinetly.
while (((i * i) + (j * j) - (12 * i) - (10 * j) + 36) == 0) {
System.out.println("(" + i + ", " + j + ")");
}
The first time this evaluates to true - i.e. when it reaches (6,0) - it will keep running because i and j are not modified inside.
You need to replace it with an if.
Take a good look at the inner while loop you have. Once the solution to the equation is found, i and j never change, and the formula always evaluates to 0, resulting in an infinite loop.
It might also be wise to rename i and j to x and y, for clarity. You're mostly on the right track though. Don't forget you only have to print the first three solutions.
I wont help you much since this is a pretty simple concept, but think about what you need to loop through, it might make it easier to instead use x and y instad of i or j. Also your printing only (6,0) because thats exactly what you told it to do with the while loop.
One hint, your while loop should have a statement that stops its function, lets say if x < 4, if it ever is greater or = to than it will continue outside the loop.
public class EquationSolver {
public static void main(String[] args) {
int found = 0;
searchSolutions:
for (int y = 0; y <= 10; y++) {
for (int x = 0; x <= 10; x++) {
if (((x * x) + (y * y) - (12 * x) - (10 * y) + 36) == 0) {
System.out.println("(" + x + ", " + y + ")");
found ++;
if (found == 3) {
break searchSolutions;
}
}
}
}
}
}
Long time I last wrote some homework of that sort...just for the fun of it :)
public class Main {
public static void main(String[] args) {
int[] range = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
boolean isSolutionFound = Boolean.FALSE;
int solCounter = 0;
searchSolutions:
for (Integer y : range) {
for (Integer x : range) {
isSolutionFound = checkForSolution(x, y);
if (isSolutionFound) {
printSolution(x, y);
solCounter++;
}
if (solCounter == 3)
break searchSolutions;
}
}
}
private static void printSolution(Integer x, Integer y) {
System.out.println(x + "," + y); // use some fancy formatting instead
}
private static boolean checkForSolution(int x, int y) {
if (x * x + y * y - 12 * x - 10 * y + 36 == 0)
return true;
else
return false;
}
}
for (int j = 0; j <= 10; j++)
{
for (int i = 0; i <= 10; i++)
{
if (((i * i) + (j * j) - (12 * i) - (10 * j) + 36) == 0)
{
System.out.println("(" + i + ", " + j + ")");
return;
}
}
}
It is import to remember the return; part as you would otherwise still search for solutions although you already found one. If you wan't more solutions, then you should should omit the ´return´ statement.
Related
My code looks like this:
public class HourGlass{
public static final int x = 5;
public static void wall(){
System.out.println("|\"\"\"\"\"\"\"\"\"|");
}
public static void top(){
for (int i = 1;i<=x;i++){
for (int j =1; j<=i; j++){
System.out.print(" ");
}
System.out.print("\\");
for (int k = 1; k <= 9-2*i ;k++){
System.out.print(":");
}
System.out.print("/\n");
}
}
public static void bottom(){
for (int i = 1;i <= x; i++){
for (int j = 1; j<= 5-i; j++){
System.out.print(" ");
}
System.out.print("/");
for (int k = 1; k <= 2*i-1; k++){
System.out.print(":");
}
System.out.print("\\\n");
}
}
public static void main(String[] args){
wall();
top();
bottom();
wall();
}
}
And I get this:
|"""""""""|
\:::::::/
\:::::/
\:::/
\:/
\/
/:\
/:::\
/:::::\
/:::::::\
/:::::::::\
|"""""""""|
How would I go about fixing this and making the bottom and top scale? I have tried to figure out how to solve this issue but I am rather stuck and have not found anything.
This code could be made less rigid, however, this was not your question. In order to make the top and bottom match, you need to ignore the top row where colons do not appear.
I changed your x variable to a capital X, because it is a constant, and made a couple tweeks to your top() and wall() code.
public static final int X = 5;
public static void wall() {
System.out.println("|\"\"\"\"\"\"\"\"\"\"\"|");
}
public static void top() {
for (int i = 1; i <= X + 1; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(" ");
}
System.out.print("\\");
for (int k = 1; k <= 9 - 2 * (i - 1); k++) {
System.out.print(":");
}
System.out.print("/\n");
}
}
Hope this helps
I always find these exercises to be easier to code if there is a method for creating a string with a repeated character. There are other ways to write it, but here is one way to do this with minimal code, using a recursive method:
private static String repeat(char c, int count) {
return (count == 0 ? "" : c + repeat(c, count - 1));
}
E.g. if you call repeat('*', 5) it returns *****
With that available, you can easily print an hourglass. I was a bit unsure what the center of the hourglass should be, so here is two methods.
Hourglass with even number of colons
public static void printHourGlassEven(int size) {
System.out.println('|' + repeat('"', size * 2) + '|');
for (int i = 1; i <= size; i++)
System.out.println(repeat(' ', i) + '\\' + repeat(':', (size - i) * 2) + '/');
for (int i = size; i >= 1; i--)
System.out.println(repeat(' ', i) + '/' + repeat(':', (size - i) * 2) + '\\');
System.out.println('|' + repeat('"', size * 2) + '|');
}
Test
printHourGlassEven(5);
Output
|""""""""""|
\::::::::/
\::::::/
\::::/
\::/
\/
/\
/::\
/::::\
/::::::\
/::::::::\
|""""""""""|
Hourglass with odd number of colons
public static void printHourGlassOdd(int size) {
System.out.println('|' + repeat('"', size * 2 - 1) + '|');
for (int i = 1; i < size; i++)
System.out.println(repeat(' ', i) + '\\' + repeat(':', (size - i) * 2 - 1) + '/');
System.out.println(repeat(' ', size) + 'X');
for (int i = size - 1; i >= 1; i--)
System.out.println(repeat(' ', i) + '/' + repeat(':', (size - i) * 2 - 1) + '\\');
System.out.println('|' + repeat('"', size * 2 - 1) + '|');
}
Test
printHourGlassOdd(5);
Output
|"""""""""|
\:::::::/
\:::::/
\:::/
\:/
X
/:\
/:::\
/:::::\
/:::::::\
|"""""""""|
Given a square matrix of size N*N, where each cell is associated with a specific cost. A path is defined as a specific sequence of cells which starts from top left cell move only right or down and ends on bottom right cell. We want to find the path with maximum value. Now to make things even more interesting: you also have T tokens. You can use the tokens to double the value on the current square. You can only use one token on any given square.
This is how I have solved the first part of the problem.
public static long pathWithMaxCost(int[][] n, int tokens) {
int[][] arr = new int[n.length][n[0].length];
// starting position
arr[arr.length - 1][0] = n[arr.length - 1][0];
// first column
for (int i = arr.length - 2; i >= 0; i--) {
arr[i][0] = arr[i + 1][0] + n[i][0];
}
// last row
for (int i = 1; i < arr[0].length; i++) {
arr[arr.length - 1][i] = arr[arr.length - 1][i - 1] + n[arr.length - 1][i];
}
for (int i = arr.length - 2; i >= 0; i--) {
for (int j = 1; j < arr[0].length; j++) {
arr[i][j] = Math.max(arr[i][j - 1], arr[i + 1][j]) + n[i][j];
}
}
return arr[0][arr[0].length - 1];
}
Now how can I handle the token part, T square values can be doubled?
static long pathWithMaxCostHash(int[][] n, int x, int y, int tokkens) {
if (x < 0 || x >= n.length || y < 0 || y >= n[0].length)
return -1;
String key = x + ":" + y + ":" + tokkens;
if (map.containsKey(key))
return map.get(key);
if(x==n.length-1&&y==0) {
if (tokkens > 0 && n[x][y] > 0) {
map.put(key,(long)n[n.length-1][0]*2);
return 2*n[n.length-1][0];
}
map.put(key,(long)n[n.length-1][0]);
return n[n.length-1][0];
}
//without picking double
long val = n[x][y]
+ Math.max(pathWithMaxCostHash(n, x + 1, y, tokkens), pathWithMaxCostHash(n, x, y - 1, tokkens));
//with picking double
if (tokkens > 0 && n[x][y] > 0) {
long val2 = 2 * n[x][y] + Math.max(pathWithMaxCostHash(n, x + 1, y, tokkens - 1),
pathWithMaxCostHash(n, x, y - 1, tokkens - 1));
val2 = Math.max(val, val2);
map.put(key, val2);
return val2;
}
map.put(key, val);
return val;
}
I'll give you a recursive approach, guess you can figure out dynamic programming based solution with this.
Initialize your dp 2d array with 0's
function: pathWithMaxCost(int x,int y,int tokens, int arr[][],int dp[][])
if(dp[x][y]) return dp[x][y];
few boundary conditions here...
return dp[x][y]=max(arr[x][y]+pathWithMaxCost(x,y+1,tokens,arr), arr[x][y]+pathWithMaxCost(x+1,y,tokens,arr), (arr[x][y]*2)+pathWithMaxCost(x,y+1,tokens-1,arr), (arr[x][y]*2)+pathWithMaxCost(x+1,y,tokens-1,arr))
Add another dimension for T, so the general check for a cell would be:
m[y][x][t] = max(
2 * n[y][x] + m[y-1][x][t-1],
2 * n[y][x] + m[y][x-1][t-1],
n[y][x] + m[y-1][x][t],
n[y][x] + m[y][x-1][t]
)
for all y,x,t
Let's consider the edge cases:
// first element
if x + y == 0:
m[y][x][0] = n[y][x]
m[y][x][1] = 2 * n[y][x]
m[y][x][t] = -Infinity, for t > 1
// first row
if y == 0:
m[y][x][t] = max(
2 * n[y][x] + m[y][x-1][t-1],
n[y][x] + m[y][x-1][t]
)
// first column
if x == 0:
m[y][x][t] = max(
2 * n[y][x] + m[y-1][x][t-1],
n[y][x] + m[y-1][x][t]
)
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);
}
}
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);
}
This question already has answers here:
Algorithm to efficiently determine the [n][n] element in a matrix
(6 answers)
Closed 7 years ago.
I have a function g(n) which can be given by g(n)=f(n,n) . This is defined recursively by
f(i, j) = 1/3
(f(i−1, j) + f(i−1, j −1) + f(i, j −1))
with f(0,0) = 0; f(i,0) = 1,i > 0; f(0, j) = 1, j > 0
I have written a java program to compute this for values from 10-15. The first couple of values are processed quickly but towards the end of values the program becomes very slow and takes a long time to process the result. Is there a problem with my code or is it just a lengthy calculation?
public class javaapplication4 {
private static double f(double i, double j) {
if (i == 0.0 && j == 0.0) return 0.0;
if (i == 0.0 || j == 0.0) return 1.0;
return (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
}
private static double g(double n) {
return f(n, n);
}
public static void main (String[] args) {
for (int n = 10; n < 16; n ++) {
System.out.println("g(" + (int) n + "): " + g(n));
}
}
}
First of all, you seem to have forgotten a 1.0 / 3 in this line:
return (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
Second, your program is slow because the same values get computed multiple times. For example, f(i - 1, j) will call f(i - 1, j - 1), which is also called from f(i, j).
To solve this, either compute your recurrence relation in a matrix:
f(0,0) = 0; f(i,0) = 1,i > 0; f(0, j) = 1, j > 0
for i = 1 to n:
for j = 1 to n:
f[i, j] = 0.33*(f[i - 1, j] + f[i, j - 1] + f[i - 1, j - 1])
Or keep your recursive implementation, but use memoization to speed it up:
A memoized function "remembers" the results corresponding to some set of specific inputs. Subsequent calls with remembered inputs return the remembered result rather than recalculating it, thus eliminating the primary cost of a call with given parameters from all but the first call made to the function with those parameters.
Basically, you can still use a matrix to store results in, and do something like this:
private static double f(double i, double j) { // make i and j ints, they do not need to be doubles here.
if (i == 0.0 && j == 0.0) return 0.0;
if (i == 0.0 || j == 0.0) return 1.0;
if (storageMatrix[i, j] != -1) {
return storageMatrix[i, j];
}
storageMatrix[i, j] = (1.0 / 3) * (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
return storageMatrix[i, j];
}
You can optimize things even further by noticing that if you implement the iterative solution I gave pseudocode for above, you only ever use the current and previous rows of your matrix. So you can just use two arrays of length n instead of a square n x n matrix to compute your function.
This is easy to speed up with memoization. Don't throw away the values that you've worked so hard to calculate.
Here's my output:
"C:\Program Files\Java\jdk1.7.0_45\bin\java" -Didea.launcher.port=7534 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.0.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_45\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\rt.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\zipfs.jar;F:\Projects\Java\stack-overflow\out\production\stack-overflow;F:\Projects\Java\stack-overflow\lib\jxl.jar;F:\Projects\Java\stack-overflow\lib\jdom.jar;F:\Projects\Java\stack-overflow\lib\Jama-1.0.2.jar;F:\Projects\Java\stack-overflow\lib\dom4j-1.6.1.jar;F:\Projects\Java\stack-overflow\lib\commons-io-2.3.jar;F:\Projects\Java\stack-overflow\lib\aopalliance-1.0.jar;F:\Projects\Java\stack-overflow\lib\sqlitejdbc-v056.jar;F:\Projects\Java\stack-overflow\lib\jackson-xc-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\commons-lang3-3.1.jar;F:\Projects\Java\stack-overflow\lib\commons-math3-3.3.jar;F:\Projects\Java\stack-overflow\lib\jackson-all-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\StackWrap4J-1.0.1.jar;F:\Projects\Java\stack-overflow\lib\jackson-jaxrs-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-smile-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-mrbean-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-core-asl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-core-lgpl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-mapper-asl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\postgresql-8.1-405.jdbc3.jar;F:\Projects\Java\stack-overflow\lib\jackson-mapper-lgpl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\mysql-connector-java-5.1.18-bin.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.aop-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.asm-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.jms-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.orm-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.oxm-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.core-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.jdbc-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.beans-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.aspects-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.context-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.expression-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.instrument-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web.struts-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.transaction-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web.portlet-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web.servlet-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.context.support-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.instrument.tomcat-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\test-lib\junit-4.10.jar;F:\Projects\Java\stack-overflow\test-lib\org.springframework.test-3.1.0.RC2.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.0.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain cruft.RecursionExample
n: 0 g(n): 0.00000015.5 +
n: 1 g(n): 0.66666715.5 +
n: 2 g(n): 0.81481515.5 +
n: 3 g(n): 0.86419815.5 +
n: 4 g(n): 0.88797415.5 +
n: 5 g(n): 0.90240315.5 +
n: 6 g(n): 0.91236115.5 +
n: 7 g(n): 0.91977515.5 +
n: 8 g(n): 0.92557415.5 +
n: 9 g(n): 0.93027315.5 +
n: 10 g(n): 0.93418015.5 +
n: 11 g(n): 0.93749715.5 +
n: 12 g(n): 0.94035715.5 +
n: 13 g(n): 0.94285715.5 +
n: 14 g(n): 0.94506715.5 +
n: 15 g(n): 0.94703915.5 +
total wall time: 11 ms
Process finished with exit code 0
Runs in 11 ms for me.
package cruft;
import java.util.HashMap;
import java.util.Map;
/**
* RecursionExample description here
* #author Michael
* #link https://stackoverflow.com/questions/28933093/recursive-function-gn
* #since 3/8/2015 7:28 PM
*/
public class RecursionExample {
private static final Map<String, Double> memo = new HashMap<String, Double>();
private static double f(int i, int j) {
if (i < 0) throw new IllegalArgumentException("i cannot be negative");
if (j < 0) throw new IllegalArgumentException("j cannot be negative");
if (i == 0 && j == 0) return 0.0;
if (i == 0 || j == 0) return 1.0;
String key = Integer.toString(i) + "~" + Integer.toString(j);
if (memo.containsKey(key)) {
return memo.get(key);
} else {
double value = (f(i-1, j) + f(i-1, j-1) + f(i, j-1))/3.0;
memo.put(key, value);
return value;
}
}
private static double g(int n) {
return f(n, n);
}
public static void main (String[] args)
{
long begTime = System.currentTimeMillis();
try {
for (int n = 0; n < 16; n ++) {
System.out.println(String.format("n: %d g(n): %f15.5 + ", n, g(n)));
}
} finally {
long endTime = System.currentTimeMillis();
System.out.println(String.format("total wall time: %10d ms", (endTime-begTime)));
}
}
}
You have forgotten to divide your result by 3, otherwise your code is fine. You can speed it up for an arbitrary amount of values by adding an array that previous results are saved in, I did it like this:
public class Recursivity {
static double[][] results = new double[20][20];
private static double f(int i, int j) {
if (i == 0 && j == 0) {
return 0.0;
}
if (i == 0 || j == 0) {
return 1.0;
}
if (results[i][j] != -1.0) {
return (results[i][j]);
}
double output = (f(i - 1, j) + (f(i - 1, j - 1) + (f(i, j - 1))));
results[i][j] = output;
return output;
}
private static double g(int n) {
return f(n, n);
}
public static void main(String[] args) {
for (int i = 0; i < results.length; i++) {
for (int j = 0; j < results.length; j++) {
results[i][j] = -1.0;
}
}
for (int n = 10; n < 16; n++) {
System.out.println("g(" + (int) n + "): " + g(n));
}
}
}
This runs a lot faster, but it requires you to have Integers as input for f. I don't know if there is any kind of list you can index by non-discrete numbers, but it should be possible for a finite amount of them.
To supplement the answer above, suppose a system can compute f(k, k) in time t. To compute f(k+1,k+1), it's going to have to compute f(k, k+1), f(k, k) and f(k+1, k). That's going to take about 3 times as long. In other words, for any given k, the time to compute f(k+1,k+1) is triple that of f(k,k). This gets out of hand fast: computing f(15, 15) is going to take 243 times as long as computing f(10, 10)!
your code is good but you just forgot to add 1/3 to here ;
return (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
so it should be like this ;
return (f(i - 1, j)*0.33 + f(i - 1, j - 1) + f(i, j - 1));
or
return (f(i - 1, j)*(1/3) + f(i - 1, j - 1) + f(i, j - 1));