Skip to content

Commit b1abe29

Browse files
committed
updated
1 parent 061c602 commit b1abe29

File tree

3 files changed

+181
-6
lines changed

3 files changed

+181
-6
lines changed

bin/chapters.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ twelve_days_of_christmas
3030
war
3131
anagram
3232
hangman
33+
first_bank_of_change
3334
markov_chain
3435
hamming_chain
3536
morse

book.md

Lines changed: 180 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4572,7 +4572,148 @@ You lose, loser! The word was "metromania."
45724572

45734573
\newpage
45744574

4575-
# Chapter 33: Markov Chain
4575+
# Chapter 33: First Bank of Change
4576+
4577+
Write a Python program called `fboc.py` that will figure out all the different combinations of pennies, nickels, dimes, and quarters in a given `value` provided as a single positional argument. The value must be greater than 0 and less than or equal to 100.
4578+
4579+
````
4580+
$ ./fboc.py
4581+
usage: fboc.py [-h] int
4582+
fboc.py: error: the following arguments are required: int
4583+
$ ./fboc.py -h
4584+
usage: fboc.py [-h] int
4585+
4586+
First Bank of Change
4587+
4588+
positional arguments:
4589+
int Sum
4590+
4591+
optional arguments:
4592+
-h, --help show this help message and exit
4593+
$ ./fboc.py 0
4594+
usage: fboc.py [-h] int
4595+
fboc.py: error: value "0" must be > 0 and <= 100
4596+
$ ./fboc.py 124
4597+
usage: fboc.py [-h] int
4598+
fboc.py: error: value "124" must be > 0 and <= 100
4599+
$ ./fboc.py 1
4600+
If you give me 1 cent, I can give you:
4601+
1: 1 penny
4602+
$ ./fboc.py 4
4603+
If you give me 4 cents, I can give you:
4604+
1: 4 pennies
4605+
$ ./fboc.py 6
4606+
If you give me 6 cents, I can give you:
4607+
1: 6 pennies
4608+
2: 1 nickel, 1 penny
4609+
$ ./fboc.py 13
4610+
If you give me 13 cents, I can give you:
4611+
1: 13 pennies
4612+
2: 1 dime, 3 pennies
4613+
3: 1 nickel, 8 pennies
4614+
4: 2 nickels, 3 pennies
4615+
$ ./fboc.py 27
4616+
If you give me 27 cents, I can give you:
4617+
1: 27 pennies
4618+
2: 1 quarter, 2 pennies
4619+
3: 1 dime, 17 pennies
4620+
4: 2 dimes, 7 pennies
4621+
5: 1 nickel, 22 pennies
4622+
6: 1 dime, 1 nickel, 12 pennies
4623+
7: 2 dimes, 1 nickel, 2 pennies
4624+
8: 2 nickels, 17 pennies
4625+
9: 1 dime, 2 nickels, 7 pennies
4626+
10: 3 nickels, 12 pennies
4627+
11: 1 dime, 3 nickels, 2 pennies
4628+
12: 4 nickels, 7 pennies
4629+
13: 5 nickels, 2 pennies
4630+
````
4631+
4632+
\newpage
4633+
4634+
## Solution
4635+
4636+
````
4637+
1 #!/usr/bin/env python3
4638+
2 """Coin combos for value"""
4639+
3
4640+
4 import argparse
4641+
5 from itertools import product
4642+
6 from functools import partial
4643+
7
4644+
8
4645+
9 # --------------------------------------------------
4646+
10 def get_args():
4647+
11 """Get command-line arguments"""
4648+
12
4649+
13 parser = argparse.ArgumentParser(
4650+
14 description='First Bank of Change',
4651+
15 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
4652+
16
4653+
17 parser.add_argument('value', metavar='int', type=int, help='Sum')
4654+
18
4655+
19 args = parser.parse_args()
4656+
20
4657+
21 if not 0 < args.value <= 100:
4658+
22 parser.error('value "{}" must be > 0 and <= 100'.format(args.value))
4659+
23
4660+
24 return args
4661+
25
4662+
26
4663+
27 # --------------------------------------------------
4664+
28 def main():
4665+
29 """Make a jazz noise here"""
4666+
30
4667+
31 args = get_args()
4668+
32 value = args.value
4669+
33 nickels = range((value // 5) + 1)
4670+
34 dimes = range((value // 10) + 1)
4671+
35 quarters = range((value // 25) + 1)
4672+
36 fig = partial(figure, value)
4673+
37 combos = [c for c in map(fig, product(nickels, dimes, quarters)) if c]
4674+
38
4675+
39 print('If you give me {} cent{}, I can give you:'.format(
4676+
40 value, '' if value == 1 else 's'))
4677+
41
4678+
42 for i, combo in enumerate(combos, 1):
4679+
43 print('{:3}: {}'.format(i, fmt_combo(combo)))
4680+
44
4681+
45
4682+
46 # --------------------------------------------------
4683+
47 def fmt_combo(combo):
4684+
48 """English version of combo"""
4685+
49
4686+
50 out = []
4687+
51 for coin, val in zip(('quarter', 'dime', 'nickel', 'penny'), combo):
4688+
52 if val:
4689+
53 plural = 'pennies' if coin == 'penny' else coin + 's'
4690+
54 out.append('{} {}'.format(val, coin if val == 1 else plural))
4691+
55
4692+
56 return ', '.join(out)
4693+
57
4694+
58
4695+
59 # --------------------------------------------------
4696+
60 def figure(value, coins):
4697+
61 """
4698+
62 If there is a valid combo of 'coins' in 'value',
4699+
63 return a tuple of ints for (quarters, dimes, nickels, pennies)
4700+
64 """
4701+
65
4702+
66 nickels, dimes, quarters = coins
4703+
67 big_coins = (5 * nickels) + (10 * dimes) + (25 * quarters)
4704+
68
4705+
69 if big_coins <= value:
4706+
70 return (quarters, dimes, nickels, value - big_coins)
4707+
71
4708+
72
4709+
73 # --------------------------------------------------
4710+
74 if __name__ == '__main__':
4711+
75 main()
4712+
````
4713+
4714+
\newpage
4715+
4716+
# Chapter 34: Markov Chain
45764717

45774718
Write a Python program called `markov.py` that takes one or more text files as positional arguments for training. Use the `-n|--num_words` argument (default `2`) to find clusters of words and the words that follow them, e.g., in "The Bustle" by Emily Dickinson:
45784719

@@ -4779,7 +4920,7 @@ Advice and Consent of the United States.
47794920

47804921
\newpage
47814922

4782-
# Chapter 34: Hamming Chain
4923+
# Chapter 35: Hamming Chain
47834924

47844925
Write a Python program called `chain.py` that takes a `-s|--start` word and searches a `-w|--wordlist` argument (default `/usr/local/share/dict`) for words no more than `-d|--max_distance` Hamming distance for some number of `-i|--iteration` (default `20`). Be sure to accept a `-S|--seed` for `random.seed`.
47854926

@@ -4982,7 +5123,7 @@ Failed to find more words!
49825123

49835124
\newpage
49845125

4985-
# Chapter 35: Morse Encoder/Decoder
5126+
# Chapter 36: Morse Encoder/Decoder
49865127

49875128
Write a Python program called `morse.py` that will encrypt/decrypt text to/from Morse code. The program should expect a single positional argument which is either the name of a file to read for the input or the character `-` to indicate reading from STDIN. The program should also take a `-c|--coding` option to indicate use of the `itu` or standard `morse` tables, `-o|--outfile` for writing the output (default STDOUT), and a `-d|--decode` flag to indicate that the action is to decode the input (the default is to encode it).
49885129

@@ -5200,7 +5341,7 @@ THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
52005341

52015342
\newpage
52025343

5203-
# Chapter 36: ROT13 (Rotate 13)
5344+
# Chapter 37: ROT13 (Rotate 13)
52045345

52055346
Write a Python program called `rot13.py` that will encrypt/decrypt input text by shifting the text by a given `-s|--shift` argument or will move each character halfway through the alphabet, e.g., "a" becomes "n," "b" becomes "o," etc. The text to rotate should be provided as a single positional argument to your program and can either be a text file, text on the command line, or `-` to indicate STDIN so that you can round-trip data through your program to ensure you are encrypting and decrypting properly.
52065347

@@ -5365,7 +5506,7 @@ The quick brown fox jumps over the lazy dog.
53655506

53665507
\newpage
53675508

5368-
# Chapter 37: Tranpose ABC Notation
5509+
# Chapter 38: Tranpose ABC Notation
53695510

53705511
Write a Python program called `transpose.py` that will read a file in ABC notation (https://en.wikipedia.org/wiki/ABC_notation) and transpose the melody line up or down by a given `-s|--shift` argument. Like the `rot13` exercise, it might be helpful to think of the space of notes (`ABCDEFG`) as a list which you can roll through. For instance, if you have the note `c` and want to transpose up a (minor) third (`-s 3`), you would make the new note `e`; similarly if you have the note `F` and you go up a (major) third, you get `A`. You will not need to worry about the actual number of semitones that you are being asked to shift, as the previous example showed that we might be shifting by a major/minor/augmented/diminished/pure interval. The purpose of the exercise is simply to practice with lists.
53715512

@@ -5561,7 +5702,7 @@ aba agE | g2g gab | cba agE |1 gED DEg :|2 gED DBG |]
55615702

55625703
\newpage
55635704

5564-
# Chapter 38: Word Search
5705+
# Chapter 39: Word Search
55655706

55665707
Write a Python program called `search.py` that takes a file name as the single positional argument and finds the words hidden in the puzzle grid.
55675708

@@ -6190,6 +6331,39 @@ number = 2
61906331
files = foo, bar
61916332
````
61926333

6334+
## Choices
6335+
6336+
Sometimes you want to limit the values of an argument. You can pass in a `list` of valid values to the `choices` option.
6337+
6338+
````
6339+
$ cat appendix/argparse/choices.py
6340+
#!/usr/bin/env python3
6341+
"""Choices"""
6342+
6343+
import argparse
6344+
6345+
parser = argparse.ArgumentParser(
6346+
description='Choices',
6347+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
6348+
6349+
parser.add_argument('color', metavar='str', help='Color', choices=['red', 'yellow', 'blue'])
6350+
6351+
args = parser.parse_args()
6352+
6353+
print('color =', args.color)
6354+
````
6355+
6356+
Any value not present in the list will be rejected and the user will be shown the valid choices:
6357+
6358+
````
6359+
$ ./choices.py
6360+
usage: choices.py [-h] str
6361+
choices.py: error: the following arguments are required: str
6362+
$ ./choices.py purple
6363+
usage: choices.py [-h] str
6364+
choices.py: error: argument str: invalid choice: 'purple' (choose from 'red', 'yellow', 'blue')
6365+
````
6366+
61936367
## Automatic help
61946368

61956369
The `argparse` module reserves the `-h` and `--help` flags for generating help documentation. You do not need to add these nor are you allowed to use these flags for other purposes. Using the above definition, this is the help that `argparse` will generate:

playful_python.pdf

5.41 KB
Binary file not shown.

0 commit comments

Comments
 (0)