As an extra twist, Maui says that after each roll, he can offer them a certain amount of prize money for them to quit. Perhaps each roll will be represented by a model wearing glittery clothes. He hasn't figured out those details yet. Regardless, he would like to be able to know the probability of success at each phase of the game so that he may set odds. That's where you come in.
Maui wants you to write a program called dond.cpp that will be called with three parameters:
UNIX> dond s t last-roll |
If last-roll is -1, then the program should print the probability of a contestant rolling an s-sided die t times succesfully. Otherwise, it should assume that the contestant has last rolled the value in last-roll, and we now want the probability of rolling the die t more times successfully.
Your program's output should match mine, which does error-check the command line parameters. The solution is a straightforward dynamic program with memoization if you want to structure it that way. You can also ditch the recursion and make it a straightforward iterative program. My solution was dynamic, because it required less thinking.
I won't give any hints or help here -- if you want some help, read the help at the end of this file.
For the grading, your program's output needs to match mine exactly on legal input.
In other words, the numbers alternate in size.
For example, (1, 4, 2, 3, 0) is a zigzag sequence. (1, 4, 5) is not. (1, 1, 4) is not. (1) is.
Your program must print the longest zigzag sequence in v, one number per line. If there are multiple zigzag sequences that are the same size, any one will do.
There are some example files in the lab directory on which to test. There are also two helper programs: islegalzigzag tests whether the zigzag path on standard input is a legal zigzag sequence of the values in the file on the command line. tfill is a program that I use to fill lines of text so that they take up 70 columns -- it is helpful to make output like that of bigzigzag readable. You can use wc to test and see if your zigzag path is as long as mine, and islegalzigzag to make sure that it is legal.
UNIX> cat v1.txt
1 4 2 3 0
UNIX> bigzigzag < v1.txt | tfill
1 4 2 3 0
UNIX> bigzigzag < v1.txt | wc
5 5 10
UNIX> bigzigzag < v1.txt | islegalzigzag v1.txt
Legal
UNIX> cat v2.txt
6 4 0 1 9 6 4 0 2 6 5
UNIX> bigzigzag < v2.txt | tfill
4 1 4 2 6 5
UNIX> bigzigzag < v2.txt | islegalzigzag v2.txt
Legal
UNIX> cat v3.txt
4 5 8 5 4 4 9 9 1 6 7 1 3 1 3 0 7 4 8 4 2 0 9 3 1 9 4 4 4 7 0 0 5 3 1
0 7 1 4 8 8 3 3 0 2 1 4 5 4 0 2 5 5 2 4 7 5 8 5 7 5 8 3 3 2 9 0 9 7 5
8 3 2 5 5 1 8 3 7 5 5 8 6 9 9 2 4 4 9 6 0 7 8 2 0 7 2 0 3 1 7
UNIX> bigzigzag < v3.txt | tfill
4 5 4 9 6 7 1 3 1 3 0 7 4 8 0 3 1 9 4 7 0 1 0 7 1 3 0 2 1 4 2 5 4 7 5
8 5 7 5 8 2 9 0 7 5 8 2 5 1 8 3 7 5 8 6 9 4 6 0 2 0 2 0 3 1 7
UNIX> bigzigzag < v3.txt | wc
66 66 132
UNIX> bigzigzag < v3.txt | islegalzigzag v3.txt
Legal
UNIX> wc v4.txt
59 1001 4004 v4.txt
UNIX> head v4.txt
2.4 8.5 9.5 5.9 7.6 7.6 3.9 9.7 4.4 6.5 4.3 8.9 5.1 6.1 5.7 4.6 9.6
0.4 0.8 0.8 6.3 4.9 2.0 9.0 0.3 5.4 5.4 0.9 7.3 3.8 9.3 2.0 7.0 9.2
2.0 6.6 0.2 7.0 4.3 7.4 1.5 5.8 0.8 9.8 7.5 8.7 0.0 3.4 1.6 3.4 6.4
6.2 5.8 5.4 9.4 1.7 7.9 8.3 7.9 4.8 3.3 3.4 8.9 9.4 9.5 3.6 1.3 0.3
6.1 4.2 9.7 6.2 4.6 5.5 2.4 5.9 4.9 6.5 4.9 1.7 9.7 7.4 6.6 2.4 3.4
0.7 8.7 5.2 0.0 6.8 0.9 0.5 6.0 5.4 0.7 3.8 9.5 5.3 9.0 3.6 2.2 1.8
6.0 5.4 1.5 7.3 3.9 0.7 1.5 8.2 4.3 0.1 3.5 1.6 2.2 6.9 3.8 1.2 1.9
9.5 2.0 0.3 2.4 1.5 2.9 6.6 6.3 9.0 0.3 1.1 7.5 4.9 6.4 8.6 5.5 3.0
8.7 9.2 9.9 3.2 5.4 1.4 6.0 0.0 7.4 5.4 6.0 3.7 2.2 2.8 7.8 7.9 8.0
8.8 3.2 2.0 8.5 5.0 9.1 8.9 9.1 0.5 5.5 4.5 4.7 3.7 1.9 4.7 8.9 9.7
UNIX> bigzigzag < v4.txt | wc
664 664 2502
UNIX> bigzigzag < v4.txt | islegalzigzag v4.txt
Legal
UNIX> wc v5.txt
589 10001 40004 v5.txt
UNIX> head v5.txt
6.1 0.5 3.3 2.0 9.2 3.3 1.0 5.2 9.9 9.7 7.2 6.8 6.8 1.7 0.4 0.8 6.4
2.3 5.2 0.6 8.2 5.0 5.7 1.8 2.9 8.2 7.3 8.6 0.9 2.0 7.0 5.8 5.0 5.5
8.3 7.3 2.8 6.4 6.5 3.8 8.8 4.5 6.4 1.1 7.3 3.0 5.0 9.5 6.7 5.6 1.1
1.8 6.3 9.7 5.5 8.4 3.0 3.5 4.0 7.5 8.1 5.5 6.8 0.0 0.7 5.4 0.5 5.9
3.4 5.1 4.0 4.9 1.2 7.6 3.3 6.5 2.6 1.5 7.2 1.9 4.2 9.5 1.6 9.9 3.5
0.5 9.2 7.8 7.4 0.8 3.4 9.8 9.2 6.7 0.3 6.2 7.4 0.7 0.9 6.3 2.6 8.7
9.1 9.3 9.5 7.7 2.3 8.3 1.7 2.8 0.3 0.3 3.0 0.2 7.0 4.4 9.0 4.5 7.8
2.1 5.8 6.3 3.2 0.9 6.0 9.5 8.8 0.2 2.5 5.1 1.1 8.5 2.6 3.0 3.2 7.1
4.2 9.6 7.2 7.2 6.7 1.2 1.4 8.1 1.7 4.0 9.2 1.3 2.4 4.4 9.8 6.3 6.8
7.0 3.4 7.1 7.5 8.6 4.9 7.6 7.8 5.0 9.3 5.1 3.6 4.1 9.5 5.6 2.8 8.7
UNIX> bigzigzag < v5.txt | wc
6580 6580 24980
UNIX> bigzigzag < v5.txt | islegalzigzag v5.txt
Legal
UNIX> time bigzigzag < v5.txt > /dev/null
12.074u 0.025s 0:12.10 99.9% 0+0k 0+0io 0pf+0w
UNIX> bigzigzag < v5.txt > v5p.txt
UNIX> time islegalzigzag < v5p.txt v5.txt
Legal
0.707u 1.047s 0:01.79 97.2% 0+0k 0+0io 0pf+0w
UNIX>
That's pretty slow -- you could make it a lot faster, but I won't so as not to set the
bar too high for y'all.
As before, I have help at the end of the file if you want it.
For the grading, your program simply needs to output the sequence with any formatting (as long as there are lines/whitespace between the numbers), and the sequence needs to be the correct length and pass the program islegalzigzag.
UNIX> dond 6 1 -1 1 UNIX> dond 6 1 0 0.666667 UNIX> dond 6 1 1 0.5 UNIX> dond 6 1 2 0.5 UNIX> dond 6 1 3 0.5 UNIX> dond 6 1 4 0.5 UNIX> dond 6 1 5 0.666667 UNIX>So, consider t=2 and last-roll=-1. This will be the sum of times that t=1 and lastroll ≠ -1, divided by six. Put another way, you have a 1/6 probability of rolling a zero. If you roll a zero, you have a 2/3 chance of winning. Ditto when you roll a five. If you roll a 1 through 4, you have a 1/2 chance of winning. So, your probability of winning when t=2 is 1/6 * (2/3 + 2/3 + 1/2 + 1/2 + 1/2 + 1/2). That value is 0.555556:
UNIX> dond 6 2 -1 0.555556 UNIX>Now consider t=2 and last-roll=0. Well, 1/6 of the time, you will roll a zero on your next roll, and 1/6 of the time, you will roll a one. In each of those, you lose. However, 1/6 of the time, you will roll a 2, and your chance of winning will be "dond 6 1 2", which is 1/2. The same is true when you roll a 3 or a 4. 1/6 of the time, you'll roll a 5, and your chance of winning will be 2/3. Therefore, if t=2 and last-roll=0, your chance of winning will be 1/6*(0 + 0 + 1/2 + 1/2 + 1/2 + 2/3). That value is 0.361111:
UNIX> dond 6 2 0 0.361111 UNIX>You should be able to confirm all of the calls below by hand. For example, dond 6 2 1 will equal 1/6*(0 + 0 + 0 + 1/2 + 1/2 + 2/3), and dond 6 2 2 will equal 1/6*(2/3 + 0 + 0 + 1/2 + 1/2 + 2/3).
UNIX> dond 6 2 1 0.277778 UNIX> dond 6 2 2 0.305556 UNIX> dond 6 2 3 0.305556 UNIX> dond 6 2 4 0.277778 UNIX> dond 6 2 5 0.361111 UNIX>The recursion should be getting clearer. dond 6 2 2 will equal 1/6*(0.361111 + 0.277778 + 0.305556 + 0.305556 + 0.277778 + 0.361111) = 0.314815:
UNIX> dond 6 3 -1 0.314815 UNIX>
| i | v[i] | up[i] | down[i] | up_path[i] | down_path[i] |
| 0 | 6 | 1 | 1 | -1 | -1 |
| 1 | 4 | 1 | 2 | -1 | 0 |
| 2 | 0 | 1 | 2 | -1 | 1 |
| 3 | 1 | 3 | 2 | 2 | 1 |
| 4 | 9 | 3 | 1 | 3 | -1 |
| 5 | 6 | 3 | 4 | 3 | 4 |
| 6 | 4 | 3 | 4 | 3 | 5 |
| 7 | 0 | 1 | 4 | -1 | 6 |
| 8 | 2 | 5 | 4 | 7 | 6 |
| 9 | 6 | 5 | 4 | 8 | 4 |
| 10 | 5 | 5 | 6 | 8 | 9 |
Look at the line where i=1. Since 4 is less than 6, there is no subsequence ending with that 4 where 4 is greater than the previous value. For that reason, up[1] = 1. However, there is a subsequence which ends with 4 where 4 is less than the previous value, and thus down[1] = 2.
When you set up[i], down[i], up_path[i] and down_path[i], you will need to check all smaller values of i. When you think you have it right, make sure you check your output against v3.txt, v4.txt and v6.txt. I have all the arrays in v1.html, v2.html, v3.html, v4.html and v6.html. The program bzz-html creates these files. When you're having problems, check your arrays against these.