Recursion memorization table
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
The following code is for this problem.
Input
The input consists of a single line with three integers n
, s
, and k
(1 ⤠n ⤠10,000, 1⤠k ⤠s ⤠500
). n
is the number of throws, k
the number of different numbers that are needed to win and s
is the number of sides the die has.
Output
Output one line with the probability that a player throws at least k
different numbers within n
throws with an s
-sided die. Your answer should be within absolute or relative error at most 10âÂÂ7
.
Sample Input 1
3 3 2
Sample Output 1
0.888888889
Sample Input 2
3 3 3
Sample Output 2
0.222222222
This program used 0.89s to pass all test cases. But I find other people use Java can achieve ~0.20s. How can I improve my code?
The idea is to establish a table for the recursive call to look up previously calculated the value.
import java.util.*;
public class Dice
static double table;
public static double game(int s, int r, int d)
if(table[r][d] != -1) return table[r][d];
double a = (1 - (double)d/(double)s) * game(s, r - 1, d + 1);
double b = ((double)d/(double)s) * game(s, r - 1, d);
double sum = a + b;
table[r][d] = sum;
return sum;
public static void main(String args)
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int s = in.nextInt();
int k = in.nextInt();
table = new double[n+1][n+1];
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
table[i][j] = (double)-1;
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
if(i + j < k)
table[i][j] = (double)0;
for(int j = 0; j < n+1; j++)
for(int i = k; i < n+1; i++)
table[j][i] = (double)1;
System.out.println(game(s, n, 0));
java recursion
add a comment |Â
up vote
3
down vote
favorite
The following code is for this problem.
Input
The input consists of a single line with three integers n
, s
, and k
(1 ⤠n ⤠10,000, 1⤠k ⤠s ⤠500
). n
is the number of throws, k
the number of different numbers that are needed to win and s
is the number of sides the die has.
Output
Output one line with the probability that a player throws at least k
different numbers within n
throws with an s
-sided die. Your answer should be within absolute or relative error at most 10âÂÂ7
.
Sample Input 1
3 3 2
Sample Output 1
0.888888889
Sample Input 2
3 3 3
Sample Output 2
0.222222222
This program used 0.89s to pass all test cases. But I find other people use Java can achieve ~0.20s. How can I improve my code?
The idea is to establish a table for the recursive call to look up previously calculated the value.
import java.util.*;
public class Dice
static double table;
public static double game(int s, int r, int d)
if(table[r][d] != -1) return table[r][d];
double a = (1 - (double)d/(double)s) * game(s, r - 1, d + 1);
double b = ((double)d/(double)s) * game(s, r - 1, d);
double sum = a + b;
table[r][d] = sum;
return sum;
public static void main(String args)
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int s = in.nextInt();
int k = in.nextInt();
table = new double[n+1][n+1];
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
table[i][j] = (double)-1;
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
if(i + j < k)
table[i][j] = (double)0;
for(int j = 0; j < n+1; j++)
for(int i = k; i < n+1; i++)
table[j][i] = (double)1;
System.out.println(game(s, n, 0));
java recursion
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
The following code is for this problem.
Input
The input consists of a single line with three integers n
, s
, and k
(1 ⤠n ⤠10,000, 1⤠k ⤠s ⤠500
). n
is the number of throws, k
the number of different numbers that are needed to win and s
is the number of sides the die has.
Output
Output one line with the probability that a player throws at least k
different numbers within n
throws with an s
-sided die. Your answer should be within absolute or relative error at most 10âÂÂ7
.
Sample Input 1
3 3 2
Sample Output 1
0.888888889
Sample Input 2
3 3 3
Sample Output 2
0.222222222
This program used 0.89s to pass all test cases. But I find other people use Java can achieve ~0.20s. How can I improve my code?
The idea is to establish a table for the recursive call to look up previously calculated the value.
import java.util.*;
public class Dice
static double table;
public static double game(int s, int r, int d)
if(table[r][d] != -1) return table[r][d];
double a = (1 - (double)d/(double)s) * game(s, r - 1, d + 1);
double b = ((double)d/(double)s) * game(s, r - 1, d);
double sum = a + b;
table[r][d] = sum;
return sum;
public static void main(String args)
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int s = in.nextInt();
int k = in.nextInt();
table = new double[n+1][n+1];
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
table[i][j] = (double)-1;
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
if(i + j < k)
table[i][j] = (double)0;
for(int j = 0; j < n+1; j++)
for(int i = k; i < n+1; i++)
table[j][i] = (double)1;
System.out.println(game(s, n, 0));
java recursion
The following code is for this problem.
Input
The input consists of a single line with three integers n
, s
, and k
(1 ⤠n ⤠10,000, 1⤠k ⤠s ⤠500
). n
is the number of throws, k
the number of different numbers that are needed to win and s
is the number of sides the die has.
Output
Output one line with the probability that a player throws at least k
different numbers within n
throws with an s
-sided die. Your answer should be within absolute or relative error at most 10âÂÂ7
.
Sample Input 1
3 3 2
Sample Output 1
0.888888889
Sample Input 2
3 3 3
Sample Output 2
0.222222222
This program used 0.89s to pass all test cases. But I find other people use Java can achieve ~0.20s. How can I improve my code?
The idea is to establish a table for the recursive call to look up previously calculated the value.
import java.util.*;
public class Dice
static double table;
public static double game(int s, int r, int d)
if(table[r][d] != -1) return table[r][d];
double a = (1 - (double)d/(double)s) * game(s, r - 1, d + 1);
double b = ((double)d/(double)s) * game(s, r - 1, d);
double sum = a + b;
table[r][d] = sum;
return sum;
public static void main(String args)
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int s = in.nextInt();
int k = in.nextInt();
table = new double[n+1][n+1];
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
table[i][j] = (double)-1;
for(int i = 0; i < n+1; i++)
for(int j = 0; j < n+1; j++)
if(i + j < k)
table[i][j] = (double)0;
for(int j = 0; j < n+1; j++)
for(int i = k; i < n+1; i++)
table[j][i] = (double)1;
System.out.println(game(s, n, 0));
java recursion
edited Feb 9 at 3:13
user1118321
10.2k11144
10.2k11144
asked Feb 9 at 2:09
Andy
183
183
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
Don't Repeat Yourself
Your main()
function starts with 3 loops to initialize your table
array. There are several problems here. First, it writes past the end of the array. If your array has n + 1
elements, then you can only write to 0 through n
. Element n + 1
is out-of-bounds. So each of your loops is writing to one element of the next row, and then one extra row at the end, and one element past that, too. The loops should only go from 0 to n
. This happens to work because you later read past the end of the array, too. If you're going to do that, you need to allocate n + 2
rows and columns.
Next, you're writing several elements 3 times. You can combine these 3 loops into 1 and do far less initialization. Further, you should use braces around all loop and conditional bodies because there's the potential to create errors in the future if you don't.
Also, you've switched i
and j
in the last loop which is highly confusing and could easily be missed by a reader.
Here's how I would write your initialization code:
table = new double [ n + 2 ][ n + 2 ]
for (int i = 0; i < n + 1; i++)
for (int j = 0; j < k; j++)
if (i + j < k)
table [ i ][ j ] = 0.0;
else
table [ i ][ j ] = -1.0;
for (int j = k; j < n + 1; j++)
table [ i ][ j ] = 1.0;
Now no element should be touched more than once, no elements past the end of the array should be written to, and no array indexes are flipped.
You're also calculating (double)d / (double)s
twice. You should calculate it once and re-use this value.
Naming
You should choose better names for your variables. i
and j
are fine for loop indexes as they are commonly used that way and nobody will be confused by them. However, I'd rename n
, s
, and k
. I'd name n
something descriptive like numThrows
; k
should be something like numNeeded
, and s
should be numSides
.
Likewise, s
, r
, and d
are not very helpful names for the arguments to game()
.
Speed
I haven't profiled your code, which is the real way to find out which parts are slow. I have seen many cases where casting variables from one type to another causes significant slowdowns. Since the bulk of your game()
function is either calling itself or casting values, I recommend just making the arguments to the function be double
to begin with. Of course, you can't use a double as an index into an array. So you could either pass the r
and d
values as both double
s and int
s.
Thanks! What do you mean by "profile your code"? I am new to programming.
â Andy
Feb 9 at 3:59
I mean run it through a Java code profiling tool. A profiler runs your program, then stops it every millisecond or so, and notes what line was executing. At the end of the run, it tells you which lines it stopped at the most. That usually indicates good places to try to optimize, because those are the places doing the most work. A quick web search for "java profiling tool" turns up several options.
â user1118321
Feb 9 at 4:13
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Don't Repeat Yourself
Your main()
function starts with 3 loops to initialize your table
array. There are several problems here. First, it writes past the end of the array. If your array has n + 1
elements, then you can only write to 0 through n
. Element n + 1
is out-of-bounds. So each of your loops is writing to one element of the next row, and then one extra row at the end, and one element past that, too. The loops should only go from 0 to n
. This happens to work because you later read past the end of the array, too. If you're going to do that, you need to allocate n + 2
rows and columns.
Next, you're writing several elements 3 times. You can combine these 3 loops into 1 and do far less initialization. Further, you should use braces around all loop and conditional bodies because there's the potential to create errors in the future if you don't.
Also, you've switched i
and j
in the last loop which is highly confusing and could easily be missed by a reader.
Here's how I would write your initialization code:
table = new double [ n + 2 ][ n + 2 ]
for (int i = 0; i < n + 1; i++)
for (int j = 0; j < k; j++)
if (i + j < k)
table [ i ][ j ] = 0.0;
else
table [ i ][ j ] = -1.0;
for (int j = k; j < n + 1; j++)
table [ i ][ j ] = 1.0;
Now no element should be touched more than once, no elements past the end of the array should be written to, and no array indexes are flipped.
You're also calculating (double)d / (double)s
twice. You should calculate it once and re-use this value.
Naming
You should choose better names for your variables. i
and j
are fine for loop indexes as they are commonly used that way and nobody will be confused by them. However, I'd rename n
, s
, and k
. I'd name n
something descriptive like numThrows
; k
should be something like numNeeded
, and s
should be numSides
.
Likewise, s
, r
, and d
are not very helpful names for the arguments to game()
.
Speed
I haven't profiled your code, which is the real way to find out which parts are slow. I have seen many cases where casting variables from one type to another causes significant slowdowns. Since the bulk of your game()
function is either calling itself or casting values, I recommend just making the arguments to the function be double
to begin with. Of course, you can't use a double as an index into an array. So you could either pass the r
and d
values as both double
s and int
s.
Thanks! What do you mean by "profile your code"? I am new to programming.
â Andy
Feb 9 at 3:59
I mean run it through a Java code profiling tool. A profiler runs your program, then stops it every millisecond or so, and notes what line was executing. At the end of the run, it tells you which lines it stopped at the most. That usually indicates good places to try to optimize, because those are the places doing the most work. A quick web search for "java profiling tool" turns up several options.
â user1118321
Feb 9 at 4:13
add a comment |Â
up vote
1
down vote
accepted
Don't Repeat Yourself
Your main()
function starts with 3 loops to initialize your table
array. There are several problems here. First, it writes past the end of the array. If your array has n + 1
elements, then you can only write to 0 through n
. Element n + 1
is out-of-bounds. So each of your loops is writing to one element of the next row, and then one extra row at the end, and one element past that, too. The loops should only go from 0 to n
. This happens to work because you later read past the end of the array, too. If you're going to do that, you need to allocate n + 2
rows and columns.
Next, you're writing several elements 3 times. You can combine these 3 loops into 1 and do far less initialization. Further, you should use braces around all loop and conditional bodies because there's the potential to create errors in the future if you don't.
Also, you've switched i
and j
in the last loop which is highly confusing and could easily be missed by a reader.
Here's how I would write your initialization code:
table = new double [ n + 2 ][ n + 2 ]
for (int i = 0; i < n + 1; i++)
for (int j = 0; j < k; j++)
if (i + j < k)
table [ i ][ j ] = 0.0;
else
table [ i ][ j ] = -1.0;
for (int j = k; j < n + 1; j++)
table [ i ][ j ] = 1.0;
Now no element should be touched more than once, no elements past the end of the array should be written to, and no array indexes are flipped.
You're also calculating (double)d / (double)s
twice. You should calculate it once and re-use this value.
Naming
You should choose better names for your variables. i
and j
are fine for loop indexes as they are commonly used that way and nobody will be confused by them. However, I'd rename n
, s
, and k
. I'd name n
something descriptive like numThrows
; k
should be something like numNeeded
, and s
should be numSides
.
Likewise, s
, r
, and d
are not very helpful names for the arguments to game()
.
Speed
I haven't profiled your code, which is the real way to find out which parts are slow. I have seen many cases where casting variables from one type to another causes significant slowdowns. Since the bulk of your game()
function is either calling itself or casting values, I recommend just making the arguments to the function be double
to begin with. Of course, you can't use a double as an index into an array. So you could either pass the r
and d
values as both double
s and int
s.
Thanks! What do you mean by "profile your code"? I am new to programming.
â Andy
Feb 9 at 3:59
I mean run it through a Java code profiling tool. A profiler runs your program, then stops it every millisecond or so, and notes what line was executing. At the end of the run, it tells you which lines it stopped at the most. That usually indicates good places to try to optimize, because those are the places doing the most work. A quick web search for "java profiling tool" turns up several options.
â user1118321
Feb 9 at 4:13
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Don't Repeat Yourself
Your main()
function starts with 3 loops to initialize your table
array. There are several problems here. First, it writes past the end of the array. If your array has n + 1
elements, then you can only write to 0 through n
. Element n + 1
is out-of-bounds. So each of your loops is writing to one element of the next row, and then one extra row at the end, and one element past that, too. The loops should only go from 0 to n
. This happens to work because you later read past the end of the array, too. If you're going to do that, you need to allocate n + 2
rows and columns.
Next, you're writing several elements 3 times. You can combine these 3 loops into 1 and do far less initialization. Further, you should use braces around all loop and conditional bodies because there's the potential to create errors in the future if you don't.
Also, you've switched i
and j
in the last loop which is highly confusing and could easily be missed by a reader.
Here's how I would write your initialization code:
table = new double [ n + 2 ][ n + 2 ]
for (int i = 0; i < n + 1; i++)
for (int j = 0; j < k; j++)
if (i + j < k)
table [ i ][ j ] = 0.0;
else
table [ i ][ j ] = -1.0;
for (int j = k; j < n + 1; j++)
table [ i ][ j ] = 1.0;
Now no element should be touched more than once, no elements past the end of the array should be written to, and no array indexes are flipped.
You're also calculating (double)d / (double)s
twice. You should calculate it once and re-use this value.
Naming
You should choose better names for your variables. i
and j
are fine for loop indexes as they are commonly used that way and nobody will be confused by them. However, I'd rename n
, s
, and k
. I'd name n
something descriptive like numThrows
; k
should be something like numNeeded
, and s
should be numSides
.
Likewise, s
, r
, and d
are not very helpful names for the arguments to game()
.
Speed
I haven't profiled your code, which is the real way to find out which parts are slow. I have seen many cases where casting variables from one type to another causes significant slowdowns. Since the bulk of your game()
function is either calling itself or casting values, I recommend just making the arguments to the function be double
to begin with. Of course, you can't use a double as an index into an array. So you could either pass the r
and d
values as both double
s and int
s.
Don't Repeat Yourself
Your main()
function starts with 3 loops to initialize your table
array. There are several problems here. First, it writes past the end of the array. If your array has n + 1
elements, then you can only write to 0 through n
. Element n + 1
is out-of-bounds. So each of your loops is writing to one element of the next row, and then one extra row at the end, and one element past that, too. The loops should only go from 0 to n
. This happens to work because you later read past the end of the array, too. If you're going to do that, you need to allocate n + 2
rows and columns.
Next, you're writing several elements 3 times. You can combine these 3 loops into 1 and do far less initialization. Further, you should use braces around all loop and conditional bodies because there's the potential to create errors in the future if you don't.
Also, you've switched i
and j
in the last loop which is highly confusing and could easily be missed by a reader.
Here's how I would write your initialization code:
table = new double [ n + 2 ][ n + 2 ]
for (int i = 0; i < n + 1; i++)
for (int j = 0; j < k; j++)
if (i + j < k)
table [ i ][ j ] = 0.0;
else
table [ i ][ j ] = -1.0;
for (int j = k; j < n + 1; j++)
table [ i ][ j ] = 1.0;
Now no element should be touched more than once, no elements past the end of the array should be written to, and no array indexes are flipped.
You're also calculating (double)d / (double)s
twice. You should calculate it once and re-use this value.
Naming
You should choose better names for your variables. i
and j
are fine for loop indexes as they are commonly used that way and nobody will be confused by them. However, I'd rename n
, s
, and k
. I'd name n
something descriptive like numThrows
; k
should be something like numNeeded
, and s
should be numSides
.
Likewise, s
, r
, and d
are not very helpful names for the arguments to game()
.
Speed
I haven't profiled your code, which is the real way to find out which parts are slow. I have seen many cases where casting variables from one type to another causes significant slowdowns. Since the bulk of your game()
function is either calling itself or casting values, I recommend just making the arguments to the function be double
to begin with. Of course, you can't use a double as an index into an array. So you could either pass the r
and d
values as both double
s and int
s.
edited Feb 9 at 5:07
Dair
3,953627
3,953627
answered Feb 9 at 3:57
user1118321
10.2k11144
10.2k11144
Thanks! What do you mean by "profile your code"? I am new to programming.
â Andy
Feb 9 at 3:59
I mean run it through a Java code profiling tool. A profiler runs your program, then stops it every millisecond or so, and notes what line was executing. At the end of the run, it tells you which lines it stopped at the most. That usually indicates good places to try to optimize, because those are the places doing the most work. A quick web search for "java profiling tool" turns up several options.
â user1118321
Feb 9 at 4:13
add a comment |Â
Thanks! What do you mean by "profile your code"? I am new to programming.
â Andy
Feb 9 at 3:59
I mean run it through a Java code profiling tool. A profiler runs your program, then stops it every millisecond or so, and notes what line was executing. At the end of the run, it tells you which lines it stopped at the most. That usually indicates good places to try to optimize, because those are the places doing the most work. A quick web search for "java profiling tool" turns up several options.
â user1118321
Feb 9 at 4:13
Thanks! What do you mean by "profile your code"? I am new to programming.
â Andy
Feb 9 at 3:59
Thanks! What do you mean by "profile your code"? I am new to programming.
â Andy
Feb 9 at 3:59
I mean run it through a Java code profiling tool. A profiler runs your program, then stops it every millisecond or so, and notes what line was executing. At the end of the run, it tells you which lines it stopped at the most. That usually indicates good places to try to optimize, because those are the places doing the most work. A quick web search for "java profiling tool" turns up several options.
â user1118321
Feb 9 at 4:13
I mean run it through a Java code profiling tool. A profiler runs your program, then stops it every millisecond or so, and notes what line was executing. At the end of the run, it tells you which lines it stopped at the most. That usually indicates good places to try to optimize, because those are the places doing the most work. A quick web search for "java profiling tool" turns up several options.
â user1118321
Feb 9 at 4:13
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187143%2frecursion-memorization-table%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password