CS 111 - Introduction to Computer Science
Homework #11

Due at the beginning of class 33.

1. Three-Pile Nim: Call your program ThreePileNim.java. In the 3-pile game of Nim, two players begin with three piles containing one or more objects. In turn, each player chooses a non-empty pile and removes one or more objects from it.  (It is legal to take all objects of a pile.)  The player taking the last object of the last pile wins.  (The version of 3-pile Nim where the one taking the last object loses is called Misere' Nim.)

In your implementation, you should internally represent the number of objects in each pile as an array of length 3.  Position n in that array will contain the number of objects in pile n.  The program initially reads the 3 initial pile sizes from the user.  Assume that these will be positive integers.  Then the game will begin. 

At the beginning of each turn, the current state of each pile is represented in text as one line per pile, each with the 0-based pile number followed by a colon and a number of asterisks equal to the number of objects currently in the pile.  Then the user inputs two integers: (1) the 0-based  pile number, and (2) the number of objects that are to be removed from that pile.  Assume that such input is a legal play.  Turns continue until all piles are empty.  (Nothing is printed after the final losing play.)

Input/output should be as shown in the following transcript.

Sample transcript (input underlined):

5 4 2
0:*****
1:****
2:**
2 1
0:*****
1:****
2:*
0 3
0:**
1:****
2:*
1 1
0:**
1:***
2:*
1 2
0:**
1:*
2:*
0 1
0:*
1:*
2:*
2 1
0:*
1:*
2:
0 1
0:
1:*
2:
1 1

Hint: If done simply, the main method needs only about a dozen lines of code.

2. BigFraction: Call your class BigFraction.java and implement it according to this specification.  You will note that BigFraction is composed of BigInteger numerator and BigInteger denominator.  Like BigInteger and BigDecimal, BigFraction is immutable.  Also, take care to simplify all fractions during construction using the BigInteger gcd method and dividing both numerator and denominator by their greatest common divisor, noting that BigInteger has its own given gcd method.  In our specification, the denominator is always positive; only the numerator can be either positive or negative.  For a refresher on fraction arithmetic, see here

3. Pig Scoring Probability: Call your class PigMath.java and implement it according to this specification.  A method public static BigFraction probabilityOfRolling(int target) returns the probability of rolling a Pig turn total of at least a given target number of points. This exercise makes use of BigFraction object for probabilities, but itself is just the implementation method static BigFractionprobabilityOfRolling(int target) and a main method provided below for testing.

The algorithm can be described as follows: Create an array p indexed by turn total t for computing p[t], the probability for reaching at least the target turn total from the current turn total t.  Initially, p[t] = 0 for t < target and p[t] = 1 for t >= target. Then, working from t=target-1 down to t=0, you can compute each p[t] = p[t+2]/6 + p[t+3]/6 + p[t+4]/6 + p[t+5]/6 + p[t+6]/6. (In other words, a non-1 roll with probability 1/6 will contribute to the current turn total success by 1/6 times the probability of success at the next turn total reached by the roll.) This calculation working backwards is called retrograde analysis, and you'll be working with BigFraction objects for exact computation.

Example: To compute the probability of reaching a target of 3, array p contains BigFraction values for {0, 0, 0, 1, 1, 1, 1, 1, 1}.
Working backwards from t = 2 down to 0:
p[2] = p[2+2]/6 + p[2+3]/6 + p[2+4]/6 + p[2+5]/6 + p[2+6]/6 = 1/6 + 1/6 + 1/6 + 1/6 + 1/6 = 5/6.
p[1] = p[1+2]/6 + p[1+3]/6 + p[1+4]/6 + p[1+5]/6 + p[1+6]/6 = 1/6 + 1/6 + 1/6 + 1/6 + 1/6 = 5/6.
p[0] = p[0+2]/6 + p[0+3]/6 + p[0+4]/6 + p[0+5]/6 + p[0+6]/6 = (5/6)/6 + 1/6 + 1/6 + 1/6 + 1/6 = 29/36.

Use loops for (1) initializing your p values, (2) iterating down through the turn totals, and (3) iterating through the roll numbers 2-6 for each turn total.

A spreadsheet demonstrating this computation for target 100 is available in XLSX and ODS formats.

Main method:

	/**
* Test probabilityOfRolling(100). The result should be "The probability in Pig of rolling at least 100 on a single turn is approximately 0.010197 and exactly 2060507550845146798433160823128452341/202070319366191015160784900114134073344."
* @param args (unused)
*/
public static void main(String[] args) {
int target = 100;
BigFraction frac = probabilityOfRolling(target);
System.out.printf("The probability in Pig of rolling at least %d on a single turn is approximately %f and exactly %s.\n", target, frac.asBigDecimal(6, RoundingMode.HALF_UP).doubleValue(), frac);
}

Rubric: (20 points total)