Skip to content

Commit 0cf871d

Browse files
committed
getting started
1 parent 7861589 commit 0cf871d

File tree

17 files changed

+10468
-9402
lines changed

17 files changed

+10468
-9402
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ clean:
66

77
book:
88
./bin/compile.py
9+
10+
toc:
11+
perl -ne '/^[#]{1,3}\s+(?!-)/ && print' book.md > toc.txt

OUTLINE.md

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,43 @@
11
## Outline
2-
1. **article**: Choose the correct article for a given word.
3-
2. **jump_the_five**: Encode all numbers in a given text using a Jump-The-Five algorithm.
4-
3. **picnic**: Manipulate strings and lists based on the number of items present.
5-
4. **wc**: Write a program to count the lines, words, and characters in text.
6-
5. **howler**: Convert all input text to uppercase.
7-
6. **apples_and_bananas**: Substitute vowels in text.
8-
7. **telephone**: Introduce mutations in a string over a given number of iterations.
9-
8. **bottles_of_beer**: Write the "99 Bottles of Beer On The Wall" song.
10-
9. **gashlycrumb**: Retreive a line of text from a file by the first letter.
11-
10. **ransom_note**: Randomly alternate the case of input text to simulate a ransom note.
12-
11. **rhymer**: Substitute alternate consonant prefixes onto a stem to find rhyming "words."
13-
12. **rock_paper_scissors**: Write the "Rock, Paper, Scissors" game.
14-
13. **abuse**: Creating insults by randomly choosing from lists of words.
15-
14. **scrambler**: Randomly shuffle the middle letters of every word in a text leaving the first and last letters in place.
16-
15. **bacronym**: Use dictionaries to organize words by first letter, then randomly choose words to create "meanings" for a given acronym.
17-
16. **wod**: Generate a Workout-Of-the-Day (WOD) from a list of possible exercises.
18-
17. **blackjack**: An abbreviated version of the card game "Blackjack" (AKA "Twenty-One").
19-
18. **family_tree**: Parse a text file containing the description of family trees, visualize the resulting graphs using GraphViz.
20-
19. **gematria**: Numerically encode each word of text by summing the ordinal values of the characters.
21-
20. **histy**: Create a textual histogram showing the frequency of letters in text.
22-
21. **mommys_little_helper**: Find words matching a given pattern to help solve a crossword puzzle. Explores manually finding words and using regular expressions.
23-
22. **kentucky_friar**: Drop the "g" from two-syllable words ending in "-ing"; convert "you" to "y'all."
24-
23. **mad_libs**: Create an interative terminal version of "Mad Libs." Hilarity is sure to ensue.
25-
24. **license_plates**: Find all possible permutations of a licence plate given a confusion matrix. Explore how and verify that regular expressions work.
26-
25. **gibberish**: Use a Markov chain to create new words from a set of training files.
27-
26. **piggy**: Encode text using the Pig Latin algorithm.
28-
27. **soundex_rhymer**: Using the Soundex function to find words ending with a given sound.
29-
28. **tictactoe**: Play a round of Tic-Tac-Toe.
30-
29. **twelve_days_of_christmas**: Write a program that will print the "Twelve Days of Christmas" song up to a given day.
31-
30. **anagram**: Finding anagrams of words.
32-
31. **hangman**: Write an interactive terminal game where the user guesses a word.
33-
32. **first_bank_of_change**: Find all possible combinations of pennies, nickels, dimes, and quarters for an amount between 1 and 100.
34-
33. **pareto**: Model how random events of zero-sum encounters led to inequitable distributions.
35-
34. **runny_babbit**: Introduce Spoonerisms into text by switching the initial consonant sounds of neighboring words.
36-
35. **markov_chain**: Use the Markov chain algorithm to generate novel texts based on training sets.
37-
36. **hamming_chain**: Find paths through words that are separated by a given Hamming distance.
38-
37. **morse**: Encrypt and decrypt text to and from two versions of Morse code.
39-
38. **rot13**: Encode and decode text by rotating the characters through a list.
40-
39. **word_search**: Find all the words hidden in the rows, columns, and diagonals in a block of text.
41-
40. **set**: Find "set" of cards from a deck of 81 where each of 4 attributes can have each of 3 values and a "set" of 3 cards is either the same or entirely different for each of the 4 attributes.
42-
41. **scrabble**: Find all possible words you could make from a random set of seven characters.
2+
1. **getting_started**: Introduction to Python language basics, the `argparse` module, and the `new.py` program for creating new programs using `argparse`.
3+
2. **article**: Choose the correct article for a given word.
4+
3. **jump_the_five**: Encode all numbers in a given text using a Jump-The-Five algorithm.
5+
4. **picnic**: Manipulate strings and lists based on the number of items present.
6+
5. **wc**: Write a program to count the lines, words, and characters in text.
7+
6. **howler**: Convert all input text to uppercase.
8+
7. **apples_and_bananas**: Substitute vowels in text.
9+
8. **telephone**: Introduce mutations in a string over a given number of iterations.
10+
9. **bottles_of_beer**: Write the "99 Bottles of Beer On The Wall" song.
11+
10. **gashlycrumb**: Retreive a line of text from a file by the first letter.
12+
11. **ransom_note**: Randomly alternate the case of input text to simulate a ransom note.
13+
12. **rhymer**: Substitute alternate consonant prefixes onto a stem to find rhyming "words."
14+
13. **rock_paper_scissors**: Write the "Rock, Paper, Scissors" game.
15+
14. **abuse**: Creating insults by randomly choosing from lists of words.
16+
15. **scrambler**: Randomly shuffle the middle letters of every word in a text leaving the first and last letters in place.
17+
16. **bacronym**: Use dictionaries to organize words by first letter, then randomly choose words to create "meanings" for a given acronym.
18+
17. **wod**: Generate a Workout-Of-the-Day (WOD) from a list of possible exercises.
19+
18. **blackjack**: An abbreviated version of the card game "Blackjack" (AKA "Twenty-One").
20+
19. **family_tree**: Parse a text file containing the description of family trees, visualize the resulting graphs using GraphViz.
21+
20. **gematria**: Numerically encode each word of text by summing the ordinal values of the characters.
22+
21. **histy**: Create a textual histogram showing the frequency of letters in text.
23+
22. **mommys_little_helper**: Find words matching a given pattern to help solve a crossword puzzle. Explores manually finding words and using regular expressions.
24+
23. **kentucky_friar**: Drop the "g" from two-syllable words ending in "-ing"; convert "you" to "y'all."
25+
24. **mad_libs**: Create an interative terminal version of "Mad Libs." Hilarity is sure to ensue.
26+
25. **license_plates**: Find all possible permutations of a licence plate given a confusion matrix. Explore how and verify that regular expressions work.
27+
26. **gibberish**: Use a Markov chain to create new words from a set of training files.
28+
27. **piggy**: Encode text using the Pig Latin algorithm.
29+
28. **soundex_rhymer**: Using the Soundex function to find words ending with a given sound.
30+
29. **tictactoe**: Play a round of Tic-Tac-Toe.
31+
30. **twelve_days_of_christmas**: Write a program that will print the "Twelve Days of Christmas" song up to a given day.
32+
31. **anagram**: Finding anagrams of words.
33+
32. **hangman**: Write an interactive terminal game where the user guesses a word.
34+
33. **first_bank_of_change**: Find all possible combinations of pennies, nickels, dimes, and quarters for an amount between 1 and 100.
35+
34. **pareto**: Model how random events of zero-sum encounters led to inequitable distributions.
36+
35. **runny_babbit**: Introduce Spoonerisms into text by switching the initial consonant sounds of neighboring words.
37+
36. **markov_chain**: Use the Markov chain algorithm to generate novel texts based on training sets.
38+
37. **hamming_chain**: Find paths through words that are separated by a given Hamming distance.
39+
38. **morse**: Encrypt and decrypt text to and from two versions of Morse code.
40+
39. **rot13**: Encode and decode text by rotating the characters through a list.
41+
40. **word_search**: Find all the words hidden in the rows, columns, and diagonals in a block of text.
42+
41. **set**: Find "set" of cards from a deck of 81 where each of 4 attributes can have each of 3 values and a "set" of 3 cards is either the same or entirely different for each of the 4 attributes.
43+
42. **scrabble**: Find all possible words you could make from a random set of seven characters.

README.md

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
77
I believe you can learn serious things through silly games. I also think you will learn best by *doing*. This is a book of programming exercises. Each chapter includes a description of a program you should write with examples of how the program should work. Most importantly, each program includes tests so that you know if your program is working well enough.
88

9-
I won't necessarily show you beforehand how to write each program. I'll describe what the program should do and provide some discussion about how to write it. I'll also create an appendix with short examples of how to do things like how to use `argparse`, how to read/write from/to a file, how to process all the files in a directory, how to extract k-mers from a string, etc. I'll provide some building blocks, but I want you to figure out how to put the pieces together.
10-
119
When you are done with this books you be able to:
1210

1311
* Write command-line Python programs
@@ -20,6 +18,8 @@ When you are done with this books you be able to:
2018
* Use and control of randomness
2119
* Create and use graphs, kmers, Markov chains, Hamming distance, the Soundex algorithm, and more
2220

21+
The first chapter will briefly introduce some aspects of the Python language, but I will assume some basic profiency with Python or some similar language. If you are coming from any other c-based language (even if it uses braces for blocks), I don't think you'll have any problem picking up Python.
22+
2323
## Forking GitHub repo
2424

2525
First use the GitHub interface to "fork" this repository into your own account. Then do `git clone` of *your* repository to get a local copy. Inside that checkout, do:
@@ -31,41 +31,6 @@ git remote add upstream https://github.com/kyclark/playful_python.git
3131
This will allow you to `git pull upstream master` in order to get updates. When you create new files, `git add/commit/push` them to *your* repository. (Please do not create pull requests on *my* repository -- unless, of course, you have suggestions for improving my repo!).
3232

3333

34-
## new.py
35-
36-
I provide some useful programs in the `bin` directory including one called `new.py` that will help you stub out new Python programs using the `argparse` module to parse the command line arguments and options for your programs. I recommend you start every new program with this program. For example, in the `article` directory the `README.md` wants you to create a program called `article.py`. You should do this:
37-
38-
````
39-
$ cd article
40-
$ new.py article
41-
````
42-
43-
This will create a new file called `article.py` (that has been made executable with `chmod +x`, if your operating system supports that) that has example code for you to start writing your program.
44-
45-
## $PATH
46-
47-
Your `$PATH` is a list of directories where your operating system will look for programs. To see what your `$PATH` looks like, do:
48-
49-
````
50-
$ echo $PATH
51-
````
52-
53-
Probably each directory is separated by a colon (`:`). *The order of the directories matters!* For instance, it's common to have more than one version of Python installed. When you type `python` on the command line, the directories in your `$PATH` are searched in order, and the first `python` found is the one that is used (and it's probably Python version 2!)
54-
55-
You could execute `new.py` by giving the full path to the program, e.g., `$HOME/work/playful_python/bin/new.py`, but that's really tedious. It's best to put `new.py` into one of the directories that is already in your `$PATH` like maybe `/usr/local/bin`. The problem is that you probably need administrator privileges to write to most of the directories that are in your `$PATH`. If you are working on your laptop, this is probably not a problem, but if you are on a shared system, you probably won't be able to copy the program into your `$PATH` directories.
56-
57-
An alternative is to alter your `$PATH` to include the directory where `new.py` is located. E.g., if `new.py` is in `$HOME/work/playful_python/bin/`, then add this directory to your `$PATH` -- probably by editing `.bashrc` or `.bash_profile` located in your `$HOME` directory (if you use `bash`). See the documentation for your shell of choice to understand how to edit and persist your `$PATH`.
58-
59-
For what it's worth, I always create a `$HOME/.local` directory for local installations of software I need, so I add `$HOME/.local/bin` to my `$PATH`. Then I copy programs like `new.py` there and they are available to me anywhere on the system.
60-
61-
## Testing your programs
62-
63-
Once you have stubbed out your new program, open it in your favorite editor and change the example arguments in `get_args` to suit the needs of your app, then add your code to `main` to accomplish the task described in the README. To run the test suite using `make`, you can type `make test` in the same directory as the `test.py` and `article.py` program. If your system does not have `make` or you just don't want to use it, type `pytest -v test.py`.
64-
65-
Your goal is to pass all the tests. The tests are written in an order designed to guide you in how break the problem down, e.g., often a test will ask you to alter one bit of text from the command line, and this it will ask you to read and alter the text from a file. I would suggest you solve the tests in order. The `make test` target in every Makefile executes `pytest -xv test.py` where the `-x` flag will have `pytest` halt testing after it finds one that fails. There's no point in running every test when one fails, so I think this is less frustrating that seeing perhaps hundreds of lines of failing tests shoot by.
66-
67-
A fair number of the program rely on a dictionary of English words. To be sure that you can reproduce my results, I include a copy of mine in `inputs/words.zip`.
68-
6934
## Why Not Notebooks?
7035

7136
Notebooks are great for interactive exploration of data, especially if you want to visualize thing, but the downsides:

bin/chapters.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
getting_started
12
article
23
jump_the_five
34
picnic

bin/compile.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,15 @@ def main():
136136
fh.write(text + '\n\\newpage\n\n')
137137

138138
solution_py = os.path.join(in_dir, dir_name, 'solution.py')
139-
assert os.path.isfile(solution_py)
140-
141-
print('\tSOLUTION')
142-
fh.write('## Solution\n\n')
143-
fh.write('````\n')
144-
numbered = getoutput('cat -n {}'.format(solution_py))
145-
fh.write(numbered)
146-
#fh.write(open(solution_py).read())
147-
fh.write('\n````\n')
148-
fh.write('\n\\newpage\n\n')
139+
if os.path.isfile(solution_py):
140+
print('\tSOLUTION')
141+
fh.write('## Solution\n\n')
142+
fh.write('````\n')
143+
numbered = getoutput('cat -n {}'.format(solution_py))
144+
fh.write(numbered)
145+
#fh.write(open(solution_py).read())
146+
fh.write('\n````\n')
147+
fh.write('\n\\newpage\n\n')
149148

150149
discussion = os.path.join(in_dir, dir_name, 'discussion.md')
151150
if os.path.isfile(discussion):
@@ -154,16 +153,16 @@ def main():
154153
fh.write(open(discussion).read())
155154
fh.write('\n\\newpage\n\n')
156155

157-
if appendix:
158-
for i, dir_name in enumerate(map(str.rstrip, open(appendix)), 1):
159-
print('Appendix {}: {}'.format(i, dir_name))
160-
readme = os.path.join(in_dir, 'appendix', dir_name, 'README.md')
161-
if os.path.isfile(readme):
162-
print('\tREADME')
163-
header = 'Appendix {}: '.format(i)
164-
text = open(readme).read()
165-
text = re.sub(r'^#\s+', '# ' + header, text)
166-
fh.write(text + '\n\\newpage\n\n')
156+
# if appendix:
157+
# for i, dir_name in enumerate(map(str.rstrip, open(appendix)), 1):
158+
# print('Appendix {}: {}'.format(i, dir_name))
159+
# readme = os.path.join(in_dir, 'appendix', dir_name, 'README.md')
160+
# if os.path.isfile(readme):
161+
# print('\tREADME')
162+
# header = 'Appendix {}: '.format(i)
163+
# text = open(readme).read()
164+
# text = re.sub(r'^#\s+', '# ' + header, text)
165+
# fh.write(text + '\n\\newpage\n\n')
167166

168167
cmd = 'pandoc {} --pdf-engine=xelatex -o {}'
169168
rv, out = getstatusoutput(cmd.format(book_file, args.outfile))

0 commit comments

Comments
 (0)