-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
1459 lines (1080 loc) · 63.4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="description" content ="CS 61A: Structure and Interpretation of Computer Programs" />
<meta name="keywords" content ="CS 61A, Computer Science, CS, 61A, Programming, John DeNero, Berkeley, EECS" />
<meta name="author" content ="John DeNero, Justin Yokota" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-throttle-debounce/1.1/jquery.ba-throttle-debounce.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="/assets/js/hl.js"></script>
<script src="/assets/js/toggledarkmode.js"></script>
<script>
// we aren't registering builtins since
// (1) they don't render differently in the current CSS from other names
// (2) it's a mess to list all of them. You can extract from the site but that takes effort
// if (1) ceases to be true, (2) might be worth the effort. For now, we're leaving as is
hljsRegister({
'keyword': "define if cond and or let begin lambda mu quote delay cons-stream set! quasiquote unquote unquote-splicing define-macro"
});
hljs.initHighlightingOnLoad();
</script>
<script src="/assets/js/dark-mode.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inconsolata|Roboto:300,400,500|Work+Sans:400,700">
<link rel="stylesheet" href="/assets/css/style.css">
<link rel="stylesheet" href="/assets/css/mono-blue.css">
<link rel="icon" href="/assets/images/favicon.ico">
<link href="/assets/css/project.css" rel="stylesheet" type="text/css">
<title>
Project 1: The Game of Hog | CS 61A Fall 2022
</title>
</head>
<body id="index" class="home">
<nav class="navbar navbar-default navbar-static-top">
<div class="container noselect">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse-section">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
<img style="max-width:60px; margin-top: -20px;" class="logo" src="/assets/images/logo.png"/>
</a>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse-section">
<ul class="nav navbar-nav navbar-right">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Calendar
<span class="caret"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a href="/weekly">Weekly Schedule</a></li>
<li><a href="/office-hours">Office Hours</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Staff
<span class="caret"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a href="/instructor">Instructors</a></li>
<li><a href="/TAs">TAs</a></li>
<li><a href="/tutors">Tutors</a></li>
<li><a href="/academic-interns">Academic Interns</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Resources
<span class="caret"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a href="https://go.cs61a.org/extensions">Request an Extension</a></li>
<li><a href="https://go.cs61a.org/accommodation-appts">Book an Accommodations Appointment</a></li>
<li><a href="/resources/">Topical Resources + Past Exams</a></li>
<li><a href="https://tutor.cs61a.org/">PythonTutor</a></li>
<li><a href="https://code.cs61a.org/">Code</a></li>
<li><a href="https://edstem.org/us/courses/25379/discussion/" target="_blank">Ed</a></li>
<li><a href="/articles/campus-res/">Department/Campus Resources</a></li>
</ul>
</li>
<li><a href="/articles/about">Syllabus</a></li>
<li><a href="/contact/">Contact</a></li>
<li>
<label class="switch">
<input type="checkbox" id="toggle-mode-cb">
<span class="slider round"></span>
</label>
</li>
</ul>
</div>
</div>
</nav>
<main id="content" class="container">
<div class='row'>
<div class='col-md-9'>
<header>
<h1>
Project 1: The Game of Hog
<ul class="inline-block list-inline">
<li><a href="hog.zip" class="label label-outline">hog.zip</a></li>
</ul>
</h1>
</header>
<div class="haiku">
<blockquote><p><img class="img-responsive center-block" src="assets/icon.gif" alt="5-sided die" width="" height=""></p>
<cite> I know! I'll use my<br/> Higher-order functions to<br/> Order higher
rolls. </cite></blockquote>
</div>
<h2 id="introduction">Introduction</h2>
<blockquote><p><strong>Important submission note:</strong> For full credit:</p>
<ul>
<li>Submit with Phase 1 complete by <strong>Tuesday, Sept 6</strong>, worth 1 pt.</li>
<li>Submit the complete project by <strong>Friday, Sept 9</strong>.</li>
</ul>
<p>Try to attempt the problems in order, as some later problems will depend on
earlier problems in their implementation and therefore also when running <code>ok</code>
tests.</p>
<p>You may complete the project with a partner.</p>
<p>You can get 1 bonus point by submitting the entire project by <strong>Thursday, Sept 8</strong>
You can receive extensions on the project deadline and checkpoint
deadline, but not on the early deadline, unless you're a DSP student with an
accommodation for assignment extensions.</p></blockquote>
<p>In this project, you will develop a simulator and multiple strategies for the
dice game Hog. You will need to use <em>control statements</em> and <em>higher-order
functions</em> together, as described in Sections 1.2 through 1.6 of <a href="http://composingprograms.com">Composing
Programs</a>, the online textbook.</p>
<blockquote><p>When students in the past have tried to implement the functions without
thoroughly reading the problem description, they’ve often run into issues.
😱
<strong>Read each description thoroughly before starting to code.</strong></p></blockquote>
<h3 id="rules">Rules</h3>
<p>In Hog, two players alternate turns trying to be the first to end a turn with
at least <code>GOAL</code> total points, where <code>GOAL</code> defaults to 100. On each turn, the current player chooses some number
of dice to roll, up to 10. That player's score for the turn is the sum of the
dice outcomes. However, a player who rolls too many dice risks:</p>
<ul>
<li><strong>Sow Sad</strong>. If any of the dice outcomes is a 1, the current player's score
for the turn is <code>1</code>.</li>
</ul>
<button id='toggle-1' class='btn btn-outline btn-lg alwaystoggle toggle'>
Examples<noscript> (enable JavaScript)</noscript>
</button>
<div class="solution toggle-1">
<ul>
<li><em>Example 1:</em> The current player rolls 7 dice, 5 of which are 1's. They
score <code>1</code> point for the turn.</li>
<li><em>Example 2:</em> The current player rolls 4 dice, all of which are 3's. Since
Sow Sad did not occur, they score <code>12</code> points for the turn.</li>
</ul>
</div>
<p>In a normal game of Hog, those are all the rules. To spice up the game, we'll
include some special rules:</p>
<ul>
<li><strong>Pig Tail</strong>. A player who chooses to roll zero dice scores
<code>2 * abs(tens - ones) + 1</code> points; where <code>tens</code>, <code>ones</code> are the
tens and ones digits of the opponent's score. The ones digit refers to the
rightmost digit and the tens digit refers to the second-rightmost digit.</li>
</ul>
<button id='toggle-2' class='btn btn-outline btn-lg alwaystoggle toggle'>
Examples<noscript> (enable JavaScript)</noscript>
</button>
<div class="solution toggle-2">
<ul>
<li><p><em>Example 1:</em></p>
<ul>
<li>The opponent has <code>46</code> points, and the current player chooses to roll
zero dice. <code>2 * abs(4 - 6) + 1 = 5</code>, so the player gains <code>5</code> points.</li>
</ul></li>
<li><p><em>Example 2:</em></p>
<ul>
<li>The opponent has <code>73</code> points, and the current player chooses to roll
zero dice. <code>2 * abs(7 - 3) + 1 = 9</code>.</li>
</ul></li>
</ul>
</div>
<ul>
<li><strong>Square Swine</strong>. After a player gains points for their turn, if the
resulting score is a perfect square, then increase their score to the next
higher perfect square. A perfect square is any integer <code>n</code> where <code>n = d * d</code> for some integer <code>d</code>.</li>
</ul>
<button id='toggle-3' class='btn btn-outline btn-lg alwaystoggle toggle'>
Examples<noscript> (enable JavaScript)</noscript>
</button>
<div class="solution toggle-3">
<ul>
<li><p><em>Example 1:</em></p>
<ul>
<li>A player has 12 points and rolls 3 dice that total 13 points. Their
new score would be 25, but since 25 is 5 squared, their score is
increased to 6 squared: 36.</li>
</ul></li>
<li><p><em>Example 2:</em></p>
<ul>
<li>A player has 12 points and rolls 3 dice that total 12 point. Their new
score would be 24, which is not a perfect square.</li>
</ul></li>
<li><p><em>Example 3:</em></p>
<ul>
<li>A player has 0 points and rolls 5 dice, but one is a 1, so their new
score would be 1. 1 is a perfect square, and so their score is
increased to 4.</li>
</ul></li>
<li><p><em>Example 4:</em></p>
<ul>
<li>A player has 80 points and rolls 10 dice, but three are 1's, so their
new score would be 1. 81 is 9 squared, so their new score is 10
squared: 100. They win the game.</li>
</ul></li>
</ul>
</div>
<h2 id="download-starter-files">Download starter files</h2>
<p>To get started, download all of the project code as a <a href="hog.zip">zip archive</a>.
Below is a list of all the files you will see in the archive once unzipped.
For the project, you'll only be making changes to <code>hog.py</code>.</p>
<ul>
<li><code>hog.py</code>: A starter implementation of Hog</li>
<li><code>dice.py</code>: Functions for making and rolling dice</li>
<li><code>ucb.py</code>: Utility functions for CS 61A</li>
<li><code>hog_ui.py</code>: A text-based user interface (UI) for Hog</li>
<li><code>ok</code>: CS 61A autograder</li>
<li><code>tests</code>: A directory of tests used by <code>ok</code></li>
</ul>
<p>Please do not modify any files other than <code>hog.py</code>.</p>
<h2 id="logistics">Logistics</h2>
<!-- <p>Remember that you can earn an additional bonus point by submitting the
project at least 24 hours before the deadline.</p> -->
<p>The project is worth 25 points, of which 1 point is for submitting
Phase 1 by the checkpoint date of Tuesday, Sept 6.</p>
<p>You will turn in the following files:</p>
<ul>
<li><code>hog.py</code></li>
</ul>
<p>You do not need to modify or turn in any other files to complete the
project. To submit the project, run the following command:</p>
<pre><code>python3 ok --submit</code></pre>
<p>You will be able to view your submissions on the <a
href="http://ok.cs61a.org">Ok dashboard</a>.</p>
<p>For the functions that we ask you to complete, there may be some
initial code that we provide. If you would rather not use that code,
feel free to delete it and start from scratch. You may also add new
function definitions as you see fit.</p>
<p><b>However, please do not modify any other functions or edit any files not
listed above</b>. Doing so may result in your code failing our autograder tests.
Also, please do not change any function signatures (names, argument order, or
number of arguments).</p>
<p>Throughout this project, you should be testing the correctness of your code.
It is good practice to test often, so that it is easy to isolate any problems.
However, you should not be testing <i>too</i> often, to allow yourself time to
think through problems.</p>
<p>We have provided an <b>autograder</b> called <code>ok</code> to help you
with testing your code and tracking your progress. The first time you run the
autograder, you will be asked to <b>log in with your Ok account using your web
browser</b>. Please do so. Each time you run <code>ok</code>, it will back up
your work and progress on our servers.</p>
<p>The primary purpose of <code>ok</code> is to test your implementations.</p>
<!-- <p>First, some of the test cases are <i>locked</i>. To unlock tests, run the
following command from your terminal:</p>
<pre><code>python3 ok -u</code></pre>
<p>This command will start an interactive prompt that looks like:</p>
<pre>
=====================================================================
Assignment: The Game of Hog
Ok, version ...
=====================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests
At each "? ", type what you would expect the output to be.
Type exit() to quit
---------------------------------------------------------------------
Question 0 > Suite 1 > Case 1
(cases remaining: 1)
>>> Code here
?
</pre>
<p>At the <code>?</code>, you can type what you expect the output to be. If you
are correct, then this test case will be available the next time you run the
autograder.</p>
<p>The idea is to understand <i>conceptually</i> what your program should do
first, before you start writing any code.</p>
<p>Once you have unlocked some tests and written some code, you can check the
correctness of your program using the tests that you have unlocked:</p>
<pre>python3 ok</pre>
<p>Most of the time, you will want to focus on a particular question. Use the
<code>-q</code> option as directed in the problems below.</p> -->
<!-- <p>Second, there may be some test cases that are <i>hidden</i>. These test cases are
<b>not</b> run by the command:</p> -->
<!--<pre>python3 ok</pre>-->
<!-- <p>They are only run when you submit:</p> -->
<!-- <pre>python3 ok --submit</pre> -->
<!-- <p> We keep test cases hidden to ensure that you write your code with the intention
of solving the question at hand, not purely to pass the given tests. The hidden
tests will be run when you submit your project. You will receive an email with part of
the autograder results after submitting. However, the autograder has a 15 minute
cooldown period. If you submit before 15 minutes have passed, the autograder will
not run.</p> -->
<p>We recommend that you submit <b>after you finish each
problem</b>. Only your last submission will be graded. It is also useful for us
to have more backups of your code in case you run into a submission issue. <b>If you forget to submit, your last backup will be automatically converted to a submission. </b></p>
<!--<p>After you run this command, you will receive an email (to the address-->
<!--that you used to sign up for Ok) that has the output from all <i>failed</i>-->
<!--unlocked tests, including hidden tests, along with your score at the bottom. You-->
<!--can continue submitting until you pass all the tests. However, you will receive-->
<!--<b>at most one email every half hour</b>.</p>-->
<!--<p>This buffer period is meant for you and your partner to try and understand-->
<!--where your error comes from, and take some time to think through your code. We-->
<!--encourage you to do this for all projects.</p>-->
<!---
<p>If you are trying to debug a test failure, you can launch an interactive session
after the test is run with:</p>
<pre><code>python3 ok -q 05 -i</code></pre>
<p>This will run the tests and launch an interactive session if a test does not
pass.</p>
<pre><code>=====================================================================
Assignment: Project 1: Hog
Ok, version ....
=====================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests
---------------------------------------------------------------------
Question ... > Suite ... > Case ...
>>> the_test()
"expected value"
# Error: expected
# "expected value"
# but got
# None
# Interactive console. Type exit() to quit
>>></code></pre>
-->
<!--- <p>The <code>tests</code> folder is used to store autograder tests, so
<b>do not modify it</b>. You may lose all your unlocking progress if you
do. If you need to get a fresh copy, you can download the
<a href="hog.zip">zip archive</a> and copy it over, but you
will need to start unlocking from scratch.</p> -->
<p>If you do not want us to record a backup of your work or information about
your progress, you can run
<pre>python3 ok --local</pre>
With this option, no information will be sent to our course
servers.
If you want to test your code interactively, you can run
<pre> python3 ok -q [question number] -i </pre>
with the appropriate question number (e.g. <code>01</code>) inserted.
This will run the tests for that question until the first one you failed,
then give you a chance to test the functions you wrote interactively.</p>
<p>You can also use the debugging print feature in OK by writing
<pre> print("DEBUG:", x) </pre>
which will produce an output in your terminal without causing OK tests to fail
with extra output.
<h2 id="phase-1-rules-of-the-game">Phase 1: Rules of the Game</h2>
<p>In the first phase, you will develop a simulator for the game of Hog.</p>
<h3 id="problem-0-0-pt">Problem 0 (0 pt)</h3>
<p>The <code>dice.py</code> file represents dice using non-pure zero-argument functions.
These functions are non-pure because they may have different return values each
time they are called, and so a side-effect of calling the function may be
changing what will happen when the function is called again. The documentation
of <code>dice.py</code> describes the two different types of dice used in the project:</p>
<ul>
<li><strong>Fair</strong> dice produce each possible outcome with equal probability. The
<code>four_sided</code> and <code>six_sided</code> functions are examples.</li>
<li><strong>Test</strong> dice are deterministic: they always cycle through a fixed sequence
of values that are passed as arguments. Test dice are generated by the
<code>make_test_dice</code> function.</li>
</ul>
<p>Before writing any code, read over the <code>dice.py</code> file and check your
understanding by unlocking the following tests.</p>
<pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 00 -u<button id="copy-code-python3ok-q00-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q00-u").onclick = () => copyCode('python3 ok -q 00 -u', "copy-code-python3ok-q00-u");
</script>
<br/>
<p>This should display a prompt that looks like this:</p>
<pre><code> =====================================================================
Assignment: Project 1: Hog Ok, version v1.18.1
=====================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests
At each "? ", type what you would expect the output to be. Type exit() to quit
---------------------------------------------------------------------
Question 0 > Suite 1 > Case 1
(cases remaining: 1)
>>> test_dice = make_test_dice(4, 1, 2)
>>> test_dice()
?</code></pre>
<p>You should type in what you expect the output to be. To do so, you need to
first figure out what <code>test_dice</code> will do, based on the description above.</p>
<p>You can exit the unlocker by typing <code>exit()</code>.</p>
<p><strong>Typing Ctrl-C on Windows to exit out of the unlocker has been known to cause
problems, so avoid doing so.</strong></p>
<h3 id="problem-1-2-pt">Problem 1 (2 pt)</h3>
<p>Implement the <code>roll_dice</code> function in <code>hog.py</code>. It takes two arguments: a
positive integer called <code>num_rolls</code> giving the number of dice to roll and a
<code>dice</code> function. It returns the number of points scored by rolling the dice
that number of times in a turn: either the sum of the outcomes or 1 <em>(Sow
Sad)</em>.</p>
<ul>
<li><strong>Sow Sad</strong>. If any of the dice outcomes is a 1, the current player's score
for the turn is <code>1</code>.</li>
</ul>
<button id='toggle-4' class='btn btn-outline btn-lg alwaystoggle toggle'>
Examples<noscript> (enable JavaScript)</noscript>
</button>
<div class="solution toggle-4">
<ul>
<li><em>Example 1:</em> The current player rolls 7 dice, 5 of which are 1's. They
score <code>1</code> point for the turn.</li>
<li><em>Example 2:</em> The current player rolls 4 dice, all of which are 3's. Since
Sow Sad did not occur, they score <code>12</code> points for the turn.</li>
</ul>
</div>
<p>To obtain a single outcome of a dice roll, call <code>dice()</code>. You should call
<code>dice()</code> <strong>exactly <code>num_rolls</code> times</strong> in the body of <code>roll_dice</code>.</p>
<p>Remember to call <code>dice()</code> exactly <code>num_rolls</code> times <strong>even if Sow Sad happens
in the middle of rolling</strong>. By doing so, you will correctly simulate rolling
all the dice together (and the user interface will work correctly).</p>
<blockquote><p><strong>Note:</strong> The <code>roll_dice</code> function, and many other functions throughout the
project, makes use of <em>default argument values</em>—you can see this in the
function heading:</p>
<pre><code>def roll_dice(num_rolls, dice=six_sided): ...</code></pre>
<p>The argument <code>dice=six_sided</code> means that when <code>roll_dice</code> is called, the
<code>dice</code> argument is <strong>optional</strong>. If no value for <code>dice</code> is provided, then
<code>six_sided</code> is used by default.</p>
<p>For example, calling <code>roll_dice(3, four_sided)</code>, or equivalently <code>roll_dice(3,
dice=four_sided)</code>, simulates rolling 3 four-sided dice, while calling <code>roll_dice(3)</code>
simulates rolling 3 six-sided dice.</p></blockquote>
<p><strong>Understand the problem</strong>:</p>
<p>Before writing any code, unlock the tests to verify your understanding of the question:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 01 -u<button id="copy-code-python3ok-q01-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q01-u").onclick = () => copyCode('python3 ok -q 01 -u', "copy-code-python3ok-q01-u");
</script>
<br/>
<blockquote><p><strong>Note:</strong> You will not be able to test your code using <code>ok</code> until you unlock
the test cases for the corresponding question.</p></blockquote>
<p><strong>Write code and check your work</strong>:</p>
<p>Once you are done unlocking, begin implementing your solution. You can check your correctness with:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 01<button id="copy-code-python3ok-q01" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q01").onclick = () => copyCode('python3 ok -q 01', "copy-code-python3ok-q01");
</script>
<br/>
<button id='toggle-5' class='btn btn-outline btn-lg alwaystoggle toggle'>
Debugging Tips<noscript> (enable JavaScript)</noscript>
</button>
<div class="solution toggle-5">
<p>Check out the <a href="/articles/debugging/">Debugging Guide</a>!</p>
<h4 id="debugging-tips">Debugging Tips</h4>
<p>If the tests don't pass, it's time to debug. You can observe the behavior of
your function using Python directly. First, start the Python interpreter and
load the <code>hog.py</code> file.</p>
<pre><code>python3 -i hog.py</code></pre>
<p>Then, you can call your <code>roll_dice</code> function on any number of dice you want.
The <code>roll_dice</code> function has a <a href="">default argument value</a> for <code>dice</code> that is a
random six-sided dice function. Therefore, the following call to <code>roll_dice</code>
simulates rolling four fair six-sided dice.</p>
<pre><code>>>> roll_dice(4)</code></pre>
<p>You will find that the previous expression may have a different result each
time you call it, since it is simulating random dice rolls. You can also use
test dice that fix the outcomes of the dice in advance. For example, rolling
twice when you know that the dice will come up 3 and 4 should give a total
outcome of 7.</p>
<pre><code>>>> fixed_dice = make_test_dice(3, 4) roll_dice(2, fixed_dice)
7</code></pre>
<blockquote><p>On most systems, you can evaluate the same expression again by pressing the
up arrow, then pressing enter or return. To evaluate earlier commands, press
the up arrow repeatedly.</p>
<p>If you find a problem, you first need to change your <code>hog.py</code> file to fix the
problem, and save the file. Then, to check whether your fix works, you'll
have to quit the Python interpreter by either using <code>exit()</code> or <code>Ctrl^D</code>, and
re-run the interpreter to test the changes you made. Pressing the up arrow in
both the terminal and the Python interpreter should give you access to your
previous expressions, even after restarting Python.</p></blockquote>
<p>[default argument value]:
http://composingprograms.com/pages/14-designing-functions.html#default-argument-values</p>
<blockquote><p>Continue debugging your code and running the <code>ok</code> tests until they all pass.</p>
<p>One more debugging tip: to start the interactive interpreter automatically
upon failing an <code>ok</code> test, use <code>-i</code>. For example, <code>python3 ok -q 01 -i</code> will
run the tests for question 1, then start an interactive interpreter with
<code>hog.py</code> loaded if a test fails.</p></blockquote>
</div>
<h3 id="problem-2-2-pt">Problem 2 (2 pt)</h3>
<p>Implement <code>tail_points</code>, which takes the player's opponent's current score
<code>opponent_score</code>, and returns the number of points scored by Pig Tail when the
player rolls 0 dice.</p>
<ul>
<li><strong>Pig Tail</strong>. A player who chooses to roll zero dice scores
<code>2 * abs(tens - ones) + 1</code> points; where <code>tens</code>, <code>ones</code> are the
tens and ones digits of the opponent's score. The ones digit refers to the
rightmost digit and the tens digit refers to the second-rightmost digit.</li>
</ul>
<button id='toggle-6' class='btn btn-outline btn-lg alwaystoggle toggle'>
Examples<noscript> (enable JavaScript)</noscript>
</button>
<div class="solution toggle-6">
<ul>
<li><p><em>Example 1:</em></p>
<ul>
<li>The opponent has <code>46</code> points, and the current player chooses to roll
zero dice. <code>2 * abs(4 - 6) + 1 = 5</code>, so the player gains <code>5</code> points.</li>
</ul></li>
<li><p><em>Example 2:</em></p>
<ul>
<li>The opponent has <code>73</code> points, and the current player chooses to roll
zero dice. <code>2 * abs(7 - 3) + 1 = 9</code>.</li>
</ul></li>
</ul>
</div>
<blockquote><p>Don't assume that scores are below 100. Write your <code>tail_points</code> function so
that it works correctly for any non-negative score.</p></blockquote>
<!-- separate block quotes -->
<blockquote><p><strong>Important:</strong> Your implementation should <strong>not</strong> use <code>str</code>, lists, or
contain square brackets <code>[</code> <code>]</code>. The test cases will check if those have
been used.</p></blockquote>
<p>Before writing any code, unlock the tests to verify your understanding of the question:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 02 -u<button id="copy-code-python3ok-q02-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q02-u").onclick = () => copyCode('python3 ok -q 02 -u', "copy-code-python3ok-q02-u");
</script>
<br/> <p>Once you are done unlocking, begin implementing your solution. You can check your correctness with:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 02<button id="copy-code-python3ok-q02" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q02").onclick = () => copyCode('python3 ok -q 02', "copy-code-python3ok-q02");
</script>
<br/>
<p>You can also test <code>tail_points</code> interactively by running <code>python3 -i hog.py</code>
from the terminal and calling <code>tail_points</code> on various inputs.</p>
<h3 id="problem-3-2-pt">Problem 3 (2 pt)</h3>
<p>Implement the <code>take_turn</code> function, which returns the number of points scored
for a turn by rolling the given <code>dice</code> <code>num_rolls</code> times.</p>
<p>Your implementation of <code>take_turn</code> should call both <code>roll_dice</code> and
<code>tail_points</code> rather than repeating their implementations.</p>
<p>Before writing any code, unlock the tests to verify your understanding of the question:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 03 -u<button id="copy-code-python3ok-q03-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q03-u").onclick = () => copyCode('python3 ok -q 03 -u', "copy-code-python3ok-q03-u");
</script>
<br/> <p>Once you are done unlocking, begin implementing your solution. You can check your correctness with:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 03<button id="copy-code-python3ok-q03" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q03").onclick = () => copyCode('python3 ok -q 03', "copy-code-python3ok-q03");
</script>
<br/>
<br>
<h3 id="problem-4-1-pt">Problem 4 (1 pt)</h3>
<p>Add functions <code>perfect_square</code> and <code>next_perfect_square</code> so that
<code>square_update</code> returns a player's total score after they roll <code>num_rolls</code>. You
do not need to edit the body of <code>square_update</code>.</p>
<ul>
<li><strong>Square Swine</strong>. After a player gains points for their turn, if the
resulting score is a perfect square, then increase their score to the next
higher perfect square. A perfect square is any integer <code>n</code> where <code>n = d * d</code> for some integer <code>d</code>.</li>
</ul>
<button id='toggle-7' class='btn btn-outline btn-lg alwaystoggle toggle'>
Examples<noscript> (enable JavaScript)</noscript>
</button>
<div class="solution toggle-7">
<ul>
<li><p><em>Example 1:</em></p>
<ul>
<li>A player has 12 points and rolls 3 dice that total 13 points. Their
new score would be 25, but since 25 is 5 squared, their score is
increased to 6 squared: 36.</li>
</ul></li>
<li><p><em>Example 2:</em></p>
<ul>
<li>A player has 12 points and rolls 3 dice that total 12 point. Their new
score would be 24, which is not a perfect square.</li>
</ul></li>
<li><p><em>Example 3:</em></p>
<ul>
<li>A player has 0 points and rolls 5 dice, but one is a 1, so their new
score would be 1. 1 is a perfect square, and so their score is
increased to 4.</li>
</ul></li>
<li><p><em>Example 4:</em></p>
<ul>
<li>A player has 80 points and rolls 10 dice, but three are 1's, so their
new score would be 1. 81 is 9 squared, so their new score is 10
squared: 100. They win the game.</li>
</ul></li>
</ul>
</div>
<p>Before writing any code, unlock the tests to verify your understanding of the question:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 04 -u<button id="copy-code-python3ok-q04-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q04-u").onclick = () => copyCode('python3 ok -q 04 -u', "copy-code-python3ok-q04-u");
</script>
<br/> <p>Once you are done unlocking, begin implementing your solution. You can check your correctness with:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 04<button id="copy-code-python3ok-q04" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q04").onclick = () => copyCode('python3 ok -q 04', "copy-code-python3ok-q04");
</script>
<br/>
<h3 id="problem-5-5-pt">Problem 5 (5 pt)</h3>
<p>Implement the <code>play</code> function, which simulates a full game of Hog. Players take
turns rolling dice until one of the players reaches the <code>goal</code> score, and the
final scores of both players are returned by the function.</p>
<p>To determine how many dice are rolled each turn, call the current player's
strategy function (Player 0 uses <code>strategy0</code> and Player 1 uses <code>strategy1</code>). A
<em>strategy</em> is a function that, given a player's score and their opponent's
score, returns the number of dice that the current player will roll in the
turn. An example strategy is <code>always_roll_5</code> which appears above <code>play</code>.</p>
<p>To determine the updated score for a player after they take a turn, call the
<code>update</code> function. An <code>update</code> function takes the number
of dice to roll, the current player's score, the opponent's score, and the
dice function used to simulate rolling dice. It returns the updated score
of the current player after they take their turn. Two examples of <code>update</code> functions
are <code>simple_update</code> and<code>square_update</code>.</p>
<p>If a player achieves the goal score by the end of their turn, i.e. after all
applicable rules have been applied, the game ends. <code>play</code> will then return the
final total scores of both players, with Player 0's score first and Player 1's
score second.</p>
<p>Some example calls to <code>play</code> are:</p>
<ul>
<li><code>play(always_roll_5, always_roll_5, simple_update)</code> simulates two players
that both always roll 5 dice each turn, playing with just the Sow Sad and Pig
Tail rules.</li>
<li><code>play(always_roll_5, always_roll_5, square_update)</code> simulates two players
that both always roll 5 dice each turn, playing with the Square Swine rule in
addition to the Sow Sad and Pig Tail rules (i.e. all the rules).</li>
</ul>
<blockquote><p><strong>Important:</strong> For the user interface to work, a strategy function should be
called only once per turn. Only call <code>strategy0</code> when it is Player 0's turn
and only call <code>strategy1</code> when it is Player 1's turn.</p>
<p><strong>Hints</strong>:</p>
<ul>
<li>If <code>who</code> is the current player, the next player is <code>1 - who</code>.</li>
<li>To call <code>play(always_roll_5, always_roll_5, square_update)</code> and print out
what happens each turn, run <code>python3 hog_ui.py</code> from the terminal.</li>
</ul></blockquote>
<p>Before writing any code, unlock the tests to verify your understanding of the question:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 05 -u<button id="copy-code-python3ok-q05-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q05-u").onclick = () => copyCode('python3 ok -q 05 -u', "copy-code-python3ok-q05-u");
</script>
<br/> <p>Once you are done unlocking, begin implementing your solution. You can check your correctness with:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 05<button id="copy-code-python3ok-q05" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q05").onclick = () => copyCode('python3 ok -q 05', "copy-code-python3ok-q05");
</script>
<br/>
<p>Check to make sure that you completed all the problems in Phase 1:</p>
<pre><code>python3 ok --score</code></pre>
<p>Then, submit your work before the checkpoint deadline:</p>
<pre><code>python3 ok --submit</code></pre>
<p>When you run these <code>ok</code> commands, you'll still see that some tests are locked
because you haven't completed the whole project yet. You'll get full credit for
the checkpoint if you complete all the problems up to this point.</p>
<p><strong>Congratulations! You have finished Phase 1 of this project!</strong></p>
<br>
<h2 id="interlude-user-interfaces">Interlude: User Interfaces</h2>
<blockquote><p>There are no required problems in this section of the project, just some
examples for you to read and understand. See Phase 2 for the remaining
project problems.</p></blockquote>
<h3 id="printing-game-events">Printing Game Events</h3>
<p>We have built a simulator for the game, but haven't added any code to describe
how the game events should be displayed to a person. Therefore, we've built a
computer game that no one can play. (Lame!)</p>
<p>However, the simulator is expressed in terms of small functions, and we can
replace each function by a version that prints out what happens when it is
called. Using higher-order functions, we can do so without changing much of our
original code. An example appears in <code>hog_ui.py</code>, which you are encouraged to
read.</p>
<p>The <code>play_and_print</code> function calls the same <code>play</code> function just implemented,
but using:</p>
<ul>
<li>new strategy functions (e.g., <code>printing_strategy(0, always_roll_5)</code>) that
print out the scores and number of dice rolled.</li>
<li>a new update function (<code>square_update_and_print</code>) that prints the outcome of
each turn.</li>
<li>a new dice function (<code>printing_dice(six_sided)</code>) that prints the outcome of
rolling the dice.</li>
</ul>
<p>Notice how much of the original simulator code can be reused.</p>
<p>Running <code>python3 hog_ui.py</code> from the terminal calls
<code>play_and_print(always_roll_5, always_roll_5)</code>.</p>
<h3 id="accepting-user-input">Accepting User Input</h3>
<p>The built-in <code>input</code> function waits for the user to type a line of text and
then returns that text as a string. The built-in <code>int</code> function can take a
string containing the digits of an integer and return that integer.</p>
<p>The <code>interactive_strategy</code> function returns a strategy that let's a person
choose how many dice to roll each turn by calling <code>input</code>.</p>
<p>With this strategy, we can finally play a game using our <code>play</code> function:</p>
<p>Running <code>python3 hog_ui.py -n 1</code> from the terminal calls
<code>play_and_print(interactive_strategy(0), always_roll_5)</code>, which plays a game
betweem a human (Player 0) and a computer strategy that always rolls 5.</p>
<p>Running <code>python3 hog_ui.py -n 2</code> from the terminal calls
<code>play_and_print(interactive_strategy(0), interactive_strategy(1))</code>, which plays
a game between two human players.</p>
<p>You are welcome to change <code>hog_ui.py</code> in any way you want, for example to use
different strategies than <code>always_roll_5</code>.</p>
<br>
<h2 id="phase-2-strategies">Phase 2: Strategies</h2>
<p>In this phase, you will experiment with ways to improve upon the basic
strategy of always rolling five dice. A <em>strategy</em> is a function that
takes two arguments: the current player's score and their opponent's score. It
returns the number of dice the player will roll, which can be from 0 to 10
(inclusive).</p>
<h3 id="problem-6-2-pt">Problem 6 (2 pt)</h3>
<p>Implement <code>always_roll</code>, a higher-order function that takes a number of dice
<code>n</code> and returns a strategy that always rolls <code>n</code> dice. Thus, <code>always_roll(5)</code>
would be equivalent to <code>always_roll_5</code>.</p>
<p>Before writing any code, unlock the tests to verify your understanding of the question:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 06 -u<button id="copy-code-python3ok-q06-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q06-u").onclick = () => copyCode('python3 ok -q 06 -u', "copy-code-python3ok-q06-u");
</script>
<br/>
<p>Once you are done unlocking, begin implementing your solution. You can check your correctness with:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 06<button id="copy-code-python3ok-q06" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q06").onclick = () => copyCode('python3 ok -q 06', "copy-code-python3ok-q06");
</script>
<br/>
<h3 id="problem-7-2-pt">Problem 7 (2 pt)</h3>
<p>A strategy only has a fixed number of possible argument values. In a game to
100, there are 100 possible <code>score</code> values (0-99) and 100 possible
<code>opponent_score</code> values (0-99), giving 10,000 possible argument combinations.</p>
<p>Implement <code>is_always_roll</code>, which takes a strategy and returns whether that
strategy always rolls the same number of dice for every possible argument
combination.</p>
<p>Before writing any code, unlock the tests to verify your understanding of the question:</p><pre style="margin-bottom:0;"><code class="nohighlight">python3 ok -q 07 -u<button id="copy-code-python3ok-q07-u" class="inline-copy-button"><div class="copy-tooltip"><span>Copy</span></div>✂️</a></code></pre>
<script>
document.getElementById("copy-code-python3ok-q07-u").onclick = () => copyCode('python3 ok -q 07 -u', "copy-code-python3ok-q07-u");
</script>
<br/>