Why does my recursion fall through? - java

My recursive function is falling through in my program. I am making a method that constructs a relatively simple object array and populates them with certain values. i.e. object 1 has these values 3,2,5,6,7, object 2 has these values; 4,5,6,4,5. and so on
the recursion comes in when I have different parts of the method that do different things to the function. as shown below:
objectConstructor(Object foo, int switcherVar){
if(switcherVar == 1){
//terminating condition leave method
return 1;
} else {
if(switcherVar == 2){
//do something
objectConstructor(object foo, 1)
}
}
return 0;
}
When I check my return value i get a 0. The stuff that I'm actually doing in the method is unrelated to my recursive function and the function IS re cursing just at the end it falls through when its supposed to jump to the terminating condition. From my understanding the problem is the way I'm formatting my recursive function.
Below is the actual code It's an airplane seat constructor that give values to an airplanes seats, like if it is occupied and whatnot. the above is easier to read but if my syntax is off that might be the problem as well.
private int airplaneSeatConstructor(Airplane airplane, String className, int numberOfSeats){
/*Airplane Seat Creator, loops through the seats and attaches credentials to them based on the type of plane
* being formed.*/
//currently only one plane type. 777.
//777 seat number 257
//does have a first class section.
System.out.println("iteration");
if(className.equals("TERM")){
return 1;
}else {
if (className.equals("FIRST")) {
for (int x = 0; x < numberOfSeats; x++) {
airplane.getSeats()[x].setOccupied(false);
airplane.getSeats()[x].setFirstClass(true);
airplane.getSeats()[x].setBusinessClass(false);
if ((x % 4) == 0 || (x % 4) == 3) {
airplane.getSeats()[x].setWindowseat(true);
airplane.getSeats()[x].setAisleSeat(false);
} else {
airplane.getSeats()[x].setAisleSeat(true);
airplane.getSeats()[x].setWindowseat(false);
}
}
System.out.println("in first");
airplaneSeatConstructor(airplane, "BUSINESS", 40);
}
if (className.equals("BUSINESS")) {
for (int x = 0; x < numberOfSeats; x++) {
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + x].setBusinessClass(true);
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + x].setFirstClass(false);
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + x].setOccupied(false);
}
System.out.println("in business");
airplaneSeatConstructor(airplane, "ECONOMY", 209);
}
if (className.equals("ECONOMY")) {
for (int x = 0; x < numberOfSeats; x++) {
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + airplane.getNumberOfSeatsPerClass()[1] + x].setBusinessClass(false);
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + airplane.getNumberOfSeatsPerClass()[1] + x].setFirstClass(false);
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + airplane.getNumberOfSeatsPerClass()[1] + x].setOccupied(false);
}
System.out.println("in economy");
airplaneSeatConstructor(airplane, "SPECIAL", 26);
}
if (className.equals("SPECIAL")) {
System.out.println("in special");
airplaneSeatConstructor(airplane, "TERM", 273);
}
}
return 0;
}
my print lines all hit but I'm still getting 0 from my return value.

In your code, whatever recursion you do, in fact, whatever calculation you do is not going to count, since you're finally returning 0 for all cases but the base one (in which you return 1).
objectConstructor(Object foo, int switcherVar){
if(switcherVar == 1){
//terminating condition leave method
return 1;
} else {
if(switcherVar == 2){
//do something
objectConstructor(object foo, 1)
}
}
return 0;
}
Recursion in your program works this way: you do the first call with switcher == 2, which makes the recursive call whit switcher == 1. But then you discard that result and just return 0.
The correct or logic way of things for doing this is more similar to this:
objectConstructor(Object foo, int switcherVar){
if(switcherVar == 1){
//terminating condition leave method
return 1;
} else {
if(switcherVar == 2){
//do something
return objectConstructor(object foo, 1)
}
}
}
Hope this helps.
However, looking closely to your code, I think that you are substituting sequence by recursion. I would refactor (i.e., divide the code of) your function by classes of seats, and make the needed calls. Recursion is not needed at all in your code. See below:
private void airplaneSeatConstructorFirstClass(Airplane airplane, int numberOfSeats)
{
for (int x = 0; x < numberOfSeats; x++) {
airplane.getSeats()[x].setOccupied(false);
airplane.getSeats()[x].setFirstClass(true);
airplane.getSeats()[x].setBusinessClass(false);
if ((x % 4) == 0 || (x % 4) == 3) {
airplane.getSeats()[x].setWindowseat(true);
airplane.getSeats()[x].setAisleSeat(false);
} else {
airplane.getSeats()[x].setAisleSeat(true);
airplane.getSeats()[x].setWindowseat(false);
}
}
}
private void airplaneSeatConstructorBussinessClass(Airplane airplane, int numberOfSeats)
{
for (int x = 0; x < numberOfSeats; x++) {
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + x].setBusinessClass(true);
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + x].setFirstClass(false);
airplane.getSeats()[airplane.getNumberOfSeatsPerClass()[0] + x].setOccupied(false);
}
}
...and so on.
Now you just have to call:
airplaneSeatConstructorFirstClass( airplane, 80 );
airplaneSeatConstructorBussinessClass( airplane, 40 );
As you can see is far easier (unless I'm missing something big).

Let's say that this
objectConstructor(object foo, 1);
returns 1.
After that you do return 0. Of course the whole thing will return 0.
Maybe you should
return objectConstructor(object foo, 1);

Related

When determining the winner in a Tic Tac Toe game, how do I avoid repetition?

Note: I am a beginner in Java (2 - 3 months of experience).
Doing a project on JetBrains/Hyperskill about making a Tic Tac Toe game, I found myself repeating quite a bit of code when trying to determine the winner of the game. To represent the game as a coordinate system (Thus 1,1 being at the bottom left and 3,3 at the top right) I am using a two-dimensional array.
This is the function for determining the winner:
public String determineWinner() {
int countX = 0; // amount of X's in a row
int countO = 0; // amount of O's in a row
for (int y = 0; y <= 2; y++) { // for all horizontal rows
countX = 0;
countO = 0;
for (int x = 0; x <= 2; x++) { // loop through all x-coordinates
String value = this.field[x][y];
if (value.equals("X")) { // if the value at that coordinate equals "X", add 1 to the count
countX++;
}
if (value.equals("O")) { // same here
countO++;
}
}
if (countX == 3) { // if the count is 3 (thus 3 X's in a row), X has won
return "X wins";
}
if (countO == 3) { // same here
return "O wins";
}
}
// Same thing, but for all vertical columns
for (int x = 0; x <= 2; x++) {
countX = 0;
countO = 0;
for (int y = 0; y <= 2; y++) {
String value = this.field[x][y];
if (value.equals("X")) {
countX++;
}
if (value.equals("O")) {
countO++;
}
}
if (countX == 3) {
return "X wins";
}
if (countO == 3) {
return "O wins";
}
}
// Same thing, but for diagonal
countX = 0;
countO = 0;
for (int i = 0; i <= 2; i++) {
String value = this.field[i][i];
if (value.equals("X")) {
countX++;
}
if (value.equals("O")) {
countO++;
}
}
if (countX == 3) {
return "X wins";
}
if (countO == 3) {
return "O wins";
}
// Same thing, but for other diagonal
countX = 0;
countO = 0;
for (int i = 0; i <= 2; i++) {
String value = this.field[i][2-i];
if (value.equals("X")) {
countX++;
}
if (value.equals("O")) {
countO++;
}
}
if (countX == 3) {
return "X wins";
}
if (countO == 3) {
return "O wins";
}
if (this.getNumberOfMoves() == 9) { // if the number of moves equals 9, the game is over and it is a draw
return "draw";
}
return "game not finished";
}
Currently, the code allows you to set a starting board (a starting arrangement for all the O's and X's) and then lets you do 1 move. After this, the game decides who is the winner or if it is a draw etc.
As one quickly notices, the function is way too long and it has quite a portion of repetition, yet I am unable to come up with any ways to shorten it.
Does anyone have any tips? Or any guidelines that apply to all code?
DISCLAIMER: Sorry if my answer started getting sloppy towards the end.
Also, I have a code at the bottom showing all the things I talked about in action.
I think the simplest thing I can say is to use more methods and possibly classes. Firstly, one of the ways to avoid repetition in all of your codes is to write them using object-oriented programming. This is the idea of having multiple classes that all interact with the main class to assist in writing code. I won't talk about that here, but if you are interested in making your code neat and "clean", I highly advise looking that up. Also, there is a great book on the subject called Clean Code by Robert C. Martin. I will simply be showing how you can take advantage of methods to shorten your code and clean it up. One of the things you repeat the most is this
if (countX == 3) {
return "X wins";
}
if (countO == 3) {
return "O wins";
}
Your countX and countO are different each time, so you rewrote it. I simpler and more efficient way to do this is to use a method. I would advise you to research the syntax for Java in you don't know how to make methods or classes, but you do use the syntax for the determineWinner() method so I will assume you understand it. You can make functions have parameters that are essentially inputs that can be accessed and modified throughout the function. (By the way, you cannot make methods inside methods in Java so you would need to place this next method outside somewhere else in the class.)
public String checkCounts() {
if (countX == 3) {
return "X wins";
}
if (countO == 3) {
return "O wins";
}
else return "N/A";
}
*You want to check to see if it returns "N/A" anytime you use the method with an if statement. If so, you should just ignore it since no one won.
whoWon = checkCounts();
//In the code I put at the bottom I will make whoWon a global variable, which is why I'm not defining it here.
//It will be already defined at the top of the code.
if (!whoWon.equals("N/A")) return whoWon;
*The ! symbol means not, a.k.a if whoWon does NOT equal "N/A", return whoWon.
This way, anytime you need to write out that if statement code, you can just write checkCounts and plug in the two variables that you just got from your Array. You would write checkCounts(); in this case. Now if you just say return checkCounts(); then the code will run all those if statements without you having to type them all and return the result. You actually repeat something else a lot too. These couple of lines
String value = this.field[x][y];
if (value.equals("X")) {
countX++;
}
if (value.equals("O")) {
countO++;
}
are quite similar to these lines
String value = this.field[i][i];
if (value.equals("X")) {
countX++;
}
if (value.equals("O")) {
countO++;
}
and these lines
String value = this.field[i][2-i];
if (value.equals("X")) {
countX++;
}
if (value.equals("O")) {
countO++;
}
so you can condense them all down into one method with three different inputs. The method will return either 0, 1, or 2. The goal is to check which one it returns with the given string input and then translate that to which variable to add 1 to.
If it's 0, ignore, if it's 1, countX++, and if it's 2, countY++.
public int checkString(String value) {
int whichCount = 0;
//if whichCount is 1, it means X
//if whichCount is 2, it means O
if (value.equals("X")) {
whichCount = 1;
}
if (value.equals("O")) {
whichCount = 2;
}
return whichCount;
}
Switch statements might be a little advanced, but they're pretty simple in concept. It's a bunch of if statements all at once in a very convenient syntax. The value inside the parenthesis is your input, or what to check. The cases say, when its equal to this, do this. When you needed to increment either countX or countY inside your for loops, you would write
switch (checkString(this.field[coord1][coord2])) {
case 1 -> countX++;
case 2 -> countO++;
}
case 1 says, if addToCount() returns 1 then do the thing to the right of the arrow and case 2 says if it returns 2 to the thing to the right of that arrow. In your for loops, coord1 and coord2 could be anything from [x][y] to [i][i] to [i][2-i] so you can change that anytime you make the switch statement.
Additionally, you can turn that switch statement itself into a method.
public void adjustCounts(String stringFromArray) {
switch (checkString(stringFromArray)) {
case 1 -> countX++;
case 2 -> countO++;
}
}
You can also take a couple of lines off by shorting your if statements. If the thing inside the if statement is only one line long than you can just put in next to it.
if (bool) {
doSomething();
}
//Change that to this
if (bool) doSomething();
Another thing you repeat a lot is this
countX = 0;
countO = 0;
I just made a very simple method that does that with no parameters.
public void resetCounts() {
countX = 0;
countO = 0;
}
That's pretty much it for repetition, but I would argue your determineWinner method is still far too large. Even if you don't repeat any more code, taking large changes of it and separating it into smaller bites can make it easier to read and understand.
I added in a bunch of methods that just contained your for loops. They will be at the very bottom of this final class I came up with. It's 85 lines long so it's technically only a 4 line improvement but it's a lot cleaner. Additionally, if you were to embed this in your actual class, and not just in a single method (because you can't put it all in one method) then it would be even more efficient because you would have access to all of the classes global variables. Here is the code I came up with, but I would highly recommend doing extra research on object-oriented programming to really improve your code.
public class TicTacToe {
String[][] field = new String[3][3];
int countX, countO = 0; // amount of X's and O's in a row
String whoWon = "N/A";
public int getNumberOfMoves() {return 0;} //Whatever you method did that determined this. Obviously it didn't really just return 0.
public String determineWinner() {
String columns = checkColumnsForWinner();
String rows = checkRowsForWinner();
String diagonal1 = checkDiagonal(1, 0);
String diagonal2 = checkDiagonal(-1, 2);
if (checkForNA(columns)) return columns;
if (checkForNA(rows)) return rows;
if (checkForNA(diagonal1)) return diagonal1;
if (checkForNA(diagonal2)) return diagonal2;
if (this.getNumberOfMoves() == 9) return "draw"; // if the number of moves equals 9, the game is over and it is a draw
return "game not finished";
}
public String checkCounts(int countX, int countO) {
if (countX == 3) return "X wins";
if (countO == 3) return "O wins";
else return "N/A";
}
public int checkString(String value) {
int whichCount = 0;
//if whichCount is 1, it means X
//if whichCount is 2, it means O
if (value.equals("X")) whichCount = 1;
if (value.equals("O")) whichCount = 2;
return whichCount;
}
public void adjustCounts(String stringFromArray) {
switch (checkString(stringFromArray)) {
case 1 -> countX++;
case 2 -> countO++;
}
}
public void resetCounts() {
countX = 0;
countO = 0;
}
public String checkRowsForWinner() {
for (int y = 0; y <= 2; y++) { // for all horizontal rows
resetCounts();
for (int x = 0; x <= 2; x++) { // loop through all x-coordinates
adjustCounts(field[x][y]);
}
whoWon = checkCounts(countX, countO);
if (!whoWon.equals("N/A")) return whoWon;
}
return "N/A";
}
public String checkColumnsForWinner() {
for (int x = 0; x <= 2; x++) {
resetCounts();
for (int y = 0; y <= 2; y++) {
adjustCounts(field[x][y]);
}
whoWon = checkCounts(countX, countO);
if (!whoWon.equals("N/A")) return whoWon;
}
return "N/A";
}
public String checkDiagonal(int mutiply, int add) {
resetCounts();
for (int i = 0; i <= 2; i++) {
adjustCounts(field[i][i*mutiply + add]);
}
whoWon = checkCounts(countX, countO);
if (!whoWon.equals("N/A")) return whoWon;
return "N/A";
}
public boolean checkForNA(String string) {return !string.equals("N/A");}
}
In regards to Object-Oriented Programming, the best example I could see you put into practice in this example is Abstraction. This is a very general concept but I think it would help a lot in this case. In my program above, I have a TicTacToe class, and all of my code in it. The problem is, you are seeing a lot of boilerplate to get the code to run. The biggest example is the 2D Array object you have. You have to do so many things to get X's or O's out of it. It would be much better (opinion) to make a new class, maybe called Board. It would contain a private 2D Array object, and public methods to get values from that object. Additionally, (this is really just my opinion) I would recommend using an enumeration instead of Strings for you Array values. For example
public enum BoardValues {
X,
O,
EMPTY
}
You could then create a class to place these board values in essentially a 3x3 Grid.
public class Board {
private BoardValues[][] values = new BoardValues[3][3];
public BoardValues getValue(int x, int y) {
return values[x][y];
}
public BoardValues[] getRow(int rowNumber) {
BoardValues[] rowValues = new BoardValues[3];
for (int i = 0; i < values.length; i++) {
rowValues[i] = getValue(i, rowNumber);
}
return rowValues;
}
public BoardValues[] getColumn(int columnNumber) {
BoardValues[] columnValues = new BoardValues[3];
for (int i = 0; i < values.length; i++) {
columnValues[i] = getValue(columnNumber, i);
}
return columnValues;
}
public void setValues(BoardValues[][] values) {
this.values = values;
}
public void setValue(int x, int y, BoardValues value) {
values[x][y] = value;
}
}
Now instead of using that pesky old 2D Array you just create a board object and set and get it's values at will when needed. Also, I didn't add in getting diagonals but you still could quite easily, mine's just for proof of concept. This is Abstraction, probably the easiest of the OOP concepts to grasp, because it's so general. I am simply obscuring information you don't need to see when you're trying to code your game.

I ran into some problems with Recursion in Java

The task is to implement a program which counts how many different Sums of Primes there are for a given number sumtoBreak.
The Method primeSum should subtract all possible primes currprime from the number sumtoBreak until the sumtoBreak becomes zero and then return (in sum) a one for each possibilty. To account for all possibilities, in each recession step, it calls itself
with sumtoBreak - currprime plus
calls itself with the nextPrime.
My Problem is that java won't return anything unless the sumtoBreak is zero right at the beginning.
Would be glad for any advice!
Here's the code (I know that the parenthesis in the code with the nested if statements are redundant, but I just wanted to make sure, that's not the problem):
Here's the fixed code:
public class PrimeSum {
public static boolean isPrime(int primecandidate) {
int count = 0;
for (int i = 2; i <= primecandidate / 2; i++) {
if (primecandidate % i == 0)
count++;
}
if (count == 0)
return true;
else
return false;
}
public static int nextPrime(int currprime) {
int j = currprime + 1;
while (!isPrime(j))
j++;
return j;
}
public static int primeSum(int sumtoBreak, int currprime) {
if (sumtoBreak == 0) {
return 1;
} else {
if (sumtoBreak < 0 || currprime > sumtoBreak) {
return 0;
} else {
return primeSum(sumtoBreak, nextPrime(currprime)) + primeSum(sumtoBreak - currprime, currprime);
}
}
}
public static void main(String[] args) {
System.out.println(primeSum(Integer.parseInt(args[0]), 2));
}
}
This doesn't answer your question, but corrects an error in your isPrime Method and computes the result much faster:
private static boolean isPrime(final int primecandidate) {
if ( primecandidate < 2) { // 0 & 1 are NOT Prime
return false;
}
if ((primecandidate & 0x1) == 0) { // Even is NOT Prime...
return primecandidate == 2; // ...except for 2 (and 0).
}
for (int i = 2, iMax = (int) Math.sqrt(primecandidate); i <= iMax; i++) {
if (primecandidate % i == 0) {
return false;
}
}
return true;
}
Note the following:
the final argument primecandidate is marked final
it corrects the result for 0 & 1 to false
the method is marked private
the iMax is Sqrt(primecandidate) & not primecandidate / 2
iMax is calculated once, instead of every iteration
I use a strategy I call "if you're done, be done."
Meaning: don't set a flag (in your case count), just get out!
Please note also, there is an apache commons Math3 function...
org.apache.commons.math3.primes.Primes.isPrime(j)
It is significantly slower for smallish values (<= Short.MAX_VALUE)
It is somewhat faster for largeish values (ca. Integer.MAX_VALUE)
There is also a BigInteger.isProbablePrime(...) function, but my Benchmark suggests it is rather slow.
I hope this helps a little?
Some things you might have missed:
in a function, a return statement terminates (break) the function immediatly. So in
if(...) { return ...; }
else {...}
→ else is redundant, as if the condition is true, the function is already terminated (break)
Something like a==0 has a boolean value (true or false). So
if(count==0) { return false; }
else { return true;}
can be shortened to return count!=0;
I recommend to always use braces, because something like if(i==0) ++i; break;, means if(i==0) {++i;}. break; will be called in any case.
public static boolean
isPrime(int n)
{
if(n==0 || n==1) { return false; }
for(int i= 2; i <= n/2; ++i)
{
if(n%i == 0) { return false; } //we know, n is not a prime,
//so function can break here
}
return true; //since for all values of i, the function did not break,
//n is a prime
}
I wish you a lot of motivation to code for the future!

Boolean Satements

public class A4work
{
private static int fibonacci(int n) {
if (n <= 1) {
return n;
}
{
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
private static boolean isAfibonacci(int a) {
int x = 0; //sequence number
int c = 0; //number in fib sequence
while (a <= c) {
c = fibonacci(x);
x++;
}
if (a == c) {
return true;
} else {
return false;
}
}
public static void main(String[] args) //called a method signiture
{
System.out.println("The 5th Square pyramidal number is " + isAfibonacci(3));
}
}
I think I have the code right, but it keeps on returning false. I'm using it to decide if a number is in the fib sequence or not.
Thanks for the help
When you use System.out.println("The 5th Square pyramidal number is "+ isAfibonacci(3) );, a in your isAfibonacci(); method becomes 3. Now look at your code knowing that.
while(3 <= 0) //replaced a with 3 here and c with 0 for visualization
{
...
}
A non-negative, non-zero integer will never be less than or equal to 0, therefore, will always result in false.
If your input a is 5, for example, you will have:
int c = 0; //number in fib sequence
while (a <= c) { ... }
The while loop will never run since 5 <= 0 is false. So a == c will always be false for any a greater than zero.
I think you want to stop iterating when c is greater than or equal to a, so the correct condition would be
while (c < a) { ... }

How do I return these using only one method?

public class newClass {
public static void main(String[] args)
{
int nullValue=0;
int nullValue2=1;
int nullValue3=0;
int nullValue4=0;
int [] sourceArray = {4,5,6,7};
int [] targetArray = new int [4];
for (int i=0; i<sourceArray.length; i++)
{
nullValue+=sourceArray[i];
}
targetArray[0]=nullValue;
// I added all sourceArray elements together and passed it to targetArray[0]
for (int i=0; i<sourceArray.length; i++)
{
nullValue2*=sourceArray[i];
}
targetArray[1]=nullValue2;
// I multiplied all sourceArray elements together and assigned the result to targetArray[1]
for (int i=0; i<sourceArray.length; i++)
{
nullValue3 += getResult(sourceArray[i]);
}
targetArray[2]=nullValue3;
// I tried to add all odd numbers in sourceArray together and assign it to targetArray[2]
for (int i=0; i<sourceArray.length; i++)
{
nullValue4 += getResult(sourceArray[i]);
}
targetArray[3]=nullValue4;
// Same as previous except I need to do that with even numbers.
}
public static int getResult (int x)
{
if (x%2 == 0)
{
return x;
}
else
{
return 0;
}
}
}
You can read my comments above. I realize I can create another method for the last part but I am supposed to use only one method to return odds and evens. I tried almost anything. I can't think of any other ways anymore. Obviously I can't return x in both cases(Yeah I was too desperate to try that).
Straight to the point. I need one method to return x if it's odd or if it's even(We can say it's impossible by the look of that sentence already). I guess that's impossible to do with only one method. I'm not good at java yet so I'm not sure. Maybe there are other ways to do that with only one method which may be so easy. I worked on it for like 6 hours so I'm asking you guys. Thanks.
Create a method to return a boolean if the number is even like so
public static boolean isEven(int x)
{
return (x%2 == 0)
}
Then in your loop for evens
for (int i=0; i<sourceArray.length; i++)
{
if(isEven(x))
nullValue3 += sourceArray[i];
}
For odds just change to if(!isEven(x))
But this is probably deviating from the requirements as you probably want a method that returns an int and you could just put the condition directly in the loop and not need a method
If I understand your question correctly, what you want is to be able to tell the getResult function whether to give you only odd numbers or only even numbers. Without getting complicated, this is what I would do:
public static int getResult(int x, boolean evens) {
if (x % 2 == 0) {
return evens ? x : 0; // shorthand for: if(evens) {return x;} else {return 0;}
} else {
return evens ? 0 : x;
}
}
Simply speaking, I pass a flag value (evens) to the getResult function. This flag tells me whether to filter for even numbers or for odd numbers.
I test whether x is even (x % 2 == 0). If it is, I return it if I'm looking for evens, and I return 0 if I'm looking for odds. If x wasn't even, then I do the opposite.
It would be a little cleaner to write a pair of helper functions, which you could then call from your getResult function.
private static int getIfEven(x) {
if (x % 2 == 0) {
return x;
}
return 0;
}
private static int getIfOdd(x) {
if (x % 2 == 0) {
return 0;
}
return x;
}
public static int getResult(int x, boolean evens) {
// shorthand for:
// if (evens) {
// return getIfEven(x);
// } else {
// return getIfOdd(x);
// }
return evens ? getIfEven(x) : getIfOdd(x);
}
Depending on how much you're allowed to deviate from the current setup (I assume this is homework), you could also just write an isEven(int x) function and call that at each step through the loop, only adding the number if it is/isn't even.

Probability of multiple dice rolls with recursion

How would I go about using recursion to calculate the probability of rolling a certain number, r, with a given number of dice? I tried to treat this as a choose problem but am still quite confused as to how the algorithm should work.
For example, it should work out to be something like this:
P(4,14)=(1/6)P(3,13)+(1/6)P(3,12)+(1/6)P(3,11)+(1/6)P(3,10)+(1/6)P(3,9)+(1/6)P(3,8)
P(3,8)=(1/6)P(2,7)+(1/6)P(2,6)+(1/6)P(2,5)+(1/6)P(2,4)+(1/6)P(2,3)+(1/6)P(2,2)
P(2,4)=(1/6)P(1,3)+(1/6)P(1,2)+(1/6)P(1,1)+(1/6)P(1,0)+(1/6)P(1,-1)+(1/6)P(1,-2)
=(1/6)(1/6)+(1/6)(1/6)+(1/6)(1/6)+(1/6)(0)+(1/6)(0)+(1/6)(0)
I'm just having trouble converting it into code.
static double P(int dice, int r) {
int ret = 1;
for (int i = 2; i < 7; i++) {
ret = (1/6)(ret*(dice-i))/(i+1);
}
return ret;
}
static double RollDice(int dice,int r) {
if (dice==1 && (r<1 || r>6)){
return 0;
}
if (dice==1 && (r>=1 && r<=6)){
return (1.0/6);
}
else {
return ((1.0/6)*P(dice-1,r-1));
}
I do not understand why you have to separate methods P() and RollDice(), since in your formulae you (correctly) describe everything with P.
If you were to put your formulae into code, it should look something like this:
EDIT: changed the base case to 0 dice, since then it becomes even simpler.
static double P(int dice, int r) {
if (dice == 0) {
// Zero dice: probabiliy 1 to get 0
if (r == 0) {
return 1.0;
} else {
return 0.0;
}
else {
// Multiple dice: recursion
double sum = 0.0;
for (/* TODO */) {
sum += //TODO
}
}
}
For the recursion part, try working it out by looking at the formula:
P(4, 14) = (1/6)P(3, 13) + (1/6)P(3, 12) + ... + (1/6)P(3, 8)
i.e. in the general case
P(dice, r)=(1/6)P(dice-1, r-1) + (1/6)P(dice-1, r-2) + ... + (1/6)P(dice-1, r-6)
meaning that you have to loop from r-6 to r-1.
And since you are taking a sum over multiple recursive calls, you have to use an accumulator initialized to 0. (The variable I called sum)
EDIT: Click here for a complete example, compare to WolframAlpha to verify the result.

Categories

Resources