| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,3 +6,6 @@ clean: | |||
| 6 | 6 | ||
| 7 | 7 | book: | |
| 8 | 8 | ./bin/compile.py | |
| 9 | + | ||
| 10 | + toc: | ||
| 11 | + perl -ne '/^[#]{1,3}\s+(?!-)/ && print' book.md > toc.txt | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,42 +1,43 @@ | |||
| 1 | 1 | ## 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. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,8 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | 7 | 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. | |
| 8 | 8 | ||
| 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 | - | ||
| 11 | 9 | When you are done with this books you be able to: | |
| 12 | 10 | ||
| 13 | 11 | * Write command-line Python programs | |
@@ -20,6 +18,8 @@ When you are done with this books you be able to: | |||
| 20 | 18 | * Use and control of randomness | |
| 21 | 19 | * Create and use graphs, kmers, Markov chains, Hamming distance, the Soundex algorithm, and more | |
| 22 | 20 | ||
| 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 | + | ||
| 23 | 23 | ## Forking GitHub repo | |
| 24 | 24 | ||
| 25 | 25 | 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 | |||
| 31 | 31 | 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!). | |
| 32 | 32 | ||
| 33 | 33 | ||
| 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 | - | ||
| 69 | 34 | ## Why Not Notebooks? | |
| 70 | 35 | ||
| 71 | 36 | Notebooks are great for interactive exploration of data, especially if you want to visualize thing, but the downsides: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,3 +1,4 @@ | |||
| 1 | + getting_started | ||
| 1 | 2 | article | |
| 2 | 3 | jump_the_five | |
| 3 | 4 | picnic | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -136,16 +136,15 @@ def main(): | |||
| 136 | 136 | fh.write(text + '\n\\newpage\n\n') | |
| 137 | 137 | ||
| 138 | 138 | 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') | ||
| 149 | 148 | ||
| 150 | 149 | discussion = os.path.join(in_dir, dir_name, 'discussion.md') | |
| 151 | 150 | if os.path.isfile(discussion): | |
@@ -154,16 +153,16 @@ def main(): | |||
| 154 | 153 | fh.write(open(discussion).read()) | |
| 155 | 154 | fh.write('\n\\newpage\n\n') | |
| 156 | 155 | ||
| 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') | ||
| 167 | 166 | ||
| 168 | 167 | cmd = 'pandoc {} --pdf-engine=xelatex -o {}' | |
| 169 | 168 | rv, out = getstatusoutput(cmd.format(book_file, args.outfile)) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments