├── .ex13_5.py.swp ├── .gitattributes ├── .gitignore ├── Card.py ├── Dairy.md ├── PrideandPrejudice.txt ├── README.md ├── TP reading notes.md ├── __pycache__ └── Card.cpython-35.pyc ├── c06d ├── captions ├── ch12_ex.py ├── ch15_ex.py ├── ch16_ex.py ├── ch16_ex.pyc ├── ch17_ex.py ├── ch4_ex.py ├── ch4_ex.pyc ├── ch8_ex.py ├── check └── checkwork.py ├── checksum.py ├── data.pkl ├── emma.txt ├── ex03_1.py ├── ex03_2.py ├── ex03_3.py ├── ex04_1.py ├── ex04_2.py ├── ex04_3.py ├── ex04_5.py ├── ex05_1.py ├── ex05_2.py ├── ex05_3.py ├── ex05_4.py ├── ex05_5.py ├── ex05_6.py ├── ex06_1.py ├── ex06_2.py ├── ex06_3.py ├── ex06_4.py ├── ex06_5.py ├── ex07_1.py ├── ex07_2.py ├── ex07_3.py ├── ex07_4.py ├── ex08_1.py ├── ex08_2.py ├── ex08_3.py ├── ex08_4.py ├── ex08_5.py ├── ex09_1.py ├── ex09_2.py ├── ex09_3.py ├── ex09_4.py ├── ex09_5.py ├── ex09_6.py ├── ex09_7.py ├── ex09_8.py ├── ex09_9.py ├── ex10_1.py ├── ex10_10.py ├── ex10_11.py ├── ex10_12.py ├── ex10_2.py ├── ex10_3.py ├── ex10_4.py ├── ex10_5.py ├── ex10_6.py ├── ex10_7.py ├── ex10_8.py ├── ex10_9.py ├── ex11_1.py ├── ex11_2.py ├── ex11_3.py ├── ex11_4.py ├── ex11_5.py ├── ex11_6.py ├── ex12_1.py ├── ex12_1_v2.py ├── ex12_2.py ├── ex12_2_v2.py ├── ex12_3.py ├── ex12_4.py ├── ex13_1.py ├── ex13_1_v2.py ├── ex13_2.py ├── ex13_3.py ├── ex13_4.py ├── ex13_5.py ├── ex13_6.py ├── ex13_7.py ├── ex13_8.py ├── ex13_9.py ├── ex14_1.py ├── ex14_2.py ├── ex14_3.py ├── ex15_1.py ├── ex15_1.pyc ├── ex15_2.py ├── ex16_1.py ├── ex16_2.py ├── ex17_1.py ├── ex17_2.py ├── ex18_1.py ├── ex18_2.py ├── ex18_3.py ├── ex19_1.py ├── ex21_1.py ├── ex21_2.py ├── inlist.py ├── inlist.pyc ├── letters.py ├── output.txt ├── polygon.py ├── polygon.pyc ├── pronounce.py ├── pronounce.pyc ├── rename.py ├── reverse_pair.py ├── shelf.pkl ├── test.py ├── test.txt ├── test_ex124.py ├── test_ex93.py ├── words.txt └── xmax.py /.ex13_5.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/.ex13_5.py.swp -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /Card.py: -------------------------------------------------------------------------------- 1 | """This module contains a code example related to 2 | 3 | Think Python, 2nd Edition 4 | by Allen Downey 5 | http://thinkpython2.com 6 | 7 | Copyright 2015 Allen Downey 8 | 9 | License: http://creativecommons.org/licenses/by/4.0/ 10 | """ 11 | 12 | from __future__ import print_function, division 13 | 14 | import random 15 | 16 | 17 | class Card: 18 | """Represents a standard playing card. 19 | 20 | Attributes: 21 | suit: integer 0-3 22 | rank: integer 1-13 23 | """ 24 | 25 | suit_names = ["Clubs", "Diamonds", "Hearts", "Spades"] 26 | rank_names = [None, "Ace", "2", "3", "4", "5", "6", "7", 27 | "8", "9", "10", "Jack", "Queen", "King"] 28 | 29 | def __init__(self, suit=0, rank=2): 30 | self.suit = suit 31 | self.rank = rank 32 | 33 | def __str__(self): 34 | """Returns a human-readable string representation.""" 35 | return '%s of %s' % (Card.rank_names[self.rank], 36 | Card.suit_names[self.suit]) 37 | 38 | def __eq__(self, other): 39 | """Checks whether self and other have the same rank and suit. 40 | 41 | returns: boolean 42 | """ 43 | return self.suit == other.suit and self.rank == other.rank 44 | 45 | def __lt__(self, other): 46 | """Compares this card to other, first by suit, then rank. 47 | 48 | returns: boolean 49 | """ 50 | t1 = self.suit, self.rank 51 | t2 = other.suit, other.rank 52 | return t1 < t2 53 | 54 | 55 | class Deck: 56 | """Represents a deck of cards. 57 | 58 | Attributes: 59 | cards: list of Card objects. 60 | """ 61 | 62 | def __init__(self): 63 | """Initializes the Deck with 52 cards. 64 | """ 65 | self.cards = [] 66 | for suit in range(4): 67 | for rank in range(1, 14): 68 | card = Card(suit, rank) 69 | self.cards.append(card) 70 | 71 | def __str__(self): 72 | """Returns a string representation of the deck. 73 | """ 74 | res = [] 75 | for card in self.cards: 76 | res.append(str(card)) 77 | return '\n'.join(res) 78 | 79 | def add_card(self, card): 80 | """Adds a card to the deck. 81 | 82 | card: Card 83 | """ 84 | self.cards.append(card) 85 | 86 | def remove_card(self, card): 87 | """Removes a card from the deck or raises exception if it is not there. 88 | 89 | card: Card 90 | """ 91 | self.cards.remove(card) 92 | 93 | def pop_card(self, i=-1): 94 | """Removes and returns a card from the deck. 95 | 96 | i: index of the card to pop; by default, pops the last card. 97 | """ 98 | return self.cards.pop(i) 99 | 100 | def shuffle(self): 101 | """Shuffles the cards in this deck.""" 102 | random.shuffle(self.cards) 103 | 104 | def sort(self): 105 | """Sorts the cards in ascending order.""" 106 | self.cards.sort() 107 | 108 | def move_cards(self, hand, num): 109 | """Moves the given number of cards from the deck into the Hand. 110 | 111 | hand: destination Hand object 112 | num: integer number of cards to move 113 | """ 114 | for i in range(num): 115 | hand.add_card(self.pop_card()) 116 | 117 | 118 | class Hand(Deck): 119 | """Represents a hand of playing cards.""" 120 | 121 | def __init__(self, label=''): 122 | self.cards = [] 123 | self.label = label 124 | 125 | 126 | def find_defining_class(obj, method_name): 127 | """Finds and returns the class object that will provide 128 | the definition of method_name (as a string) if it is 129 | invoked on obj. 130 | 131 | obj: any python object 132 | method_name: string method name 133 | """ 134 | for ty in type(obj).mro(): 135 | if method_name in ty.__dict__: 136 | return ty 137 | return None 138 | 139 | 140 | if __name__ == '__main__': 141 | deck = Deck() 142 | deck.shuffle() 143 | 144 | hand = Hand() 145 | print(find_defining_class(hand, 'shuffle')) 146 | 147 | deck.move_cards(hand, 5) 148 | hand.sort() 149 | print(hand) -------------------------------------------------------------------------------- /Dairy.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/Dairy.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # _Think Python_ solutions 2 | 3 | * Author: Dex D. Hunter 4 | 5 | * Copyright 2017 Dex D. Hunter 6 | 7 | * License: [![Foo](https://licensebuttons.net/l/by/3.0/88x31.png)](https://creativecommons.org/licenses/by/4.0/) 8 | 9 | Hi there! This is my approach to _think python_ written by Allen Downey. You can see his book [there](http://greenteapress.com/wp/think-python-2e/) and code [there](https://github.com/AllenDowney/ThinkPython) and I adapted his answers in some of solutions (see my code to find out where). To find a particular exercise, you can search through the index. Cheers! 10 | 11 | # Exercise Index (Bold for Important or Interesting Exercises) 12 | * 3-1 right_justify 13 | * 3-2 do_twice, do_four, print_twice, etc 14 | * 3-3 draw_4x4_grid 15 | * 4-1 stack diagram for circle(bob, radius) 16 | * __4-2 draw flower with turtleWorld__ 17 | * 4-3 draw pies 18 | * 4-4 draw letters 19 | * 4-5 draw spirals 20 | * 5-1 time convert 21 | * __5-2 implementation of Fermat's Last Theorem__ 22 | * 5-3 triangle check 23 | * 5-4 stack diagram on recursive function 24 | * 5-5 read koch recursive function 25 | * 5-6 draw Koch curve and snowflake 26 | * 6-1 stack diagram for calling functions 27 | * 6-2 Ackermann function with simple control flow 28 | * 6-3 palindrome check 29 | * 6-4 is_power check 30 | * __6-5 the great common divisor(GCD) calculator__ 31 | * 7-1 test square root with math module 32 | * 7-2 eval function in loop 33 | * 7-3 Srinivasa Ramanujan's estimation of pi 34 | * 8-1 experiments with string methods 35 | * 8-2 count 'a' in 'banana' 36 | * 8-3 one line is_palindrome 37 | * 8-4 explanation of 5 functions 38 | * 8-5 rotate by n characters 39 | * 9-1 read words.txt 40 | * 9-2 has_no_e 41 | * 9-3 avoids and forbidden letters 42 | * 9-4 uses_only 43 | * 9-5 uses_all(inverse of uses_only) 44 | * 9-6 is_abecedarian checks string's alphabetic order 45 | * 9-7 cartalk1: find consecutive double words 46 | * 9-8 cartalk2: find self-palindromic numbers 47 | * 9-9 cartalk3: find my and mom's age 48 | * 10-1 nested_sum 49 | * 10-2 cumsum (cumulative sum) 50 | * 10-3 middle, which takes a list without first and last element 51 | * 10-4 chop, same as middle but returns None 52 | * 10-5 is_sorted, check list in ascending order 53 | * 10-6 is_anagram 54 | * 10-7 has_duplicates 55 | * __10-8 Birthday_paradox__ 56 | * 10-9 two methods to add elements to list 57 | * __10-10 check whether a word is in the list with in operator and bisect__ 58 | * 10-11 reverse_pair 59 | * __10-12 interlock__ 60 | * 11-1 store words in words.txt as dictionary 61 | * 11-2 inverse_dict with setdefault method 62 | * 11-3 ackmann_memo 63 | * 11-4 dictionary version of has_duplicates 64 | * 11-5 dict version of rotate 65 | * __11-6 homophone (sound check)__ 66 | * 12-1 letter frequecy 67 | * __12-2 anagram search and sort__ 68 | * 12-3 metathesis pairs 69 | * 12-4 longest reducible words 70 | * 13-1 read a text file and breaks to words with stripped string.puncutation and string.whitespace 71 | * 13-2 read a text file from project Gutenberg and count number of words 72 | * 13-3 count 20 most frequently used word 73 | * 13-4 subtract_version_1 74 | * 13-5 choose_from_hist 75 | * 13-6 subtract_with_set 76 | * 13-7 choose_from_hist_version_2 77 | * __13-8 Markov analysis__ 78 | * __13-9 Zipf's law implementation__ 79 | * 14-1 a function reads a file and change the pattern string with replacement string and output the file 80 | * 14-2 store dictionary in a file and look up a dictionary from given file 81 | * 14-3 search a directory recursively and find out duplicates by md5sum check 82 | * 15-1 class and objects instantiation 83 | * 15-2 combine turtle and class, math proof for overlapping problem(back in 15-1) 84 | * 16-1 mul_time 85 | * 16-2 datetime, time, timedelta, etc manipulation 86 | * 17-1 rewrite time class in methods 87 | * 17-2 debug kangroo class (list initialization) 88 | * 18-1 UML diagram for PingPong 89 | * 18-2 deal_hand (Deck) 90 | * 18-3 add methods to PokerHand class `has_pair`, `has_twopair` 91 | * 19-1 conditional expression 92 | -------------------------------------------------------------------------------- /TP reading notes.md: -------------------------------------------------------------------------------- 1 | # This is Dex's note of reading _Think Python_ 2 | 3 | [__Check out my Github__](https://github.com/DexHunter) 4 | 5 | ## Reading notes: 6 | 7 | 1. two kinds of programs process high level language into low level language: interpreter & compiler 8 | 2. source code -> interpreter -> outputx 9 | 3. source code -> compiler -> object code -> executor -> output 10 | 4. program: a program is a sequence of instructions that specifies how to perform a computation. 11 | 5. script: the contents stored in form of a file 12 | 6. value: one of the basic units of data, like a number or string, that a program manipulates. 13 | 7. type: a category of values. 14 | 8. variable: a name that refers to a value. 15 | 9. argument: the expression in parentheses 16 | 17 | * question: why display the numbers start with 0 makes it bizarre? 18 | 19 | * note: page 20 has many definitions 20 | 21 | 9. two types of partition table: 22 | (1)MBR: Master Boot Record 23 | (2)GPT: GUID Partition Table 24 | 10. flow of execution: the order in which statement are executed 25 | 11. Function: a named sequence of statements that performs some useful operation. Functions may or may not take arguments and may or may not produce a result. 26 | 12. function definition: a statement that creates a new function, specifying its name, parameters, and the statements it excutes. 27 | 13. function object: a value created by a function definition. The name of the function is a variable that refers to a function object. 28 | 14. instance: a member of set 29 | 15. encapsulation: wrap a piece of code up in a function. 30 | 16. generaliztion: add a parameter to a function 31 | 17. interface of a function: a summary of how it is used: what are the parameters? What does the function do? And what is the return value? An interface is "clean" if it is "as simple as possible, but not simpler. (Einstein)" 32 | 18. A development plan: a process for writing programs. 33 | (1) Start by writing a small program with no function definitions. 34 | (2) Once you get the program working, encapsulate it in a function and give it a name. 35 | (3) Generalize the functionn by adding appropriate parameters. 36 | (4) Repeat steps 1-3 until you have a set of working functions. Copy and paste working code to aviod retyping( and re-bugging) 37 | (5) Loot for opportunities to improve the program by refactoring. For example, if you have similar code in several places, consider facotring it into an appropriately general function. 38 | 39 | ## V. Chapter 5 40 | 41 | 19. modulus operator: % 42 | 20. boolean expressions: either true or false 43 | 21. logical operators: and, or, not 44 | 22. conditional execution: if 45 | 23. alternative execution: else, elif 46 | 24. chained conditionals: 2+ branches 47 | 25. nested conditionals 48 | 26. recursion 49 | 27. stack diagram for recursive function. 50 | (1)n = 0, base case 51 | (2) 52 | 28. infinite recursion 53 | 29. keyboard input --> raw_input() 54 | 30. guardian 55 | 31. debuging: 56 | there are three possiblities here: 57 | (1)There is something wrong with the arguments the function is getting; a precondition is violated. 58 | (2)There is something wrong with the function; a post condition is violated. 59 | (3)These is something wrong with the return value or the way it is being used. 60 | 61 | ## VI. Chapter 6 62 | 63 | 1. Return Values 64 | 2. Incremental Development 65 | 3. Composition 66 | 4. Boolean Functions 67 | 5. More Recursion 68 | 6. Leap of Faith 69 | 7. Checking Types 70 | 8. Debugging 71 | 72 | ## VII. Chapter 7 Iteration 73 | 74 | 1. Multiple Assignment: to distinguish between an assignment operation and a statement of equality 75 | 2. Updating Variables: (1)increment (2)decrement 76 | 3. The while Statement 77 | 78 | 79 | 80 | ## Chapter 11 Dictionaries 81 | 82 | * key and values -> key-value pair (aka item) 83 | * associative memories 84 | * string and numbers can always be keys!!! 85 | * keys are immutable 86 | * Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. 87 | * list CANNOT be keys!!!! 88 | 89 | # Chapter 12 Tuples 90 | 91 | * The _ (undersocre) in python means: 92 | 93 | _ has 3 main conventional uses in Python: 94 | 95 | [source](http://stackoverflow.com/questions/5893163/what-is-the-purpose-of-the-single-underscore-variable-in-python) 96 | > 97 | 98 | 1. To hold the result of the last executed statement in an interactive interpreter session. This precedent was set by the standard CPython interpreter, and other interpreters have followed suit 99 | 100 | 2. For translation lookup in i18n (imported from the corresponding C conventions, I believe), as in code like: raise 101 | forms.ValidationError(_("Please enter a correct username")) 102 | 103 | 3. As a general purpose "throwaway" variable name to indicate that part of a function result is being deliberately ignored, as in code like: label, has_label, _ = text.partition(':') 104 | The latter two purposes can conflict, so it is necessary to avoid using _ as a throwaway variable in any code block that also uses it for i18n translation (many folks prefer a double-underscore, __, as their throwaway variable for exactly this reason). 105 | > 106 | * use 'in' to check whether a value is in the list 107 | 108 | 109 | ## Chapter 13 Case Study: Data Structure Selection 110 | 111 | #### What is difference between `return` and `pass` in python? [Souce](http://stackoverflow.com/questions/7872611/in-python-what-is-the-difference-between-pass-and-return) 112 | 113 | * `Return` exits the current function or method. `Pass` is a null operation and allows execution to continue at the next statement. 114 | 115 | #### Rubber duck debugging 116 | 117 | * Sometimes when you ask a question, you find the answer before you finish asking, then you don't need to ask a real person, you can just ask a rubber duck. It's a real thing called rubber duck debugging, you can just see the wikipedia. 118 | 119 | 120 | 121 | ## Chapter 14 Files 122 | 123 | * persistence: run for a long time (or all the time), keep at least some of data in permanent storage 124 | * trasience: run for a short time, when the program ends, data vanish as well 125 | 126 | ### Reading and Writing 127 | 128 | * If the file already exists, opening it in write mode clears out the old data and starts 129 | fresh, so be careful! 130 | 131 | * When the first oprand is a string, % is a format operator 132 | * relative path 133 | * absolute path, starts wtih '/' 134 | * dbm is a module in Python 3! 135 | * pipe object: an object representing a running program 136 | * What is pickle? pickle is a module implements serializing and de-serializing a Python object structure. "Pickling" is the process whereby a Python object hierarchy is converted into a byte stream, and "unpickling" is the inverse operation 137 | 138 | #### The % specifiers that you can use in ANSI C are: 139 | 140 | ##### Usual variable type Display 141 | 142 | * %c char single character 143 | 144 | * %d (%i) int signed integer 145 | 146 | * %e (%E) float or double exponential format 147 | 148 | * %f float or double signed decimal 149 | 150 | * %g (%G) float or double use %f or %e as required 151 | 152 | * %o int unsigned octal value 153 | 154 | * %p pointer address stored in pointer 155 | 156 | * %s array of char sequence of characters 157 | 158 | * %u int unsigned decimal 159 | 160 | * %x (%X) int unsigned hex value 161 | 162 | 163 | ## Chapter 15 Classes and Objects 164 | 165 | * == operator for object will check the object identity as __is__ operator rather than object equvalence, 166 | 167 | 168 | ## Chapter 17 Classes and Methods 169 | 170 | * Object-oriented: represents relationship between programmer-defined types and functions 171 | 172 | ## Chapter 18 Inheritance 173 | * veneer: a method or function that provide a different interface to another function without doing much computation 174 | 175 | ## Chapter 19 The Goodies 176 | 177 | #### conditional expressions 178 | 179 | #### list comprehensions 180 | 181 | #### generator expressions 182 | 183 | 184 | #### any and all 185 | 186 | 187 | #### sets 188 | 189 | #### counters 190 | 191 | A Counter represents a multiset. 192 | 193 | #### defaultdict 194 | 195 | 196 | #### named tuples 197 | 198 | #### gathering keyword args 199 | 200 | #### -------------------------------------------------------------------------------- /__pycache__/Card.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/__pycache__/Card.cpython-35.pyc -------------------------------------------------------------------------------- /captions: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/captions -------------------------------------------------------------------------------- /ch12_ex.py: -------------------------------------------------------------------------------- 1 | def sumall(*args): 2 | # use of gather opeartion 3 | # on page 142 4 | sum_result = 0 5 | for i in range(len(args)): 6 | sum_result = sum_result + args[i] 7 | return sum_result 8 | 9 | print sumall(1,2,3,4) -------------------------------------------------------------------------------- /ch15_ex.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | '''Represents a point in 2-D space.''' 3 | 4 | 5 | 6 | class Rectangle: 7 | '''Represents a rectangle 8 | 9 | attributes: width, height, corner. 10 | ''' 11 | def find_center(rect): 12 | p = Point() 13 | p.x = rect.corner.x + rect.width/2 14 | p.y = rect.corner.y + rect.height/2 15 | return p 16 | 17 | def print_point(p): 18 | print( '(%g, %g)' % (p.x, p.y) ) 19 | 20 | def distance_between_points(p1, p2): 21 | distance = math.sqrt( (p1.x - p2.x)**2 + (p1.y - p2.y)**2 ) 22 | return distance 23 | 24 | def move_rectangle(rect, dx, dy): 25 | '''Creates and returns a new rectangle 26 | 27 | ''' 28 | rect_new = copy.deepcopy(rect) #not only copy the object but also the references it contains 29 | rect_new.corner.x += dx 30 | rect_new.corner.y += dy 31 | 32 | import copy 33 | import math 34 | if __name__ == '__main__': 35 | blank = Point() 36 | blank.x = 3.0 37 | blank.y = 4.0 38 | b = Point() 39 | b.x = 0.0 40 | b.y =0.0 41 | print (distance_between_points(blank, b)) 42 | print_point(blank) 43 | bob = Rectangle() 44 | bob.width = 100.0 45 | bob.height = 200.0 46 | bob.corner = Point() 47 | bob.corner.x = 0.0 48 | bob.corner.y = 0.0 49 | 50 | center = find_center(bob) 51 | print_point(center) 52 | move_rectangle(bob, 50, 50) 53 | print_point(find_center(bob)) -------------------------------------------------------------------------------- /ch16_ex.py: -------------------------------------------------------------------------------- 1 | class Time: 2 | '''Represents the time of day. 3 | 4 | attributes: hour, minute, second 5 | ''' 6 | 7 | def print_time(t): 8 | print ('(%.2d:%.2d:%.2d)' % (t.hour, t.minute, t.second)) 9 | 10 | def is_after(t1, t2): 11 | return (t1.hour, t1.minute, t1.second) > (t2.hour, t2.minute, t2.second) 12 | 13 | def mul_time(t, n): 14 | '''Multiple time t by n 15 | 16 | n: int 17 | 18 | Returns a time tr 19 | ''' 20 | return int_to_time(time_to_int(t) * n) 21 | 22 | def add_time(t1, t2): 23 | sum = Time() 24 | sum.hour = t1.hour + t2.hour 25 | sum.minute = t1.minute + t2.minute 26 | sum.second = t1.second + t2.second 27 | 28 | while sum.second >= 60: 29 | sum.second -= 60 30 | sum.minute += 1 31 | 32 | while sum.minute >= 60: 33 | sum.minute -= 60 34 | sum.hour += 1 35 | 36 | return sum 37 | 38 | def increment(t, sec): 39 | '''Writes a inc function does not contain any loops 40 | #for the second exercise of writing a pure function, I think you can just create a new object by copy.deepcopy(t) and modify the new object. I think it is quite simple so I will skip this one, if you differ please contact me and I will try to help 41 | 42 | idea: using divmod 43 | sec: seconds in IS 44 | ''' 45 | t.second += sec 46 | inc_min, t.second = div(t.seconds, 60) 47 | t.minute += inc_min 48 | inc_hour, t.minute = div(t.minute, 60) 49 | t.hour += inc_hour 50 | return t 51 | 52 | def int_to_time(seconds): 53 | """Makes a new Time object. 54 | 55 | seconds: int seconds since midnight. 56 | """ 57 | time = Time() 58 | minutes, time.second = divmod(seconds, 60) 59 | time.hour, time.minute = divmod(minutes, 60) 60 | return time 61 | 62 | 63 | def time_to_int(time): 64 | """Computes the number of seconds since midnight. 65 | 66 | time: Time object. 67 | """ 68 | minutes = time.hour * 60 + time.minute 69 | seconds = minutes * 60 + time.second 70 | return seconds 71 | 72 | if __name__ == '__main__': 73 | t = Time() 74 | t.hour = 17 75 | t.minute = 43 76 | t.second = 6 77 | print_time(mul_time(t, 3)) 78 | 79 | t2 = Time() 80 | t2.hour = 17 81 | t2.minute = 44 82 | t2.second = 5 83 | print_time(t) 84 | 85 | start = Time() 86 | start.hour = 9 87 | start.minute =45 88 | start.second = 0 89 | 90 | duration = Time() 91 | duration.hour = 1 92 | duration.minute = 35 93 | duration.second = 0 94 | 95 | done = add_time(start, duration) 96 | print_time(done) 97 | 98 | print( is_after(t, t2) ) 99 | -------------------------------------------------------------------------------- /ch16_ex.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/ch16_ex.pyc -------------------------------------------------------------------------------- /ch17_ex.py: -------------------------------------------------------------------------------- 1 | class Time: 2 | def __init__(self, hour=0, minute=0, second=0): 3 | self.hour = hour 4 | self.minute = minute 5 | self.second = second 6 | 7 | def __str__(self): 8 | return '%.2d:%.2d:%.2d' % (self.hour, self.minute, self.second) 9 | 10 | def __add__(self, other): 11 | ''' change the behavior of + operator, aka operator overloading''' 12 | #type-based dispatch 13 | if isinstance(other, Time): 14 | return self.add_time(other) 15 | else: 16 | return self.increment(seconds) 17 | 18 | def __radd__(self, other): 19 | '''right-side addition 20 | make addition commutative ''' 21 | return self.__add__(other) 22 | 23 | def add_time(self, other): 24 | seconds = self.time_to_int() + other.time_to_int() 25 | return int_to_time(seconds) 26 | 27 | def print_time(self): 28 | print('%.2d:%.2d:%.2d' % (self.hour, self.minute, self.second)) 29 | 30 | def time_to_int(self): 31 | minutes = self.hour * 60 + self.minute 32 | seconds = minutes * 60 + self.second 33 | return seconds 34 | 35 | def increment(self, seconds): 36 | seconds += self.time_to_int() 37 | return int_to_time(seconds) 38 | 39 | def is_after(self, other): 40 | return self.time_to_int() > other.time_to_int() 41 | 42 | 43 | def int_to_time(seconds): 44 | '''No need to rewrite it as a method since there is no object to invoke 45 | 46 | ''' 47 | time = Time() 48 | minutes, time.second = divmod(seconds, 60) 49 | time.hour, time.minute = divmod(minutes, 60) 50 | return time 51 | 52 | class Point: 53 | def __init__(self, x=0, y=0): 54 | self.x = x 55 | self.y = y 56 | 57 | def __str__(self): 58 | return '(%d,%d)' % (self.x, self.y) 59 | 60 | def __add__(self, other): 61 | if isinstance(other, Point): 62 | return self.add_point(other) 63 | else: #if second operand is a tuple 64 | return self.add_tuple(other) 65 | 66 | def add_point(self, other): 67 | vector = Point() 68 | vector.x = self.x + other.x 69 | vector.y = self.y + other.y 70 | return vector 71 | 72 | def add_tuple(self, other): 73 | if isinstance(other, tuple): 74 | self.x += other[0] 75 | self.y += other[1] 76 | return self 77 | else: 78 | print("Input format is wrong, return given Point") 79 | return self 80 | 81 | def __radd__(self, other): 82 | return self.__add__(other) 83 | 84 | if __name__ == '__main__': 85 | start = Time() 86 | start.hour = 9 87 | start.minute = 45 88 | start.second = 00 89 | start.print_time() 90 | time = Time(9, 45, 1) 91 | print(time) 92 | print(time.is_after(start)) 93 | d1 = Point(3,4) 94 | print(d1) 95 | d2 = Point(5,12) 96 | print(d2) 97 | print(d1+d2) 98 | print(d1+(5,12)) 99 | d1 = Point(3,4) #__add__ is a modifier function 100 | print((5,12)+d1) 101 | print(d1) 102 | print(d1) 103 | #print( int_to_time(500) ) 104 | end = start.increment(1337) 105 | end.print_time() 106 | print(start + end) -------------------------------------------------------------------------------- /ch4_ex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | def square(t): 4 | for i in range(4): 5 | t.fd(100) 6 | t.lt(90) # move a right angle to the left 7 | 8 | def square_modified(t,length): 9 | for i in range(4): 10 | t.fd(length) #custom length 11 | t.lt(90) # move a right angle to the left 12 | 13 | def polygon(t,length, n): 14 | move_angle = 360.0 / n #!!!make angle to float 15 | for i in range(n): 16 | t.fd(length) #custom length 17 | t.lt(move_angle) # move a right angle to the left 18 | 19 | def circle(t, r): 20 | #figure out the circumference of the circle and make sure that length * n = circumference 21 | n = 20 22 | circumference = 2 * math.pi * r 23 | length = circumference / n 24 | polygon(t, length, n) 25 | 26 | def arc(t, r, angle): 27 | n = 10 28 | circumference = 2 * math.pi * r 29 | length = circumference / n 30 | arc_angle = (float) (angle / n) 31 | for i in range(n + 1): # + 1 to draw the closing after turning angle 32 | t.fd(length) 33 | t.lt(arc_angle) 34 | 35 | 36 | 37 | import math 38 | from swampy.TurtleWorld import * 39 | 40 | if __name__ == '__main__': 41 | world = TurtleWorld() 42 | bob = Turtle() 43 | print bob 44 | bob.delay = 0.001 45 | #circle(bob, 20) 46 | #polygon(bob, 1, 200) 47 | arc(bob, 10, 180) 48 | bob.die() 49 | wait_for_user() -------------------------------------------------------------------------------- /ch4_ex.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/ch4_ex.pyc -------------------------------------------------------------------------------- /ch8_ex.py: -------------------------------------------------------------------------------- 1 | #running on python 2 is fine 2 | 3 | def ducklings(): 4 | prefixes = 'JKLMNOPQ' 5 | suffix = 'ack' 6 | 7 | for letter in prefixes: 8 | if letter == 'O' or letter == 'Q': 9 | suffix = 'uack' 10 | print letter + suffix 11 | else: 12 | suffix = 'ack' 13 | print letter + suffix 14 | 15 | ducklings() 16 | 17 | #friut[:] will return the full string which is "banana" 18 | 19 | def find(string, letter, index): 20 | while index < len(string): 21 | if string[index] == letter: 22 | return index 23 | index = index + 1 24 | return -1 25 | 26 | find_second_e = find("I revised this exercise to make it more readable", "e", 5) 27 | print find_second_e 28 | 29 | def count(string, letter): 30 | length = len(string) 31 | counter = 0 32 | index = 0 33 | while length > 0: 34 | if find(string, letter, index) != -1: 35 | counter += 1 36 | index = find(string, letter, index) 37 | string = string[1 : len(string)] 38 | length = len(string) 39 | 40 | return counter 41 | 42 | 43 | count_e = count("I revised this exercise to make it more readable", "e") 44 | print count_e 45 | -------------------------------------------------------------------------------- /check/checkwork.py: -------------------------------------------------------------------------------- 1 | #This is for check duplicate file from exercise 14-3 -------------------------------------------------------------------------------- /checksum.py: -------------------------------------------------------------------------------- 1 | #This is for check duplicate file from exercise 14-3 -------------------------------------------------------------------------------- /data.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/data.pkl -------------------------------------------------------------------------------- /ex03_1.py: -------------------------------------------------------------------------------- 1 | #Write a function named right_justify that takes a string named s as a parameter and prints the string with enough leading spaces so that the last letter of the string is in column 70 of the display 2 | 3 | def right_justify(s): 4 | whitespace_num = 70 - len(s) 5 | s = ' ' * whitespace_num + s 6 | print s 7 | 8 | right_justify("month") 9 | right_justify("a") 10 | right_justify("This is a test,This is a test,This is a test,This is a test,This is a") #string length = 69 -------------------------------------------------------------------------------- /ex03_2.py: -------------------------------------------------------------------------------- 1 | def do_twice(f,v): 2 | f(v) 3 | f(v) 4 | 5 | def print_twice(s): 6 | print(s) 7 | print(s) 8 | 9 | do_twice(print_twice,"spam") 10 | 11 | def do_four(f,v): 12 | do_twice(f,v) 13 | do_twice(f,v) 14 | 15 | print ("--------cutting line---------") 16 | 17 | do_four(print_twice,"four") -------------------------------------------------------------------------------- /ex03_3.py: -------------------------------------------------------------------------------- 1 | #first one 2 | 3 | def do_two(f): 4 | f() 5 | f() 6 | 7 | def print_two(v): 8 | print (v*2) 9 | 10 | 11 | def do_four(f): 12 | f() 13 | f() 14 | f() 15 | f() 16 | 17 | 18 | def print_dash(): 19 | print ( '-', end=' ' ) 20 | 21 | def print_line_short(): 22 | print ("+", end=' ') 23 | do_four(print_dash) 24 | 25 | 26 | def print_line(): 27 | do_two(print_line_short) 28 | print ("+", end=' ') 29 | 30 | def print_line_four(): 31 | do_four(print_line_short) 32 | print ("+", end=' ') 33 | 34 | def print_vbar(): 35 | print(("|"+" "*9)*2+"|") 36 | 37 | def print_vbar_four(): 38 | print(("|"+" "*9)*4+"|") 39 | 40 | 41 | def print_grid(): 42 | print_line() 43 | print("") 44 | do_four(print_vbar) 45 | print_line() 46 | print("") 47 | do_four(print_vbar) 48 | print_line() 49 | 50 | 51 | print_grid() 52 | 53 | #second one 54 | 55 | def print_grid_four(): 56 | print_line_four() 57 | print("") 58 | do_four(print_vbar_four) 59 | print_line_four() 60 | print("") 61 | do_four(print_vbar_four) 62 | print_line_four() 63 | print("") 64 | do_four(print_vbar_four) 65 | print_line_four() 66 | print("") 67 | do_four(print_vbar_four) 68 | print_line_four() 69 | 70 | print("") 71 | print("---------cutting edge------------") 72 | 73 | print_grid_four() -------------------------------------------------------------------------------- /ex04_1.py: -------------------------------------------------------------------------------- 1 | #first: draw a stack diagram 2 | ''' 3 | set r = 5 4 | set t = Bob 5 | __main__ 6 | 7 | 8 | 9 | polygon_n length= 1.571 move_angle = 18 n = 0 10 | polygon_n length= 1.571 move_angle = 18 n = 1 11 | polygon_n length= 1.571 move_angle = 18 n = 2 12 | polygon_n length= 1.571 move_angle = 18 n = 3 13 | polygon_n length= 1.571 move_angle = 18 n = 4 14 | polygon_n length= 1.571 move_angle = 18 n = 5 15 | polygon_n length= 1.571 move_angle = 18 n = 6 16 | polygon_n length= 1.571 move_angle = 18 n = 7 17 | polygon_n length= 1.571 move_angle = 18 n = 8 18 | polygon_n length= 1.571 move_angle = 18 n = 9 19 | polygon_n length= 1.571 move_angle = 18 n = 10 20 | polygon_n length= 1.571 move_angle = 18 n = 11 21 | polygon_n length= 1.571 move_angle = 18 n = 12 22 | polygon_n length= 1.571 move_angle = 18 n = 13 23 | polygon_n length= 1.571 move_angle = 18 n = 14 24 | polygon_n length= 1.571 move_angle = 18 n = 15 25 | polygon_n length= 1.571 move_angle = 18 n = 16 26 | polygon_n length= 1.571 move_angle = 18 n = 17 27 | polygon_n length= 1.571 move_angle = 18 n = 18 28 | polygon_n length= 1.571 move_angle = 18 n = 19 29 | polygon_n length= 1.571 move_angle = 18 n = 20 30 | 31 | 32 | 33 | ''' 34 | 35 | #second: Totally make sense 36 | 37 | ''' 38 | 39 | 40 | def arc(t, r, angle): 41 | """Draws an arc with the given radius and angle. 42 | 43 | t: Turtle 44 | r: radius 45 | angle: angle subtended by the arc, in degrees 46 | """ 47 | arc_length = 2 * math.pi * r * abs(angle) / 360 48 | n = int(arc_length / 4) + 1 49 | step_length = arc_length / n 50 | step_angle = float(angle) / n 51 | 52 | # making a slight left turn before starting reduces 53 | # the error caused by the linear approximation of the arc 54 | lt(t, step_angle/2) 55 | polyline(t, n, step_length, step_angle) 56 | rt(t, step_angle/2) 57 | 58 | ''' -------------------------------------------------------------------------------- /ex04_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | from swampy.TurtleWorld import * 4 | from polygon import arc 5 | 6 | def petal(t, r, angle): 7 | for i in range(2): 8 | arc(t, r, angle) 9 | lt(t, 180-angle) 10 | 11 | 12 | def flower(t, n, r, angle): 13 | for i in range(n): 14 | petal(t, r, angle) 15 | rt(t, 360.0/n) 16 | 17 | 18 | def move(t, length): 19 | pu(t) 20 | fd(t, length) 21 | pd(t) 22 | 23 | world = TurtleWorld() 24 | bob = Turtle() 25 | bob.delay = 0.0001 26 | 27 | move(bob, -150) 28 | petal(bob, 50.0, 100.0) 29 | move(bob,100) 30 | flower(bob, 7, 60.0, 60.0) 31 | 32 | move(bob, 100) 33 | flower(bob, 10, 40.0, 80.0) 34 | 35 | move(bob, 200) 36 | flower(bob, 50, 50.0, 100.0) 37 | 38 | bob.die() 39 | wait_for_user() -------------------------------------------------------------------------------- /ex04_3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | def isosceles(t, l, theta): 4 | # t : turtle 5 | # l: length of legs 6 | # theta: inner angle 7 | 8 | b = 2 * l * math.sin(((theta/2)/180) * math.pi) #base length 9 | 10 | t.fd(l) 11 | t.rt(90+theta/2) 12 | t.fd(b) 13 | t.rt(90+theta/2) 14 | t.fd(l) 15 | t.lt(180) 16 | 17 | 18 | 19 | def pie(t, n, l): 20 | # t : turtle 21 | # n : the amount of pieces of pie 22 | # l : the length of leg 23 | 24 | theta = 360.0 / n # inner angle 25 | for i in range(n): 26 | isosceles(t, l, theta) 27 | 28 | 29 | from swampy.TurtleWorld import * 30 | import math 31 | 32 | world = TurtleWorld() 33 | bob = Turtle() 34 | bob.delay = 0.001 35 | 36 | pie(bob, 5, 30) 37 | bob.pu() 38 | bob.fd(120) 39 | bob.pd() 40 | 41 | pie(bob, 6, 30) 42 | bob.pu() 43 | bob.fd(120) 44 | bob.pd() 45 | 46 | pie(bob, 7, 30) 47 | bob.pu() 48 | bob.fd(120) 49 | bob.pd() 50 | 51 | pie(bob, 8, 30) 52 | bob.pu() 53 | bob.fd(120) 54 | bob.pd() 55 | 56 | bob.die() 57 | wait_for_user() -------------------------------------------------------------------------------- /ex04_5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | ''' 4 | draw fermat's spiral 5 | ideas from Downey's original code. 6 | 7 | ''' 8 | try: 9 | # see if Swampy is installed as a package 10 | from swampy.TurtleWorld import * 11 | except ImportError: 12 | # otherwise see if the modules are on the PYTHONPATH 13 | from TurtleWorld import * 14 | 15 | 16 | def draw_spiral(t, n, length, a, b): 17 | 18 | theta = 0.0 19 | 20 | for i in range(n): 21 | fd(t, length) 22 | dtheta = 1 / (a + b * theta) 23 | 24 | rt(t, dtheta) 25 | theta += dtheta 26 | 27 | def draw_spiral_n(t, n, length, a, b): 28 | 29 | theta = 0.0 30 | 31 | for i in range(n): 32 | bk(t, length) #inverse move 33 | dtheta = 1 / (a + b * theta) 34 | 35 | rt(t, dtheta) 36 | 37 | theta += dtheta 38 | 39 | 40 | import math 41 | # create the world and bob 42 | world = TurtleWorld() 43 | bob = Turtle() 44 | bob2 = Turtle() 45 | bob.delay = 0 46 | bob2.delay = 0 47 | draw_spiral(bob, n=1000, length=3, a=0.01, b=0.0002) 48 | draw_spiral_n(bob2, n=1000, length=3, a=0.01, b=0.0002) 49 | 50 | 51 | bob.die() 52 | bob2.die() 53 | 54 | wait_for_user() -------------------------------------------------------------------------------- /ex05_1.py: -------------------------------------------------------------------------------- 1 | import time 2 | # time.time() return the time in seconds since the epoch as a floating point number 3 | 4 | def chour(t): 5 | hour = t / 3600 6 | print("The number of hours has passed since epoch is %f" % hour) 7 | 8 | def cminute(t): 9 | minute = t / 60 10 | print("The number of minutes has passed since epoch is %f" % minute) 11 | 12 | def cseconds(t): 13 | seconds = t 14 | print("The number of seconds has passed since epoch is %f" % seconds) 15 | 16 | def num_day(): 17 | sec = time.time() 18 | num_day = sec / (60*60*24) 19 | print("The number of days has passed since epoch is %f" % num_day) 20 | 21 | num_day() 22 | chour(time.time()) 23 | cminute(time.time()) 24 | cseconds(time.time()) -------------------------------------------------------------------------------- /ex05_2.py: -------------------------------------------------------------------------------- 1 | # 5_2_1 run python2 2 | import math 3 | 4 | def check_fermat(a, b, c, n): 5 | if n > 2 and a**n + b**n == c**n: 6 | print ("Fermat is wrong!") 7 | else: 8 | print ("Fermat is right on this!") 9 | 10 | 11 | def run_cf(): 12 | for a in range(1, 100): 13 | for b in range(1, 100): 14 | for c in range(1, 100): 15 | for n in range(3, 100): 16 | check_fermat(a, b, c, n) 17 | 18 | 19 | 20 | 21 | # first test 22 | check_fermat(2, 3, 4, 2) 23 | check_fermat(3, 4, 5, 2) #n need to be more than 2! 24 | 25 | # second test 26 | #run_cf() 27 | # 5_2_2 run python2 28 | def check_fermat_custom(): 29 | a = input("Please in put a: ") 30 | b= input("Please in put b: ") 31 | c = input("Please in put c: ") 32 | n = input("Please input n: ") 33 | return check_fermat(a, b, c, n) 34 | 35 | check_fermat_custom() 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /ex05_3.py: -------------------------------------------------------------------------------- 1 | def is_triangle(a, b, c): 2 | if a + b > c and a + c > b and b + c > a: 3 | print "Yes" 4 | else: 5 | print "No" 6 | 7 | is_triangle(3, 4, 5) 8 | 9 | def is_triangle_custom(): 10 | a = input("Please input a: ") 11 | b = input("Please input b: ") 12 | c = input("Please input c: ") 13 | return is_triangle(a, b, c) 14 | 15 | is_triangle_custom() -------------------------------------------------------------------------------- /ex05_4.py: -------------------------------------------------------------------------------- 1 | def recurse(n, s): 2 | if n == 0: 3 | print(s) 4 | else: 5 | print "n is: %d" % n 6 | print "s is: %d" % s 7 | recurse(n-1, n+s) 8 | 9 | recurse(3, 0) 10 | recurse(-1, 0) #Runtime error: maxmimum recursion depth exceeded 11 | ''' 12 | input n (n>0) since n need to approach 0 13 | ''' -------------------------------------------------------------------------------- /ex05_5.py: -------------------------------------------------------------------------------- 1 | def draw(t, length, n): 2 | if n == 0: 3 | return 4 | angle = 50 # initialize angle 5 | t.fd(length * n) 6 | t.lt(angle) 7 | draw(t, length, n-1) #recursive call 8 | t.rt(2*angle) 9 | draw(t, length, n-1) 10 | t.lt(angle) 11 | t.bk(length*n) 12 | 13 | # if product of n and length is big it will draw something like a spiral but not circular 14 | # and when product reduces, it draws something like a snowflake 15 | 16 | from swampy.TurtleWorld import * 17 | import math 18 | 19 | if __name__ == '__main__': 20 | world = TurtleWorld() 21 | bob = Turtle() 22 | bob.delay = 0.001 23 | draw(bob, 3, 30) 24 | wait_for_user() -------------------------------------------------------------------------------- /ex05_6.py: -------------------------------------------------------------------------------- 1 | def koch(t, l): 2 | # t: turtle 3 | # l: length 4 | if l < 3: 5 | t.fd(l) 6 | else: 7 | koch(t,l/3) 8 | t.lt(60) 9 | koch(t,l/3) 10 | t.rt(120) 11 | koch(t,l/3) 12 | t.lt(60) 13 | koch(t,l/3) 14 | 15 | #inner angle summation is 360 degrees 16 | def snowflake(t, l): 17 | koch(t, l) 18 | t.rt(120) 19 | koch(t,l) 20 | t.rt(120) 21 | koch(t,l) 22 | 23 | 24 | from swampy.TurtleWorld import * 25 | import math 26 | 27 | if __name__ == '__main__': 28 | world = TurtleWorld() 29 | bob = Turtle() 30 | bob.delay = 0 31 | #koch(bob, 550) #the same as figure 5-2 shows 32 | snowflake(bob, 300) 33 | bob.die() 34 | wait_for_user() -------------------------------------------------------------------------------- /ex06_1.py: -------------------------------------------------------------------------------- 1 | def b(z): 2 | prod = a(z, z) #calculate product of 3 | print (z, prod) 4 | return prod 5 | 6 | def a(x, y): 7 | x = x + 1 #increment x 8 | return x * y 9 | 10 | def c(x, y, z): 11 | total = x + y + z 12 | square = b(total) ** 2 13 | return square 14 | 15 | x = 1 16 | y = x + 1 17 | print (c(x, y+3, x+ y)) 18 | 19 | ''' 20 | steps : c(1, 2 + 3, 1 + 2) 21 | total = 1 + 5 + 3 = 9 22 | square = b(9) 23 | inside b: prod = a(9, 9) 24 | inside a: x = 10 return 90 25 | back to b: print(9, 90) return 90 26 | back to c: square = 90 ^2 = 8100 27 | print 8100 28 | ''' -------------------------------------------------------------------------------- /ex06_2.py: -------------------------------------------------------------------------------- 1 | def ack(m, n): 2 | if m == 0: 3 | return n + 1 4 | elif m > 0 and n == 0: 5 | return ack(m-1, 1) 6 | else: 7 | return ack(m-1, ack(m, n - 1)) 8 | 9 | x = ack(3, 6) 10 | print x -------------------------------------------------------------------------------- /ex06_3.py: -------------------------------------------------------------------------------- 1 | def is_palindrome(word): 2 | if word == word[::-1]: 3 | return True 4 | else: 5 | return False 6 | 7 | print is_palindrome("helloollehr") 8 | 9 | #another version 10 | 11 | def is_palin(w): 12 | if w[-1] != w[-len(w)]: 13 | return False 14 | else: 15 | return is_palin(w[-len(w)+1:len(w)-1]) # This return is essential for successful run! Otherwise it is not a recursive call 16 | 17 | result = is_palin("redividerr") 18 | print result -------------------------------------------------------------------------------- /ex06_4.py: -------------------------------------------------------------------------------- 1 | def is_power(a, b): 2 | if(a == b): #base case a = b 3 | return True 4 | elif(a % b != 0): 5 | return False 6 | else: 7 | return is_power(a/b , b) 8 | 9 | print is_power(8,2) 10 | print is_power(9,2) -------------------------------------------------------------------------------- /ex06_5.py: -------------------------------------------------------------------------------- 1 | def gcd(a, b): 2 | a = int(a) 3 | b = int(b) 4 | if a > b: 5 | c = a - b 6 | gcd(b, c) 7 | elif a < b: 8 | c = b - a 9 | gcd(a, c) 10 | else: 11 | print a 12 | 13 | gcd(252, 105) 14 | 15 | #another version instruted from book 16 | # I wonder how to prove it mathematically. Hmm... 17 | # Update: This algorithm is based on Bezout's identity which states that let a and b be nonzero integers and let d be their greatest common divisor. Then there exist integers x and y such that ax + by = d, https://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity 18 | def gcd_euclid(a,b): 19 | if (b == 0): 20 | return a 21 | else: 22 | return gcd_euclid(b, a%b) 23 | 24 | 25 | print gcd_euclid(105, 252) -------------------------------------------------------------------------------- /ex07_1.py: -------------------------------------------------------------------------------- 1 | def mysqrt(a): 2 | epsilon = 0.00001 3 | x = 5.00000 4 | while True: 5 | y = (x + a/x) / 2 6 | if abs(y - x) < epsilon: 7 | return y 8 | break 9 | x = y 10 | 11 | import math 12 | print mysqrt( 4 ) 13 | 14 | def test_square_root(): 15 | print "a mysqrt(a) math.sqrt(a) diff" 16 | print "- --------- ------------ ----" 17 | for a in range(1, 10): 18 | print "%.1f %.5f %.5f %f" % (a,mysqrt(a), math.sqrt(a), mysqrt(a)-math.sqrt(a)) 19 | 20 | test_square_root() -------------------------------------------------------------------------------- /ex07_2.py: -------------------------------------------------------------------------------- 1 | def eval_loop(): 2 | while True: 3 | i = raw_input("Input: ") 4 | try: 5 | print(eval(i)) 6 | except (NameError, SyntaxError): 7 | if i == 'done': 8 | break 9 | else: 10 | print i 11 | 12 | 13 | import math #in case you need to evaluate some complex functions 14 | eval_loop() 15 | -------------------------------------------------------------------------------- /ex07_3.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | def estimate_pi(): 5 | sum = 0 6 | epsilon = math.pow(10, -15) 7 | k = 0 8 | i = 1 #initialize i, the value doesn't matter 9 | while i > epsilon: 10 | i = (math.factorial(4*k) * (1103 + 26390 * k)) / (math.pow((math.factorial(k)), 4) * math.pow(396, 4*k) ) 11 | sum += i 12 | k += 1 #!important 13 | inverse = 2 * math.sqrt(2) * sum / 9801 14 | return 1/inverse 15 | 16 | print estimate_pi() 17 | print math.pi 18 | print estimate_pi() - math.pi -------------------------------------------------------------------------------- /ex07_4.py: -------------------------------------------------------------------------------- 1 | def eval_loop(): 2 | while True: 3 | i = input("Input: ") 4 | if i == "done": 5 | break 6 | else: 7 | print i 8 | 9 | eval_loop() 10 | -------------------------------------------------------------------------------- /ex08_1.py: -------------------------------------------------------------------------------- 1 | # experiment with string methods, preferrably run on python 3 2 | 3 | print 'www.example.com'.strip('cmow.') 4 | print "apple".replace("a", "i") -------------------------------------------------------------------------------- /ex08_2.py: -------------------------------------------------------------------------------- 1 | word = 'banana' 2 | i = word.count('a') 3 | print i -------------------------------------------------------------------------------- /ex08_3.py: -------------------------------------------------------------------------------- 1 | def is_palindrome(word): 2 | return word == word[::-1] 3 | 4 | 5 | print is_palindrome("redivider") 6 | print is_palindrome("apple") -------------------------------------------------------------------------------- /ex08_4.py: -------------------------------------------------------------------------------- 1 | # parameter is a string 2 | 3 | def any_lowercase1(s): 4 | for c in s: 5 | if c.islower(): 6 | return True #check every character in the string is a lowercase character and return a boolean value 7 | else: 8 | return False 9 | 10 | def any_lowercase2(s): 11 | for c in s: 12 | if 'c'.islower(): #always return a string 'true' since 'c' is a lowercase no matter how many characters are in the string 13 | return 'True' 14 | else: 15 | return 'False' 16 | 17 | def any_lowercase3(s): 18 | for c in s: 19 | flag = c.islower() #check if the last character in the string is a lower case, return a boolean value 20 | return flag 21 | 22 | def any_lowercase4(s): 23 | flag = False 24 | for c in s: 25 | flag = flag or c.islower() #check if the last character in the string is a lower case, return a boolean value 26 | return flag 27 | 28 | def any_lowercase5(s): 29 | for c in s: 30 | if not c.islower(): 31 | return False #check if every character in the string is a lower case, return a boolean value False if not 32 | return True -------------------------------------------------------------------------------- /ex08_5.py: -------------------------------------------------------------------------------- 1 | def rotate_word(s, n): 2 | s_c = "" #initialize 3 | i = 0 #initialize 4 | for c in s: 5 | if ord(c) >= ord('A') and ord(c) <= ord('Z'): 6 | i = (ord(c) - ord('A') + n ) % 26 + ord('A') 7 | elif ord(c) >= ord('a') and ord(c) <= ord('z'): 8 | i = (ord(c) - ord('a') + n ) % 26 + ord('a') 9 | else: 10 | i = ord(c) # other characters does not change 11 | s_c += chr(i) 12 | return s_c 13 | 14 | print (rotate_word("apple+apple", 3)) 15 | print (rotate_word("APPLE", 3)) -------------------------------------------------------------------------------- /ex09_1.py: -------------------------------------------------------------------------------- 1 | def read(f): 2 | with open(f) as file: 3 | for line in file: 4 | word = line.strip() 5 | if len(word) > 20: 6 | print word 7 | 8 | read('words.txt') 9 | #read('test.txt') -------------------------------------------------------------------------------- /ex09_2.py: -------------------------------------------------------------------------------- 1 | def has_no_e(word): 2 | if "e" not in word: 3 | return True 4 | else: 5 | return False 6 | 7 | def read(f): 8 | ctr_e = 0.0 9 | ctr_all = 0.0 10 | with open(f) as file: 11 | for line in file: 12 | ctr_all += 1 13 | word = line.strip() 14 | if has_no_e(word): 15 | print word 16 | ctr_e += 1 17 | print ctr_e / ctr_all 18 | 19 | read('words.txt') -------------------------------------------------------------------------------- /ex09_3.py: -------------------------------------------------------------------------------- 1 | # This exercise is eaiser to do with regex 2 | # An answer becomes very handy in this case:http://stackoverflow.com/questions/22506193/is-there-a-better-algorithm-for-exercise-9-3-in-think-python-how-to-think-like 3 | ''' 4 | # previous version, changed after read the link 5 | def avoids(word, forbid_string): 6 | for c in word: 7 | if c in forbid_string: 8 | return False 9 | return True 10 | ''' 11 | 12 | def avoids(word, forbid_string): 13 | return set(forbid_string).isdisjoint(set(word)) 14 | 15 | # a combination of five forbidden letters that excludes the smallest number of words also means a combination contains the least amount of words 16 | def avoids_count_modified(word): 17 | forbid_string = raw_input("Please enter a forbidden string: ") 18 | return sum(avoids(word, forbid_string) for c in word) 19 | 20 | print avoids("Apple", "abcdA") 21 | # I am not trying to write a function to return the combination, you can read the post with given link, that's a brilliant solution 22 | # the answer is ['q', 'j', 'x', 'z', 'w'] if you are interested -------------------------------------------------------------------------------- /ex09_4.py: -------------------------------------------------------------------------------- 1 | def uses_only(word, letters): 2 | for c in "".join(word.split()): 3 | #print c # test 4 | if c not in letters: 5 | return False 6 | return True 7 | 8 | print (uses_only("hoe alfalfa", "acefhlo" )) 9 | # Ace, lohf? -------------------------------------------------------------------------------- /ex09_5.py: -------------------------------------------------------------------------------- 1 | def uses_all(word, letters): 2 | # if letter in letters does not appear in word, it means this letter was not used in word which will return False 3 | for c in letters: 4 | if c not in word: 5 | return False 6 | return True 7 | 8 | print (uses_all("To day is a good day", "god")) 9 | print (uses_all("To day is a good day", "godA")) -------------------------------------------------------------------------------- /ex09_6.py: -------------------------------------------------------------------------------- 1 | def is_abecedarian(word): 2 | for i in range(len(word)): 3 | for j in range(i+1, len(word)): 4 | if ord(word[i]) > ord(word[j]): 5 | return False 6 | return True 7 | 8 | def count_abecedarian(word): 9 | ctr = 0 10 | for c in word: 11 | if is_abecedarian(c): 12 | ctr += 1 13 | print ctr 14 | 15 | 16 | if __name__ == '__main__': 17 | with open('words.txt', 'r') as fin: 18 | words = [line.strip() for line in fin] 19 | count_abecedarian(words) 20 | # ans: The amount of abecedarian words is 596 -------------------------------------------------------------------------------- /ex09_7.py: -------------------------------------------------------------------------------- 1 | def find_double(word): 2 | i = 0 3 | ctr = 0 # double counter 4 | while i < len(word) - 2: 5 | if word[i+1] == word[i]: 6 | ctr += 1 7 | i += 2 8 | if ctr == 3: 9 | return word 10 | else: 11 | ctr = 0 12 | i += 1 13 | 14 | return None 15 | 16 | 17 | # ans: bookkeeper, etc 18 | if __name__ == '__main__': 19 | 20 | with open('words.txt', 'r') as fin: 21 | words = [line.strip() for line in fin] 22 | for c in words: 23 | if find_double(c) != None: 24 | print (find_double(c)) 25 | 26 | 27 | -------------------------------------------------------------------------------- /ex09_8.py: -------------------------------------------------------------------------------- 1 | def is_palindrome(word): 2 | return word == word[::-1] 3 | 4 | def is_palindrome_num(num): 5 | part_one = num[2:6] 6 | num = str(int(num) + 1) 7 | part_two = num[1:6] 8 | num = str(int(num) + 1) 9 | part_three = num[1:5] 10 | num = str(int(num) + 1) 11 | part_four = num 12 | if is_palindrome(part_one): 13 | if is_palindrome(part_two): 14 | if is_palindrome(part_three): 15 | if is_palindrome(part_four): 16 | return True 17 | return False 18 | 19 | def check_num(): 20 | for i in range(100000, 999999): 21 | if is_palindrome_num(str(i)): 22 | print i 23 | 24 | 25 | check_num() 26 | #ans: 198888, 199999 -------------------------------------------------------------------------------- /ex09_9.py: -------------------------------------------------------------------------------- 1 | def is_reverse(a, b): 2 | return b == a[::-1] 3 | 4 | def find_mom_and_my_age_difference(): 5 | 6 | 7 | diff = 15 8 | while diff < 50: 9 | ctr = 0 10 | my_age = 0 11 | while my_age < 99: 12 | #print my_age 13 | mom_age = my_age + diff 14 | if is_reverse(str(my_age).zfill(2), str(mom_age)): 15 | ctr += 1 16 | if ctr == 8: 17 | return diff 18 | my_age += 1 19 | 20 | diff += 1 21 | 22 | def find_my_age(n): 23 | mom_age = n 24 | my_age = 0 25 | ctr = 0 26 | while my_age < 99: 27 | if is_reverse(str(my_age).zfill(2), str(mom_age)): 28 | ctr += 1 29 | if ctr == 6:#reverse phenomena has happened six times before 30 | return my_age 31 | mom_age += 1 32 | my_age += 1 33 | 34 | print find_my_age(find_mom_and_my_age_difference()) 35 | #ans: 57 yrs old 36 | ''' 37 | after read author's answer, I found there are two possibilities one is that kid's birthday is earlier than mom's, the other is mom's birthday is earlier than kid's but that will reuslt in a different situation. But my solution is enough to find the right answer. 38 | ''' -------------------------------------------------------------------------------- /ex10_1.py: -------------------------------------------------------------------------------- 1 | def nested_sum(L): 2 | total = 0 # don't use `sum` as a variable name 3 | for i in L: 4 | if isinstance(i, list): # checks if `i` is a list 5 | total += nested_sum(i) 6 | else: 7 | total += i 8 | return total 9 | 10 | t = [[1,2], [3],[4,5,6]] 11 | print nested_sum(t) -------------------------------------------------------------------------------- /ex10_10.py: -------------------------------------------------------------------------------- 1 | import bisect as bs 2 | #import time #test 3 | # list need to be sorted first! 4 | if __name__ == '__main__': 5 | s = raw_input("What do yo wan to search? ") 6 | #s = "hey" 7 | #st = time.time() 8 | l = [] 9 | with open('words.txt', 'r') as fin: 10 | for line in fin: 11 | word = line.strip() 12 | l.append(word) 13 | print bs.bisect(l, s) #count start from 1 14 | #bs.bisect(l, s) 15 | #et = time.time() - st 16 | #print et -------------------------------------------------------------------------------- /ex10_11.py: -------------------------------------------------------------------------------- 1 | ''' #due to poor effiency I abort this method 2 | def find_reverse(l): 3 | ctr = 0 4 | for i in range(len(l)): 5 | for j in range(i+1, len(l)): 6 | if l[i] == l[j][::-1]: 7 | ctr += 1 8 | print (l[i], l[j]) 9 | return ctr 10 | 11 | if __name__ == '__main__': 12 | l = [] 13 | with open('words.txt', 'r') as fin: 14 | for line in fin: 15 | word = line.strip() 16 | l.append(word) 17 | print find_reverse(l) 18 | ''' 19 | import bisect as bs 20 | 21 | def exist_check(a, x): 22 | ''' 23 | Checks if a is in x. 24 | a: string 25 | x: list 26 | 27 | Returns: bool 28 | ''' 29 | #https://docs.python.org/2/library/bisect.html 30 | i = bs.bisect_left(a, x) 31 | if i != len(a) and a[i] == x: 32 | return True 33 | return False 34 | 35 | 36 | import time 37 | if __name__ == '__main__': 38 | l = [] 39 | ctr = 0 40 | st = time.time() 41 | with open('words.txt', 'r') as fin: 42 | for line in fin: 43 | word = line.strip() 44 | l.append(word) 45 | for i in l: 46 | if exist_check(l,i[::-1]): 47 | ctr += 1 48 | #print (i, i[::-1]) 49 | #This one is much faster than author's, I think it's because bisect module uses a better implementation. 50 | #The original time used: 71.5869998932 51 | #This method time used: 0.22100019455 52 | et = time.time() - st 53 | print ctr 54 | print et 55 | print len(l) 56 | 57 | 58 | -------------------------------------------------------------------------------- /ex10_12.py: -------------------------------------------------------------------------------- 1 | ''' 2 | I tried to writw something but found that I misunderstood the question (alternating) 3 | Then I looked up on Internet 4 | The result is amazing! 5 | Check this out:http://stackoverflow.com/questions/5523058/how-to-optimize-this-python-code-from-thinkpython-exercise-10-10 6 | 7 | ''' 8 | 9 | words = set(line.strip() for line in open("words.txt")) 10 | for w in words: 11 | even, odd = w[::2], w[1::2] 12 | if even in words and odd in words: 13 | print even, odd 14 | print "The word is %s" % (w) -------------------------------------------------------------------------------- /ex10_2.py: -------------------------------------------------------------------------------- 1 | def cumsum(l): 2 | total = 0 3 | for i in range(len(l)): 4 | total += l[i] 5 | l[i] = total 6 | return l 7 | 8 | t = [1, 2, 3] 9 | print cumsum(t) 10 | -------------------------------------------------------------------------------- /ex10_3.py: -------------------------------------------------------------------------------- 1 | def middle(l): 2 | return l[1:len(l)-1] 3 | 4 | t = [1, 2, 3, 4] 5 | print middle(t) -------------------------------------------------------------------------------- /ex10_4.py: -------------------------------------------------------------------------------- 1 | def chop(l): 2 | l.pop(0) 3 | l.pop() 4 | 5 | t = [1, 2, 3, 4] 6 | print chop(t) 7 | print t -------------------------------------------------------------------------------- /ex10_5.py: -------------------------------------------------------------------------------- 1 | def is_sorted(l): 2 | if len(l) == 1: 3 | return True 4 | else: 5 | if(l[0] > l[1]): 6 | return False 7 | return is_sorted(l[1:]) 8 | 9 | print is_sorted([1,2,2]) 10 | print is_sorted(['b','a']) -------------------------------------------------------------------------------- /ex10_6.py: -------------------------------------------------------------------------------- 1 | def is_anagram(a, b): 2 | for c in a: 3 | if c not in b: 4 | return False 5 | for c in b: 6 | if c not in a: 7 | return False 8 | return True 9 | 10 | print is_anagram("apple", "palpe") 11 | print is_anagram("applex", "palpe") -------------------------------------------------------------------------------- /ex10_7.py: -------------------------------------------------------------------------------- 1 | def has_duplicate(l): 2 | for i in range(len(l)): 3 | for j in range(i+1,len(l)): 4 | if l[i] == l[j]: 5 | return True 6 | return False 7 | 8 | print has_duplicate([1,2,3,4,5]) 9 | print has_duplicate([1,2,3,4,5,5]) -------------------------------------------------------------------------------- /ex10_8.py: -------------------------------------------------------------------------------- 1 | # using exclusive method as Wikipedia suggests 2 | 3 | from __future__ import division 4 | import math 5 | 6 | def p_cal(n): 7 | # probability calculator for n people (generalized) 8 | np_of_a = math.factorial(365) / math.factorial(365-n) / math.pow(365, n) 9 | return (1 - np_of_a) 10 | 11 | print p_cal(23) -------------------------------------------------------------------------------- /ex10_9.py: -------------------------------------------------------------------------------- 1 | def read_a(file): 2 | words = [] 3 | for i in file: 4 | words.append(i.strip()) 5 | return words 6 | 7 | def read_b(file): 8 | words = [] 9 | for i in file: 10 | words = words + [i.strip()] 11 | return words 12 | 13 | 14 | if __name__ == '__main__': 15 | with open('words.txt', 'r') as fin: 16 | print len(read_a(fin)) 17 | with open('words.txt', 'r') as fin2: 18 | print len(read_b(fin2)) #much slower -------------------------------------------------------------------------------- /ex11_1.py: -------------------------------------------------------------------------------- 1 | def get_dict(): 2 | l = [] 3 | fin = open("words.txt") 4 | for line in fin: 5 | word = line.strip() 6 | l.append(word) 7 | d = dict.fromkeys(l) 8 | return d 9 | 10 | def search_dict(d, s): 11 | if s in d: 12 | return True 13 | else: 14 | return False 15 | 16 | def search_list(l, s): 17 | if s in l: 18 | return True 19 | else: 20 | return False 21 | 22 | def make_word_list(): 23 | """Reads lines from a file and builds a list using append. 24 | 25 | returns: list of strings 26 | """ 27 | word_list = [] 28 | fin = open('words.txt') 29 | for line in fin: 30 | word = line.strip() 31 | word_list.append(word) 32 | return word_list 33 | 34 | #bisect is faster by about 0.032s, normal in using list is faster by 0.038 35 | 36 | import bisect as bs 37 | if __name__ == '__main__': 38 | 39 | d = get_dict() 40 | search_dict(d, "hey") 41 | -------------------------------------------------------------------------------- /ex11_2.py: -------------------------------------------------------------------------------- 1 | def histogram(s): 2 | d = dict() 3 | for c in s: 4 | if c not in d: 5 | d[c] = 1 6 | else: 7 | d[c] += 1 8 | return d 9 | 10 | def invert_dict(d): 11 | inverse = dict() 12 | for key in d: 13 | val = d[key] 14 | inverse.setdefault(val, []).append(key) # searched online to get this answer and it's same as the author's 15 | return inverse 16 | 17 | 18 | hist = histogram('parrot') 19 | print hist 20 | inverse = invert_dict(hist) 21 | print inverse -------------------------------------------------------------------------------- /ex11_3.py: -------------------------------------------------------------------------------- 1 | 2 | def ack(m, n): 3 | A = {} 4 | if m == 0: 5 | return n + 1 6 | elif m > 0 and n == 0: 7 | return ack(m-1, 1) 8 | else: 9 | A[m, n] = ack(m-1, ack(m, n-1) ) 10 | return A[m, n] 11 | 12 | print ack(3,4) 13 | print ack(3,6) 14 | #print A 15 | 16 | 17 | -------------------------------------------------------------------------------- /ex11_4.py: -------------------------------------------------------------------------------- 1 | def has_duplicate(l): 2 | d = {} 3 | for c in l: 4 | if c not in d: 5 | d[c] = 1 6 | else: 7 | return True 8 | return False 9 | 10 | print has_duplicate([1,2,3,4,5]) 11 | print has_duplicate([1,2,3,4,5,5]) 12 | 13 | 14 | '''In author's answer, there is a better solution''' 15 | 16 | def has_duplicate2(l): 17 | return len(set(l)) < len(l) # Sets are lists with no duplicate entries 18 | #http://stackoverflow.com/questions/3949310/how-is-set-implemented 19 | print '' 20 | print has_duplicate2([1,2,3,4,5]) 21 | print has_duplicate2([1,2,3,4,5,5]) 22 | -------------------------------------------------------------------------------- /ex11_5.py: -------------------------------------------------------------------------------- 1 | def rotate_letter(letter, n): 2 | """Rotates a letter by n places. Does not change other chars. 3 | 4 | letter: single-letter string 5 | n: int 6 | 7 | Returns: single-letter string 8 | """ 9 | if letter.isupper(): 10 | start = ord('A') 11 | elif letter.islower(): 12 | start = ord('a') 13 | else: 14 | return letter 15 | 16 | c = ord(letter) - start 17 | i = (c + n) % 26 + start 18 | return chr(i) 19 | 20 | 21 | def rotate_word(word, n): 22 | """Rotates a word by n places. 23 | 24 | word: string 25 | n: integer 26 | 27 | Returns: string 28 | """ 29 | res = '' 30 | for letter in word: 31 | res += rotate_letter(letter, n) 32 | return res 33 | 34 | import bisect as bs 35 | 36 | def exist_check(a, x): 37 | ''' 38 | Checks if a is in x. 39 | a: string 40 | x: list 41 | 42 | Returns: bool 43 | ''' 44 | #https://docs.python.org/2/library/bisect.html 45 | i = bs.bisect_left(a, x) 46 | if i != len(a) and a[i] == x: 47 | return True 48 | return False 49 | 50 | def rotate_pair(l): 51 | '''Returans a list containing all rotate pairs of a wordlist 52 | 53 | l: wordlist 54 | 55 | Returns: rotate_list 56 | ''' 57 | rl = {} 58 | for word in l: 59 | for num in range(1,14): 60 | if exist_check(l, rotate_word(word, num)): 61 | rl[word] = str(num) + rotate_word(word, num) 62 | return rl 63 | 64 | 65 | if __name__ == '__main__': 66 | 67 | with open('words.txt', 'r') as fin: 68 | words = [line.strip() for line in fin] 69 | print rotate_pair(words) 70 | 71 | -------------------------------------------------------------------------------- /ex11_6.py: -------------------------------------------------------------------------------- 1 | from pronounce import read_dictionary 2 | 3 | def hp_word(d): 4 | '''Prints all the homophone words as puzzle said 5 | 6 | d: given dictionary 7 | 8 | Returns: None 9 | ''' 10 | for word, sound in d.items(): 11 | word_cut = word[1:] 12 | word_sliced = word[0] + word[2:] 13 | if word_cut in d: 14 | if d[word] == d[word_cut]: 15 | if word_sliced in d: 16 | if d[word] == d[word_sliced]: 17 | if len(word) == 5: 18 | print word 19 | 20 | 21 | if __name__ == '__main__': 22 | d = read_dictionary() 23 | nd = hp_word(d) 24 | 25 | ''' 26 | I got answers: 27 | 28 | eerie 29 | llama 30 | llano 31 | llana 32 | scent 33 | ooohs 34 | lloyd 35 | aaron 36 | 37 | while in author's solution answers are: 38 | (which might not be correct because puzzle said the answer should be a five character word) 39 | llama lama lama 40 | llamas lamas lamas # this one is 6 char! 41 | scent cent sent 42 | 43 | But as long as you found _a_ word, then you solved the puzzle 44 | ''' -------------------------------------------------------------------------------- /ex12_1.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | def most_frequent(s): 4 | return collections.Counter(s).most_common() 5 | 6 | if __name__ == '__main__': 7 | # emma.txt is provided from author's code 8 | with open('emma.txt', 'r') as fin: 9 | string = fin.read() 10 | print most_frequent(string) -------------------------------------------------------------------------------- /ex12_1_v2.py: -------------------------------------------------------------------------------- 1 | #version 2 for exercise 1 in chapter 12 2 | 3 | def map_dict(s): 4 | ''' 5 | Returns a dictionary mapping each letter with corresponding frequency 6 | 7 | s: string 8 | 9 | ''' 10 | d = {} 11 | for i in s: 12 | d[i] = d.get(i, 0) + 1 13 | return d 14 | 15 | def most_frequent(s): 16 | ''' 17 | Sorts the letters in reverse order of frequence 18 | 19 | s: string 20 | 21 | Retruns a list of letters 22 | ''' 23 | d = map_dict(s) 24 | 25 | l = [] 26 | 27 | for x, f in d.items(): 28 | l.append((f,x)) 29 | 30 | l.sort(reverse = True) 31 | 32 | result = [] 33 | 34 | for f, x in l: 35 | result.append(x) 36 | 37 | return result 38 | 39 | 40 | 41 | if __name__ == '__main__': 42 | # emma.txt is provided from author's code 43 | with open('emma.txt', 'r') as fin: 44 | string = fin.read() 45 | print most_frequent(string) -------------------------------------------------------------------------------- /ex12_2.py: -------------------------------------------------------------------------------- 1 | '''http://stackoverflow.com/questions/8286554/using-python-find-anagrams-for-a-list-of-words 2 | 3 | # hughdbrown did an amazing job and I tried to understand his code and found this one is the better so far. 4 | ''' 5 | from collections import defaultdict 6 | 7 | def load_words(filename = "words.txt"): 8 | with open(filename) as f: 9 | for word in f: 10 | yield word.rstrip() # return a generator 11 | 12 | def all_anagram(l): 13 | '''Reads a list and return a set of anagram words 14 | 15 | l: list 16 | 17 | Returns: set 18 | ''' 19 | d = defaultdict(list) # avoid KeyError in dict() 20 | for word in l: 21 | signature = "".join(sorted(word)) #sorted: leave the original word untouched 22 | d[signature].append(word) 23 | return d 24 | 25 | def print_anagram(l): 26 | d = all_anagram(l) 27 | for key, anagram in d.iteritems(): 28 | if len(anagram) > 1: 29 | print (anagram) 30 | #print (key, anagram) 31 | 32 | def print_anagram_in_order(l): 33 | d = all_anagram(l) 34 | new_list = [] 35 | for v in d.values(): 36 | if len(v) > 1: 37 | new_list.append((len(v), v)) 38 | new_list.sort(reverse=True) # sort in descending order 39 | 40 | for x in new_list: 41 | print (x) 42 | 43 | 44 | 45 | if __name__ == '__main__': 46 | l = load_words() 47 | #print_anagram(l) 48 | print_anagram_in_order(l) 49 | -------------------------------------------------------------------------------- /ex12_2_v2.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | def load_words(filename = "words.txt"): 4 | with open(filename) as f: 5 | for word in f: 6 | yield word.rstrip() # return a generator 7 | 8 | def all_anagram(s): 9 | ''' 10 | s: string 11 | ''' 12 | d = defaultdict(list) 13 | for i in s: 14 | signature = ''.join(sorted(i)) # siganature is a after-sort string of chars in the word 15 | d[signature].append(i) 16 | 17 | return d 18 | 19 | def print_anagram_in_order(s): 20 | d = all_anagram(s) 21 | l = [] 22 | for signature, words in d.items(): 23 | if len(words) > 1: 24 | l.append((len(words),words)) 25 | l.sort(reverse=True) 26 | for x in l: 27 | print x 28 | 29 | def select_bingo(s, n=8): 30 | d = all_anagram(s) 31 | l = {} 32 | for signature, words in d.iteritems(): 33 | if len(words) > 1: 34 | if len(signature) == n: 35 | l[signature] = words 36 | res = [] 37 | for k, v in l.iteritems(): 38 | res.append((len(v),v)) 39 | 40 | for x in sorted(res, reverse=False): 41 | print x 42 | 43 | #print_anagram_in_order(load_words()) 44 | select_bingo(load_words()) -------------------------------------------------------------------------------- /ex12_3.py: -------------------------------------------------------------------------------- 1 | # mathesis pair 2 | # my idea: to start the pair of word need to be anagram (consist of all the same letter) 3 | # secondly only 1 char's position can be changed. 4 | 5 | 6 | ''' 7 | According to author's answer it is easier to find the distance between a pair of word! 8 | ''' 9 | from collections import defaultdict 10 | 11 | def load_words(filename = "words.txt"): 12 | with open(filename) as fin: 13 | for line in fin: 14 | yield line.rstrip() 15 | 16 | def all_anagram(s): 17 | ''' 18 | s: string 19 | ''' 20 | d = defaultdict(list) 21 | for i in s: 22 | signature = ''.join(sorted(i)) # siganature is a after-sort string of chars in the word 23 | d[signature].append(i) 24 | 25 | for k, v in d.items(): 26 | if len(v) == 1: 27 | del d[k] 28 | 29 | return d 30 | 31 | def pair_distance(a, b): 32 | # credit to http://www.greenteapress.com/thinkpython/code/metathesis.py 33 | assert len(a) == len(b) # if not equal raise AssertionError 34 | ctr = 0 35 | for c1, c2 in zip(a,b): # zip(a,b) returns a tuple for each corresponding char pair eg. "apple" & "paple" returns [('a', 'p'), ('p', 'a'), ('p', 'p'), ('l', 'l'), ('e', 'e')] 36 | if c1 != c2: 37 | ctr += 1 38 | return ctr 39 | 40 | def find_metathesis(s): 41 | d = all_anagram(s) 42 | for v in d.itervalues(): 43 | for a in v: 44 | for b in v: 45 | if a < b and pair_distance(a,b) == 2: 46 | print a, b 47 | 48 | find_metathesis(load_words()) -------------------------------------------------------------------------------- /ex12_4.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division 2 | ''' 3 | I misunderstodd what 'middle' mean in the question. I thought it was exactly the mid, however, in the hint and answer of author's the middle mean actually anywhere between the first and last char. So I rewrite my program to fit the problem. 4 | ''' 5 | # more on this 6 | ''' 7 | I used others' codes to test but found only when using memo can you improve performance significatnly, otherwise the process is really slow 8 | ''' 9 | 10 | from collections import defaultdict 11 | 12 | memo = {} 13 | memo[''] = [''] 14 | 15 | def child(word, d): 16 | res = [] 17 | for i in range(len(word)): 18 | child = word[:i] + word[i+1:] 19 | if child in d: 20 | res.append(child) 21 | return res 22 | 23 | def children(word, d): 24 | '''Gets the child of a string which is in the list 25 | ''' 26 | if word in memo: 27 | return memo[word] 28 | 29 | rest = [] 30 | for x in child(word, d): 31 | if children(x, d): #if list is not empty 32 | rest.append(x) 33 | 34 | memo[word] = rest 35 | return rest 36 | 37 | def all_children(d): 38 | res = [] 39 | for word in d: 40 | t = children(word, d) 41 | if t != []: 42 | res.append(word) 43 | return res 44 | 45 | def map_words(filename="words.txt"): 46 | d = defaultdict(list) 47 | with open(filename) as fin: 48 | for line in fin: 49 | word = line.strip().lower() 50 | d[word] = None 51 | 52 | for letter in ['a', 'i', '']: 53 | d[letter] = letter 54 | return d 55 | 56 | def print_trail(word, d): 57 | if len(word) == 0: 58 | return 59 | print(word, end =' ') 60 | t = children(word, d) 61 | print_trail(t[0], d) 62 | 63 | def print_longest(d): 64 | t = [] 65 | words = all_children(d) 66 | for word in words: 67 | t.append((len(word), word)) 68 | t.sort(reverse = True) 69 | 70 | for _,word in t[0:1]: #without _ underscore list index out of index 71 | print_trail(word, d) 72 | print('\n') 73 | ''' 74 | 75 | def list_of_words(filename="words.txt"): 76 | f = open(filename) 77 | l = [] 78 | for line in f: 79 | word = line.strip().lower() 80 | l.append(word) 81 | f.close() 82 | l.append('a') 83 | l.append('i') 84 | l.append('') 85 | return l 86 | ''' 87 | 88 | print_longest(map_words()) 89 | 90 | 91 | ''' 92 | !another thought: start from the smallest 'a', 'i', and to get the longest consequence. 93 | ''' -------------------------------------------------------------------------------- /ex13_1.py: -------------------------------------------------------------------------------- 1 | ''' 2 | I was first approach this problem by using translate function in python 2 according to:http://stackoverflow.com/questions/3900054/python-strip-multiple-characters 3 | 4 | but soon I switched to python 3 and found that advantage of using translate vanished due to unicode feature in python 3 according to: http://stackoverflow.com/questions/1450897/python-removing-characters-except-digits-from-string 5 | 6 | and my solution is based on one of answers in: 7 | http://stackoverflow.com/questions/10017147/removing-a-list-of-characters-in-string 8 | and I feel it is still quite fast 9 | ''' 10 | 11 | import string 12 | 13 | def read_file(filename): 14 | '''Reads a file and return stripped strings 15 | 16 | filename: str 17 | 18 | Returns a generator contains byte unicode? 19 | ''' 20 | remove_chars = list(string.punctuation + string.whitespace) 21 | with open(filename, encoding="utf8") as fin: 22 | for line in fin: 23 | if not line.strip().startswith('#'): 24 | for word in line.split(): 25 | yield word.translate({ord(x): '' for x in remove_chars}).lower().encode("utf-8") 26 | 27 | if __name__ == '__main__': 28 | print(list(read_file('words.txt'))) -------------------------------------------------------------------------------- /ex13_1_v2.py: -------------------------------------------------------------------------------- 1 | import string 2 | import collections 3 | 4 | def read_file(filename, skip_header=True): 5 | """Makes a histogram that contains the words from a file. 6 | **Rewrite the author's method for simplicity** 7 | 8 | filename: string 9 | skip_header: boolean, default=True 10 | 11 | returns: map from each word to the number of times it appears. 12 | """ 13 | hist = collections.Counter() 14 | 15 | with open(filename, encoding="utf8") as fin: 16 | #skip the header 17 | if skip_header: 18 | skip_gutenberg_header(fin) 19 | #update 20 | for line in fin: 21 | hist.update([word.strip(string.punctuation + string.whitespace).lower() for word in line.replace('-', ' ').split()]) 22 | 23 | return hist 24 | 25 | def skip_gutenberg_header(fp): 26 | """Reads from fp until it finds the line that ends the header. 27 | 28 | fp: open file object 29 | 30 | copied from author's answer 31 | """ 32 | for line in fp: 33 | if line.startswith('*END*THE SMALL PRINT!'): 34 | break 35 | 36 | if __name__ == '__main__': 37 | print(list(read_file('emma.txt'))) -------------------------------------------------------------------------------- /ex13_2.py: -------------------------------------------------------------------------------- 1 | from ex13_1 import * 2 | from collections import Counter 3 | # I have downloaded _Pride and Prejudice_ from Gutenberg website and modified header with '#' 4 | 5 | def count_number(l): 6 | c = Counter(l) 7 | print(c) #each word occurence 8 | #print(c.most_common(20)) #ex13_3 9 | 10 | if __name__ == '__main__': 11 | #print(list(read_file('PrideandPrejudice.txt'))) #check 12 | l = list(read_file('PrideandPrejudice.txt')) 13 | count_number(l) 14 | print("Total number of unique different words is: ", len(set(l))) 15 | print("Total number of words is:", len(l)) -------------------------------------------------------------------------------- /ex13_3.py: -------------------------------------------------------------------------------- 1 | from ex13_1 import * 2 | from ex13_2 import * 3 | 4 | from collections import Counter 5 | # I have downloaded _Pride and Prejudice_ from Gutenberg website and modified header with '#' 6 | 7 | def count_number_frequency(l): 8 | '''Print the 20 most frequently used words in the book''' 9 | c = Counter(l) 10 | print(c.most_common(20)) 11 | 12 | if __name__ == '__main__': 13 | #print(list(read_file('PrideandPrejudice.txt'))) #check 14 | l = list(read_file('PrideandPrejudice.txt')) 15 | count_number_frequency(l) 16 | print("Total number of unique different words is: ", len(set(l))) #8141 17 | print("Total number of words is:", len(l)) #124493 -------------------------------------------------------------------------------- /ex13_4.py: -------------------------------------------------------------------------------- 1 | '''I was wondering to use bisect search but still lack of effiency to tell wether a word is typo or should be included in the word list 2 | 3 | Besides, it will be a good practice to use a dict to store both word lists but I will just skip this one for now and read the answer 4 | 5 | (28/01/2017)Update: after reading author's answer, I found there are several things I ignored during process. For example, hyphens are not processed. But author does not even bother with translate at all. :/ 6 | ''' 7 | 8 | import string 9 | ''' 10 | another method for ex13_1,13_2,13_3 11 | ''' 12 | 13 | def load_word_as_dict(filename): 14 | '''Loads a file as a "memoized" dictionary mapping from word to frequency 15 | 16 | Return the dictionary 17 | ''' 18 | d = {} 19 | with open(filename, encoding='utf8') as fin: 20 | for line in fin: 21 | if not line.strip().startswith('#'): 22 | for word in line.split(): 23 | new_word = word.translate({ord(c): None for c in (string.punctuation + string.whitespace)}).lower().encode("utf-8") 24 | if new_word not in d: 25 | d[new_word] = 1 26 | else: 27 | d[new_word] += 1 28 | return d 29 | 30 | 31 | def check_word_in_book(wordlist, book_wordlist): 32 | #l = [] 33 | for word in book_wordlist.keys(): 34 | if word not in wordlist.keys(): 35 | print(word) 36 | #l.append(word) 37 | #print(len(l)) #2110 38 | 39 | if __name__ == '__main__': 40 | d1 = load_word_as_dict('words.txt') 41 | #for i in d1: 42 | # print(i, d1[i]) #test 43 | d2 = load_word_as_dict('PrideandPrejudice.txt') 44 | #for i in d2: 45 | # print(i, d2[i]) #test 46 | check_word_in_book(d1, d2) 47 | -------------------------------------------------------------------------------- /ex13_5.py: -------------------------------------------------------------------------------- 1 | '''This is Dex's solution to exercise 13_5 of Think Python ''' 2 | 3 | def choose_from_hist(hist): 4 | ''' 5 | Generate a hist list according to frequency 6 | then choose randomly one from the list 7 | WARN: this is low effiency 8 | ''' 9 | l = [] 10 | for key, value in hist.items(): 11 | l.extend([key] * value) #word needs to be inside a list 12 | return random.choice(l) 13 | 14 | 15 | 16 | import random 17 | from ex13_4 import * 18 | 19 | if __name__ == '__main__': 20 | hist = load_word_as_dict('words.txt') 21 | print(choose_from_hist(hist)) -------------------------------------------------------------------------------- /ex13_6.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Find a word in the book but not word list using set (data structure) 3 | ''' 4 | import string 5 | def read_file(filename): 6 | '''Reads a file and return stripped strings 7 | 8 | filename: str 9 | 10 | Returns a generator contains byte unicode? 11 | ''' 12 | remove_chars = list(string.punctuation + string.whitespace) 13 | with open(filename, encoding="utf8") as fin: 14 | for line in fin: 15 | if not line.strip().startswith('#'): 16 | for word in line.split(): 17 | yield word.translate({ord(x): '' for x in remove_chars}).lower().encode("utf-8") 18 | 19 | def subtraction(s1, s2): 20 | ''' 21 | in the s1 but not s2 22 | s1 - s2 23 | ''' 24 | return s1 - s2 25 | 26 | if __name__ == '__main__': 27 | s2 = set(read_file('words.txt')) 28 | s1 = set(read_file('PrideandPrejudice.txt')) 29 | print (subtraction(s1, s2)) 30 | print(len(subtraction(s1,s2))) -------------------------------------------------------------------------------- /ex13_7.py: -------------------------------------------------------------------------------- 1 | import string 2 | import sys 3 | import codecs 4 | from random import randint 5 | from bisect import bisect 6 | import collections 7 | 8 | def read_file(filename): 9 | '''adapted from author's answer 10 | Read a file and return histogram of frequency of every word 11 | ''' 12 | hist = collections.Counter() 13 | fp = open(filename, encoding="utf8") 14 | for line in fp: 15 | line = line.replace('-', ' ') # remove hyphens 16 | for word in line.split(): 17 | word = word.strip(string.punctuation + string.whitespace) #remove punctuation and whitespace 18 | word = word.lower() #lowercase all the chars 19 | hist[word] = hist.get(word, 0) + 1 #increment if word is already encountered once else set to 1 20 | return hist 21 | 22 | def cumsum(l): 23 | total = 0 24 | for i in range(len(l)): 25 | total += l[i] 26 | l[i] = total 27 | return l 28 | 29 | def choose_from_random(hist): 30 | l = list(hist.keys()) # get word list 31 | #print(repr(l)) 32 | cs = cumsum(list(int(i) for i in hist.values())) #cumulative sum of wordlist 33 | total = cs[-1] 34 | x = randint(0,total-1) 35 | index = bisect(cs, x) #TODO: understand bisect 36 | return l[index] 37 | 38 | if __name__ == '__main__': 39 | hist = read_file('emma.txt') #it is not working on 'PrideandPrejudice.txt' since there are different encoing schemes involved 40 | # TODO: learn encoding souce: http://stackoverflow.com/questions/14630288/unicodeencodeerror-charmap-codec-cant-encode-character-maps-to-undefined 41 | print(choose_from_random(hist)) 42 | -------------------------------------------------------------------------------- /ex13_8.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | from collections import defaultdict 4 | 5 | def read_and_analyze(filename, skip_header=True): 6 | '''Read a text file and perform Markov analysis. 7 | 8 | structure: dict[prefix] = suffix 9 | 10 | Returns a markov dict 11 | ''' 12 | d = defaultdict(list) 13 | with open(filename, encoding="utf8") as fin: 14 | if skip_header: 15 | skip_gutenberg_header(fin) 16 | 17 | for line in fin: 18 | line = line.replace('-', '') 19 | line_split = line.split() 20 | for i in range(0,len(line_split)-1): 21 | strippables = string.punctuation + string.whitespace 22 | word = line_split[i] 23 | word = word.strip(strippables).lower() 24 | # simple behavior with low effiency 25 | d[word].append(line_split[i+1]) 26 | # This method could have problem with next line 27 | return d 28 | 29 | def generate_random_content(d, prefix_len=2, text_len=50): 30 | '''Generate a random text based on a given markov dict 31 | 32 | Starts again if raised error 33 | ''' 34 | des = [] 35 | word_list = [] 36 | for word in list(d.keys()): 37 | if len(word) == prefix_len: 38 | word_list.append(word) 39 | first = random.choice(word_list) 40 | des.append(first) 41 | first_s = d[first] 42 | index2 = random.randint(0,len(first_s)-1) 43 | for i in range(text_len): 44 | previous = first_s[index2] 45 | sub = d[previous] 46 | random_index = random.randint(0,len(sub)-1) 47 | des.append(sub[random_index]) 48 | 49 | print(' '.join(des)) 50 | 51 | 52 | 53 | 54 | def skip_gutenberg_header(fp): 55 | """Reads from fp until it finds the line that ends the header. 56 | 57 | fp: open file object 58 | 59 | copied from author's answer 60 | """ 61 | for line in fp: 62 | if line.startswith('*END*THE SMALL PRINT!'): 63 | break 64 | 65 | def main(): 66 | 67 | d = read_and_analyze('emma.txt') 68 | #for prefix, suffix in d.items(): 69 | # print(prefix, suffix) 70 | print("Generating random text") 71 | generate_random_content(d) 72 | 73 | if __name__ == '__main__': 74 | main() -------------------------------------------------------------------------------- /ex13_9.py: -------------------------------------------------------------------------------- 1 | ''' 2 | TODO: draw the rank-frequency plot 3 | y = -s*x + b (y= logf, x=logr, b=logc)''' 4 | 5 | import string 6 | import collections 7 | 8 | def read_file(filename, skip_header=True): 9 | """Makes a histogram that contains the words from a file. 10 | **Rewrite the author's method for simplicity** 11 | 12 | filename: string 13 | skip_header: boolean, default=True 14 | 15 | returns: map from each word to the number of times it appears. 16 | """ 17 | hist = collections.Counter() 18 | 19 | with open(filename, encoding="utf8") as fin: 20 | #skip the header 21 | if skip_header: 22 | skip_gutenberg_header(fin) 23 | #update 24 | for line in fin: 25 | hist.update([word.strip(string.punctuation + string.whitespace).lower() for word in line.replace('-', ' ').split()]) 26 | 27 | return hist 28 | 29 | def skip_gutenberg_header(fp): 30 | """Reads from fp until it finds the line that ends the header. 31 | 32 | fp: open file object 33 | 34 | copied from author's answer 35 | """ 36 | for line in fp: 37 | if line.startswith('*END*THE SMALL PRINT!'): 38 | break 39 | 40 | def freq_and_rank(hist): 41 | freq = list(hist.values()) 42 | freq.sort(reverse=True) 43 | rank = 1 44 | for f in freq: 45 | yield rank, f 46 | rank += 1 47 | 48 | def main(): 49 | hist = read_file('emma.txt') 50 | for rank, freq in freq_and_rank(hist): 51 | print (rank, freq) 52 | 53 | 54 | if __name__ == '__main__': 55 | main() -------------------------------------------------------------------------------- /ex14_1.py: -------------------------------------------------------------------------------- 1 | from string import maketrans 2 | 3 | def sed(s, replace_string, input, output): 4 | fin = open(input, 'r') 5 | fout = open(output, 'w') 6 | 7 | trantab = maketrans(s, replace_string) # translate table 8 | 9 | 10 | for word in fin: 11 | re_word = word.translate(trantab) 12 | fout.write(re_word) 13 | 14 | fin.close() 15 | fout.close() 16 | 17 | 18 | if __name__ == '__main__': 19 | sed('p', 'q', 'test.txt', 'output.txt') #success with this one 20 | -------------------------------------------------------------------------------- /ex14_2.py: -------------------------------------------------------------------------------- 1 | ''' pickle is GREAT for this saving specified data structure task. 2 | ''' 3 | import pickle 4 | from collections import defaultdict 5 | 6 | def load_words(filename = "words.txt"): 7 | with open(filename) as f: 8 | for word in f: 9 | yield word.rstrip() # return a generator 10 | 11 | def all_anagram(l): 12 | '''Reads a list and return a set of anagram words 13 | 14 | l: list 15 | 16 | Returns: set 17 | ''' 18 | d = defaultdict(list) # avoid KeyError in dict() 19 | for word in l: 20 | signature = "".join(sorted(word)) #sorted: leave the original word untouched 21 | d[signature].append(word) 22 | 23 | for k, v in d.items(): #remove d[k] if there is only one value corresponding to the key which means there is no anagram for the word 24 | if len(v) == 1: 25 | del d[k] 26 | 27 | return d 28 | 29 | def save_dict(d): 30 | with open('shelf.pkl', 'wb') as f: #wb for write byte 31 | pickle.dump(d, f, pickle.HIGHEST_PROTOCOL) 32 | 33 | def look_up_dict(word): 34 | #look up a word and return its anagram in the 'shelf' 35 | with open('shelf.pkl', 'rb') as f: #rb for read byte 36 | d = pickle.load(f) 37 | for k, v in d.iteritems(): 38 | for i in v: 39 | if i == word: 40 | return v 41 | 42 | if __name__ == '__main__': 43 | books = all_anagram(load_words()) 44 | save_dict(books) 45 | print '' 46 | print look_up_dict('tired') 47 | print look_up_dict('cosets') -------------------------------------------------------------------------------- /ex14_3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | 4 | import os 5 | import glob #The glob module finds all the pathnames matching a specified pattern according to the rules used by the Unix shell, although results are returned in arbitrary order. No tilde expansion is done, but *, ?, and character ranges expressed with [] will be correctly matched. 6 | 7 | # The author asked to write a md5sum check to find duplicate without providing anymore information. It is interesting to learn how md5sum actually works. So for reference: https://en.wikipedia.org/wiki/Md5sum 8 | import hashlib 9 | import itertools 10 | 11 | #following code is copied from http://stackoverflow.com/questions/3431825/generating-an-md5-checksum-of-a-file 12 | def md5(fname): 13 | hash_md5 = hashlib.md5() 14 | with open(fname, "rb") as f: 15 | for chunk in iter(lambda: f.read(4096), b""): 16 | hash_md5.update(chunk) 17 | return hash_md5.hexdigest() 18 | 19 | def main(): 20 | d = {} 21 | rev_d = {} 22 | for filename in glob.glob('./**/*.py',recursive = True): 23 | print(os.path.abspath(filename)) 24 | print(md5(os.path.abspath(filename))) 25 | d[filename] = md5(os.path.abspath(filename)) 26 | 27 | for k, v in d.items(): 28 | rev_d.setdefault(v, set()).add(k) 29 | print ("Are there any duplicate files?") 30 | ''' 31 | for k, v in rev_d.items(): 32 | if len(v) > 1: 33 | print ("Yes, and they are:") 34 | print (v) 35 | ''' 36 | print(set(itertools. chain.from_iterable(values for key, values in rev_d.items() if len(values) > 1))) 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /ex15_1.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | '''Represents a point in 2-D space.''' 3 | def print_point(p): 4 | print( '(%g, %g)' % (p.x, p.y) ) 5 | 6 | def distance_between_points(p1, p2): 7 | distance = math.sqrt( (p1.x - p2.x)**2 + (p1.y - p2.y)**2 ) 8 | return distance 9 | 10 | class Rectangle: 11 | '''Represents a rectangle 12 | 13 | Attributes: width, height, corner. 14 | ''' 15 | 16 | def find_center(rect): 17 | p = Point() 18 | p.x = rect.corner.x + rect.width/2 19 | p.y = rect.corner.y + rect.height/2 20 | return p 21 | 22 | def move_rectangle(rect, dx, dy): 23 | '''Creates and returns a new rectangle 24 | 25 | ''' 26 | rect_new = copy.deepcopy(rect) #not only copy the object but also the references it contains 27 | rect_new.corner.x += dx 28 | rect_new.corner.y += dy 29 | 30 | class Circle: 31 | '''Represents a circle. 32 | 33 | Attributes: center, radius 34 | ''' 35 | 36 | def point_in_circle(crc, pt): 37 | d = distance_between_points(crc.center, pt) 38 | print(d) 39 | return d <= crc.radius 40 | 41 | def rect_in_circle(crc, rect): 42 | d = distance_between_points(crc.center, rect.corner) 43 | return d <= crc.radius 44 | 45 | def rect_circle_overlap(crc, rect): 46 | #reference: http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection 47 | rect_center = find_center(rect) 48 | d_center = Point() 49 | d_center.x = abs(rect_center.x - crc.center.x) 50 | d_center.y = abs(rect_center.y - crc.center.y) 51 | 52 | if(d_center.x > (rect.width/2 + crc.radius)): 53 | return False 54 | if(d_center.y > (rect.height/2 + crc.radius)): 55 | return False 56 | if(d_center.x <= (rect.width/2)): 57 | return True 58 | if(d_center.y <= (rect.height/2)): 59 | return True 60 | #check whether the corner of rectangle is inside the circle 61 | cornerDistance_sq = (d_center.x - rect.width/2) **2 + (d_center.y - rect.height/2) **2 62 | 63 | return cornerDistance_sq <= (crc.radius ** 2) 64 | 65 | 66 | import math 67 | import copy 68 | if __name__ == '__main__': 69 | 70 | 71 | bob = Rectangle() 72 | bob.width = 100.0 73 | bob.height = 200.0 74 | bob.corner = Point() 75 | bob.corner.x = 50.0 76 | bob.corner.y = 50.0 77 | 78 | print_point(find_center(bob)) 79 | crc = Circle() 80 | crc.center = Point() 81 | crc.center.x = 150.0 82 | crc.center.y = 100.0 83 | crc.radius = 75.0 84 | print(point_in_circle(crc, bob.corner)) 85 | print(rect_in_circle(crc, bob)) 86 | print(rect_circle_overlap(crc,bob)) -------------------------------------------------------------------------------- /ex15_1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/ex15_1.pyc -------------------------------------------------------------------------------- /ex15_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | class Rectangle: 4 | '''Represents a rectangle 5 | 6 | Attributes: width, height, corner. 7 | ''' 8 | 9 | class Point: 10 | '''Represents a point in 2-D space.''' 11 | 12 | class Circle: 13 | '''Represents a circle. 14 | 15 | Attributes: center, radius 16 | ''' 17 | 18 | import math 19 | # for turtle reference, see: https://docs.python.org/2/library/turtle.html#turtle.setheading 20 | import turtle 21 | from ex15_1 import * 22 | 23 | def draw_rect(t, rect): 24 | t.pu() 25 | t.setx(rect.corner.x) # set x cordinate 26 | t.sety(rect.corner.y) # set y cordinate 27 | print(t.position()) 28 | 29 | t.seth(0) # set heading to east 30 | t.pd() # put pen down 31 | t.fd(rect.width) 32 | print(t.position()) 33 | 34 | t.seth(90) 35 | t.fd(rect.height) 36 | print(t.position()) 37 | t.seth(180) 38 | t.fd(rect.width) 39 | print(t.position()) 40 | t.seth(270) 41 | t.fd(rect.height) 42 | 43 | 44 | 45 | def draw_circle(t, crc): 46 | # given center find a point on circle 47 | t.pu() 48 | t.setx(crc.center.x) 49 | t.sety(crc.center.y) 50 | t.fd(crc.radius) 51 | print(t.position()) 52 | t.lt(90) 53 | t.pd() 54 | t.circle(crc.radius) 55 | 56 | 57 | if __name__ == '__main__': 58 | bob = turtle.Turtle() 59 | 60 | bob.delay = 0.001 61 | 62 | 63 | 64 | rect = Rectangle() 65 | rect.height = 100.0 66 | rect.width = 200.0 67 | rect.corner = Point() 68 | rect.corner.x = 50.0 69 | rect.corner.y = 80.0 70 | 71 | 72 | # draw a circle 73 | crc = Circle() 74 | crc.center = Point() 75 | crc.center.x = 150.0 76 | crc.center.y = 10.0 77 | crc.radius = 75.0 78 | 79 | draw_rect(bob, rect) 80 | draw_circle(bob, crc) 81 | print("are there any overlap") 82 | print(rect_circle_overlap(crc, rect)) 83 | 84 | # wait for the user to close the window 85 | turtle.mainloop() -------------------------------------------------------------------------------- /ex16_1.py: -------------------------------------------------------------------------------- 1 | from ch16_ex import * 2 | 3 | def mul_time(t, n): 4 | ''' the same as in ch16_ex ''' 5 | return int_to_time(time_to_int(t) * n) 6 | 7 | def average_pace(t, delta_x): 8 | ''' Represents average pace in a race 9 | t: finishing time 10 | delta_x: movement during race 11 | unit : time per mile ''' 12 | return int_to_time(time_to_int(t) / delta_x ) 13 | 14 | 15 | 16 | if __name__ == '__main__': 17 | t = Time() 18 | t.hour = 3 19 | t.minute = 30 20 | t.second = 30 21 | print_time(mul_time(t, 3)) 22 | print_time(average_pace(t,30)) -------------------------------------------------------------------------------- /ex16_2.py: -------------------------------------------------------------------------------- 1 | import time 2 | from datetime import date, time, datetime, timedelta 3 | from dateutil.relativedelta import relativedelta 4 | 5 | def current_day(): 6 | return (date.strftime(date.today(), "%A")) #strftime = string format time 7 | 8 | def ObtainDate(): 9 | while True: 10 | usrIn = input("Give a date in the format of yyyy-mm-dd: ") 11 | try: 12 | return datetime.strptime(usrIn, "%Y-%m-%d") # strptime = string parse time 13 | except ValueError: 14 | print ("Invalid format!\n") 15 | 16 | def usr_info(birthday): 17 | '''Takes a birthday as input and prints the user's age and the number of days, hours, minutes and seconds until their next birthday 18 | 19 | birthday: yyyy-MM-dd %Y-%m-%d 20 | ''' 21 | today = datetime.today() 22 | print ("Your age is: %d" % relativedelta(today, birthday).years) 23 | #print ("Your age is: %d" % (today.year - birthday.year - ((today.month, today.day) < (birthday.month, birthday.day)))) #second way of writing 24 | next_birthday = birthday.replace(year=today.year) 25 | if next_birthday < today: 26 | next_birthday = birthday.replace(year=today.year + 1) 27 | duration = next_birthday - today 28 | print ("Time until your next birthday is: ", duration.days, " days.") 29 | 30 | def double_day(bday1, bday2): 31 | ''' The author wrote "For two people born on different days, there is a day when one is twice as old as the other. That’s their Double Day." 32 | But I do not know what does author mean by double day at all. So I looked up the answer and got the idea that double day is actually when the difference between birthday of first dude and second dude doubles. But I wonder if there are any meaning to calculate this. 33 | source: https://github.com/AllenDowney/ThinkPython2/blob/master/code/double.py 34 | 35 | update: okay, I understand it now after testing. It basically means that older dude lives twice amount of days than younger dude 36 | ''' 37 | old_dude = min(bday1, bday2) 38 | young_dude = max(bday1, bday2) 39 | delta = young_dude + (young_dude - old_dude) 40 | return delta #return a timedelta object when old_dude lives twice amount of days as younger dude 41 | 42 | 43 | def n_day(bd1, bd2, n): 44 | '''A general version of double_day which computes the day when one person is n times older than the other. 45 | 46 | Return: timedelta 47 | ''' 48 | old_dude = min(bd1, bd2) 49 | young_dude = max(bd1, bd2) 50 | delta = young_dude + n * (young_dude - old_dude) 51 | return delta 52 | 53 | if __name__ == '__main__': 54 | print (date.today()) 55 | print (current_day()) 56 | birthday = ObtainDate() 57 | usr_info(birthday) 58 | # two day before I was born 59 | rday = datetime(1995, 12, 21) 60 | print("Double day is: ", double_day(rday, birthday)) 61 | print("Ten times day is: ", n_day(rday, birthday, 10)) 62 | -------------------------------------------------------------------------------- /ex17_1.py: -------------------------------------------------------------------------------- 1 | '''following code are adapted from http://greenteapress.com/thinkpython2/code/Time2.py''' 2 | from __future__ import print_function, division 3 | 4 | class Time: 5 | '''Change the attributes of Time to be a single integer representing seconds since midnight 6 | 7 | attributes: seconds 8 | ''' 9 | 10 | def __init__(self, hour=0, minute=0, second=0): 11 | minutes = hour * 60 + minute 12 | self.seconds = minutes * 60 + second 13 | 14 | def __str__(self): 15 | minutes, second = divmod(self.seconds, 60) 16 | hour, minute = divmod(minutes, 60) 17 | return '%.2d:%.2d:%.2d' % (hour, minute, second) 18 | 19 | def __lt__(self, other): 20 | t1 = self.seconds 21 | t2 = other.seconds 22 | return t1 < t2 23 | 24 | def print_time(self): 25 | """Prints a string representation of the time.""" 26 | print(str(self)) 27 | 28 | def time_to_int(self): 29 | """Computes the number of seconds since midnight.""" 30 | return self.seconds 31 | 32 | def is_after(self, other): 33 | """Returns True if t1 is after t2; false otherwise.""" 34 | return self.time_to_int() > other.time_to_int() 35 | 36 | def __add__(self, other): 37 | """Adds two Time objects or a Time object and a number. 38 | 39 | other: Time object or number of seconds 40 | """ 41 | if isinstance(other, Time): 42 | return self.add_time(other) 43 | else: 44 | return self.increment(other) 45 | 46 | def __radd__(self, other): 47 | """Adds two Time objects or a Time object and a number.""" 48 | return self.__add__(other) 49 | 50 | def add_time(self, other): 51 | """Adds two time objects.""" 52 | assert self.is_valid() and other.is_valid() 53 | seconds = self.time_to_int() + other.time_to_int() 54 | return int_to_time(seconds) 55 | 56 | def increment(self, seconds): 57 | """Returns a new Time that is the sum of this time and seconds.""" 58 | seconds += self.time_to_int() 59 | return int_to_time(seconds) 60 | 61 | def is_valid(self): 62 | minutes, second = divmod(self.seconds, 60) 63 | hour, minute = divmod(minutes, 60) 64 | if hour < 0 or minute < 0 or second < 0: 65 | return False 66 | if minute >= 60 or second >= 60: 67 | return False 68 | return True 69 | 70 | def int_to_time(seconds): 71 | return Time(0,0,seconds) 72 | 73 | '''belowing code not changed''' 74 | def main(): 75 | start = Time(9, 45, 00) 76 | start.print_time() 77 | 78 | end = start.increment(1337) 79 | #end = start.increment(1337, 460) 80 | end.print_time() 81 | 82 | print('Is end after start?') 83 | print(end.is_after(start)) 84 | 85 | print('Using __str__') 86 | print(start, end) 87 | 88 | start = Time(9, 45) 89 | duration = Time(1, 35) 90 | print(start + duration) 91 | print(start + 1337) 92 | print(1337 + start) 93 | 94 | print('Example of polymorphism') 95 | t1 = Time(7, 43) 96 | t2 = Time(7, 41) 97 | t3 = Time(7, 37) 98 | total = sum([t1, t2, t3]) 99 | print(total) 100 | print(t1 < t2) 101 | print(t3 < t2) 102 | 103 | if __name__ == '__main__': 104 | main() -------------------------------------------------------------------------------- /ex17_2.py: -------------------------------------------------------------------------------- 1 | class Kangroo: 2 | ''' 3 | 4 | attributes: pouch_contents 5 | ''' 6 | 7 | def __init__(self, pouch_contents): 8 | l = [] 9 | l.append(pouch_contents) 10 | self.pouch_contents = l 11 | 12 | def put_in_pouch(self,obj): 13 | self.pouch_contents.append(obj) 14 | 15 | 16 | def __str__(self): 17 | return '%s' % (''.join(str(x) for x in self.pouch_contents)) 18 | 19 | if __name__ == '__main__': 20 | a = Kangroo('kanga') 21 | b = Kangroo('roo') 22 | a.put_in_pouch(b) 23 | print(a) 24 | print(b) -------------------------------------------------------------------------------- /ex18_1.py: -------------------------------------------------------------------------------- 1 | PingPongParent --> Ping 2 | PingPongParent --> Pong -------------------------------------------------------------------------------- /ex18_2.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | class Card: 4 | ''' class represents suit of cars, encoding with numbers 5 | 6 | Attributes: 7 | suit; 8 | rank; 9 | 10 | sapdes -> 3 11 | hearts -> 2 12 | diamonds -> 1 13 | clubs -> 0 14 | 15 | jack -> 11 16 | queen -> 12 17 | king -> 13 18 | 19 | 20 | ''' 21 | # Attribute 22 | suit_names = ['Clubs', 'Diamonds', 'Hearts', 'Spades'] 23 | rank_names = [None, 'Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King'] 24 | 25 | def __init__(self, suit=0, rank=2): 26 | self.suit = suit 27 | self.rank = rank 28 | 29 | def __str__(self): 30 | return '%s of %s' % (Card.rank_names[self.rank], Card.suit_names[self.suit]) 31 | 32 | def __lt__(self, other): 33 | # first compare suit 34 | if self.suit < other.suit: return True 35 | if self.suit > other.suit: return False 36 | 37 | # if suit is the same then compare rank 38 | return self.rank < other.rank 39 | 40 | 41 | class Deck: 42 | '''class represents deck 43 | 44 | Attributes: 45 | cards: list 46 | ''' 47 | 48 | def __init__(self): 49 | self.cards = [] 50 | for suit in range(4): 51 | for rank in range(1, 14): 52 | card = Card(suit, rank) 53 | self.cards.append(card) 54 | 55 | def __str__(self): 56 | res = [] 57 | for card in self.cards: 58 | res.append(str(card)) 59 | return '\n'.join(res) 60 | 61 | def pop_card(self): 62 | '''remove the last card from the deck''' 63 | return self.cards.pop() 64 | 65 | def add_card(self, card): 66 | ''' add a card to the last position of deck (using veneer methods)''' 67 | self.cards.append(card) 68 | 69 | def shuffle(self): 70 | '''shuffle the deck randomly''' 71 | random.shuffle(self.cards) 72 | 73 | def sort(self): 74 | '''sort the deck in descending ordoer''' 75 | self.cards.sort() 76 | 77 | def move_card(self, hand, num): 78 | '''move card(s) to another Hand or Deck''' 79 | for i in range(num): 80 | hand.add_card(self.pop_card()) 81 | 82 | def deal_hands(self, num_of_hands, num_of_cards_per_hand): 83 | '''deal hands 84 | 85 | num_of_hands: int 86 | num_of_cards_per_hand: list 87 | 88 | ''' 89 | hand_list = [] 90 | for i in range(num_of_hands): 91 | h = Hand("Hand No. %d" % i) 92 | self.move_card(h, num_of_cards_per_hand) 93 | hand_list.append(h) 94 | return hand_list 95 | 96 | 97 | class Hand(Deck): 98 | '''class represents cards on hand, inherited from deck ''' 99 | 100 | def __init__(self, label=''): 101 | '''initialize cards on hand, and label which hand is using''' 102 | self.cards = [] 103 | self.label = label 104 | 105 | if __name__ == '__main__': 106 | king_of_spades = Card(3, 13) # test 107 | print(king_of_spades) 108 | d = Deck() #test 109 | print('\n---initial result---') 110 | print(d) 111 | d.shuffle() 112 | print('\n---shuffle result---') 113 | print(d) 114 | d.sort() 115 | print('\n---sort result---') 116 | print(d) 117 | print('\n---deal_hand test result---') 118 | li = d.deal_hands(5,4) 119 | for h in li: 120 | print (h.label) 121 | print (h) 122 | -------------------------------------------------------------------------------- /ex18_3.py: -------------------------------------------------------------------------------- 1 | """Adapeted from Think Python website 2 | 3 | Copyright 2017 Dex D. Hunter 4 | 5 | License: http://creativecommons.org/licenses/by/4.0/ 6 | """ 7 | 8 | from __future__ import print_function, division 9 | 10 | from Card import Hand, Deck 11 | 12 | 13 | class PokerHand(Hand): 14 | """Represents a poker hand. 15 | 16 | Inherited from Hand 17 | """ 18 | 19 | def suit_hist(self): 20 | """Builds a histogram of the suits that appear in the hand. 21 | 22 | Stores the result in attribute suits. 23 | """ 24 | self.suits = {} 25 | for card in self.cards: 26 | self.suits[card.suit] = self.suits.get(card.suit, 0) + 1 27 | print(self.suits) 28 | 29 | def rank_hist(self): 30 | """Builds a histogram of the rank that appear in the hand. 31 | 32 | Stores the result in attribute rank. 33 | """ 34 | self.ranks = {} 35 | for card in self.cards: 36 | self.ranks[card.rank] = self.ranks.get(card.rank, 0) + 1 37 | print(self.ranks) 38 | 39 | def has_flush(self): 40 | """Returns True if the hand has a flush, False otherwise. 41 | 42 | Note that this works correctly for hands with more than 5 cards. 43 | 44 | flush: 5 cards with the same suit 45 | """ 46 | self.suit_hist() 47 | for val in self.suits.values(): 48 | if val >= 5: 49 | return True 50 | return False 51 | 52 | def has_pair(self, other): 53 | '''pair: two cards with the same rank''' 54 | self.rank_hist() 55 | for val in self.ranks.values(): 56 | if val >= 2: 57 | return True 58 | return False 59 | 60 | 61 | def has_twopair(self): 62 | ''' has two pairs of cards with the same rank ''' 63 | self.rank_hist() 64 | count = 0 65 | for val in self.ranks.values(): 66 | if val >= 2: 67 | count += 1 68 | 69 | if count >=2: 70 | return True 71 | return False 72 | 73 | def classify(self): 74 | ''' 75 | straight: five cards with ranks in sequence 76 | 77 | flush: five cards with the same suit 78 | ''' 79 | label = ['pair', 'two pair', 'three of a kind', 'striaght', 'flush', 'full house', 'four of a kind', 'straight flush'] 80 | 81 | 82 | 83 | if __name__ == '__main__': 84 | # make a deck 85 | deck = Deck() 86 | deck.shuffle() 87 | 88 | # deal the cards and classify the hands 89 | h = PokerHand() 90 | deck.move_cards(h, 10) 91 | h.suit_hist() 92 | print(h) 93 | ''' 94 | for i in range(7): 95 | hand = PokerHand() 96 | deck.move_cards(hand, 7) 97 | hand.suit_hist 98 | hand.sort() 99 | print(hand) 100 | print(hand.has_flush()) 101 | print('') 102 | ''' -------------------------------------------------------------------------------- /ex19_1.py: -------------------------------------------------------------------------------- 1 | def binomial_coeff(n, k): 2 | '''Compute the binomial coefficient 3 | 4 | n: number of trials 5 | k: number of successes 6 | 7 | returns: int 8 | ''' 9 | if k==0: 10 | return 1 11 | if n==0: 12 | return 0 13 | 14 | res = binomial_coeff(n-1, k) + binomial_coeff(n-1, k-1) 15 | return res 16 | 17 | 18 | def b(n,k): 19 | '''rewrite the function in a compact way 20 | I failed to rewrite in conditional expression. :/ 21 | But this is the end of the course so meh. never mind 22 | ''' 23 | 24 | memo = {} 25 | if (n,k) in memo: 26 | return memo[(n,k)] 27 | if k==0: 28 | return 1 29 | if n==0: 30 | return 0 31 | 32 | r = b(n-1, k) + b(n-1, k-1) 33 | memo[(n,k)] = r 34 | return r 35 | 36 | if __name__ == '__main__': 37 | a = binomial_coeff(3,4) 38 | # b(3,4) = b(2, 4) + b(2,3) 39 | # b(2,4) = b(1,4) + b(1,3) 40 | # b(1,4) = b(0,4) + b(0,3) = 0 + 0 = 0 41 | # b(1,3) = b(0,3) + b(0,2) = 0 + 0 = 0 42 | # b(2,3) = b(1,3) + b(1,2) 43 | # b(1,2) = b(0,2) + b(0,1) = 0 + 0 = 0 44 | print(a) 45 | print(b(3,4)) 46 | c = binomial_coeff(10,4) 47 | print(c) 48 | print(b(10,4)) -------------------------------------------------------------------------------- /ex21_1.py: -------------------------------------------------------------------------------- 1 | ''' 2 | #Answering questions 3 | 4 | # 1. What is the order of growth of n^3 + n^2? What about 1000000*n^3 + n^2? What about n^3 + 1000000 * n^2? 5 | 6 | Ans: The answer is cubic, O(x^3). When n approaches infinite, the constant and n^2 does not matter 7 | 8 | # 2. What is the order of growth of n2 + n · n + 1 ? Before you start multiplying, remember that you only need the leading term. 9 | 10 | Ans: cubic, O(x^3) 11 | 12 | 3. If f is in O(g), for some unspecified function g , what can we say about af+b? 13 | 14 | Ans: If a is constant, I think the answer should be same as O(g) 15 | 16 | 4. If f1 and f2 are in O(g), what can we say about f1 + f2? 17 | 18 | 19 | Ans: 20 | 21 | 5. If f1 is in O(g) and f2 is in O(h), what can we say about f1 + f2? 22 | 23 | 6. If f1 is in O(g) and f2 is in O(h), what can we say about f1 * f2? 24 | 25 | 26 | 27 | 28 | 29 | ''' -------------------------------------------------------------------------------- /ex21_2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1. What is a "comparison sort"? What is the best worst-case order of growth for a comparison sort? What is the best worst-case order of growth for any sort algorithm? 3 | 4 | Ans: All comparison sorts has a property that the sorting order it determined is based only on the comprisons between the input elements. (b) The best scenario is O(nlogn) (c) For radix sort, the order of growth is 5 | 6 | 7 | 2. What is the order of growth of bubble sort, and does Barack Obama think it is "the wrong way to go"? 8 | 9 | 10 | Ans: The asymptotic complexity of bubble sort is O(n^2) 11 | 12 | 13 | 3. What is a stable sort and why might it matter in practice? 14 | 15 | 16 | 4. What is a stable sort and why might it matter in practice? 17 | 18 | 19 | 5. What is the worst sorting algorithm (that has a name)? 20 | 21 | 6. What sort algorithm does the C library use? What sort algorithm does Python use? Are these algorithms stable? 22 | 23 | 7. Many of the non-comparison sorts are linear, so why does Python use an O(nlogn) comparison sort? 24 | 25 | ''' -------------------------------------------------------------------------------- /inlist.py: -------------------------------------------------------------------------------- 1 | """This module contains a code example related to 2 | 3 | Think Python, 2nd Edition 4 | by Allen Downey 5 | http://thinkpython2.com 6 | 7 | Copyright 2015 Allen Downey 8 | 9 | License: http://creativecommons.org/licenses/by/4.0/ 10 | """ 11 | 12 | from __future__ import print_function, division 13 | 14 | import bisect 15 | 16 | 17 | def make_word_list(): 18 | """Reads lines from a file and builds a list using append. 19 | 20 | returns: list of strings 21 | """ 22 | word_list = [] 23 | fin = open('words.txt') 24 | for line in fin: 25 | word = line.strip() 26 | word_list.append(word) 27 | return word_list 28 | 29 | 30 | def in_bisect(word_list, word): 31 | """Checks whether a word is in a list using bisection search. 32 | 33 | Precondition: the words in the list are sorted 34 | 35 | word_list: list of strings 36 | word: string 37 | """ 38 | if len(word_list) == 0: 39 | return False 40 | 41 | i = len(word_list) // 2 42 | if word_list[i] == word: 43 | return True 44 | 45 | if word_list[i] > word: 46 | # search the first half 47 | return in_bisect(word_list[:i], word) 48 | else: 49 | # search the second half 50 | return in_bisect(word_list[i+1:], word) 51 | 52 | 53 | def in_bisect_cheat(word_list, word): 54 | """Checks whether a word is in a list using bisection search. 55 | 56 | Precondition: the words in the list are sorted 57 | 58 | word_list: list of strings 59 | word: string 60 | """ 61 | i = bisect.bisect_left(word_list, word) 62 | if i == len(word_list): 63 | return False 64 | 65 | return word_list[i] == word 66 | 67 | 68 | if __name__ == '__main__': 69 | word_list = make_word_list() 70 | 71 | for word in ['aa', 'alien', 'allen', 'zymurgy']: 72 | print(word, 'in list', in_bisect(word_list, word)) 73 | 74 | for word in ['aa', 'alien', 'allen', 'zymurgy']: 75 | print(word, 'in list', in_bisect_cheat(word_list, word)) 76 | 77 | -------------------------------------------------------------------------------- /inlist.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/inlist.pyc -------------------------------------------------------------------------------- /letters.py: -------------------------------------------------------------------------------- 1 | """This module contains code from 2 | Think Python by Allen B. Downey 3 | http://thinkpython.com 4 | 5 | Copyright 2012 Allen B. Downey 6 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 7 | 8 | """ 9 | 10 | from swampy.TurtleWorld import * 11 | 12 | from polygon import circle, arc 13 | 14 | # LEVEL 0 PRIMITIVES are provided by World.py. 15 | # They include fd, bk, lt, rt, pu and pd 16 | 17 | 18 | # LEVEL 1 PRIMITIVES are simple combinations of Level 0 primitives. 19 | # They have no pre- or post-conditions. 20 | 21 | def fdlt(t, n, angle=90): 22 | """forward and left""" 23 | fd(t, n) 24 | lt(t, angle) 25 | 26 | def fdbk(t, n): 27 | """forward and back, ending at the original position""" 28 | fd(t, n) 29 | bk(t, n) 30 | 31 | def skip(t, n): 32 | """lift the pen and move""" 33 | pu(t) 34 | fd(t, n) 35 | pd(t) 36 | 37 | def stump(t, n, angle=90): 38 | """make a vertical line and leave the turtle at the top, facing right""" 39 | lt(t) 40 | fd(t, n) 41 | rt(t, angle) 42 | 43 | def hollow(t, n): 44 | """move the turtle vertically and leave it at the top, facing right""" 45 | lt(t) 46 | skip(t, n) 47 | rt(t) 48 | 49 | 50 | # LEVEL 2 PRIMITIVES use primitives from Levels 0 and 1 51 | # to draw posts (vertical elements) and beams (horizontal elements) 52 | # Level 2 primitives ALWAYS return the turtle to the original 53 | # location and direction. 54 | 55 | def post(t, n): 56 | """make a vertical line and return to the original position""" 57 | lt(t) 58 | fdbk(t, n) 59 | rt(t) 60 | 61 | def beam(t, n, height): 62 | """make a horizontal line at the given height and return.""" 63 | hollow(t, n*height) 64 | fdbk(t, n) 65 | hollow(t, -n*height) 66 | 67 | 68 | def hangman(t, n, height): 69 | """make a vertical line to the given height and a horizontal line 70 | at the given height and then return. 71 | This is efficient to implement, and turns out to be useful, but 72 | it's not so semantically clean.""" 73 | stump(t, n * height) 74 | fdbk(t, n) 75 | lt(t) 76 | bk(t, n*height) 77 | rt(t) 78 | 79 | def diagonal(t, x, y): 80 | """make a diagonal line to the given x, y offsets and return""" 81 | from math import atan2, sqrt, pi 82 | angle = atan2(y, x) * 180 / pi 83 | dist = sqrt(x**2 + y**2) 84 | lt(t, angle) 85 | fdbk(t, dist) 86 | rt(t, angle) 87 | 88 | def vshape(t, n, height): 89 | diagonal(t, -n/2, height*n) 90 | diagonal(t, n/2, height*n) 91 | 92 | def bump(t, n, height): 93 | """make a bump with radius n at height*n 94 | """ 95 | stump(t, n*height) 96 | arc(t, n/2.0, 180) 97 | lt(t) 98 | fdlt(t, n*height+n) 99 | 100 | 101 | """ 102 | The letter-drawing functions all have the precondition 103 | that the turtle is in the lower-left corner of the letter, 104 | and postcondition that the turtle is in the lower-right 105 | corner, facing in the direction it started in. 106 | 107 | They all take a turtle as the first argument and a size (n) 108 | as the second. Most letters are (n) units wide and (2n) units 109 | high. 110 | 111 | """ 112 | 113 | def draw_a(t, n): 114 | diagonal(t, n/2, 2*n) 115 | beam(t, n, 1) 116 | skip(t, n) 117 | diagonal(t, -n/2, 2*n) 118 | 119 | def draw_b(t, n): 120 | bump(t, n, 1) 121 | bump(t, n, 0) 122 | skip(t, n/2) 123 | 124 | def draw_c(t, n): 125 | hangman(t, n, 2) 126 | fd(t, n) 127 | 128 | def draw_d(t, n): 129 | bump(t, 2*n, 0) 130 | skip(t, n) 131 | 132 | def draw_ef(t, n): 133 | hangman(t, n, 2) 134 | hangman(t, n, 1) 135 | 136 | def draw_e(t, n): 137 | draw_ef(t, n) 138 | fd(t, n) 139 | 140 | def draw_f(t, n): 141 | draw_ef(t, n) 142 | skip(t, n) 143 | 144 | def draw_g(t, n): 145 | hangman(t, n, 2) 146 | fd(t, n/2) 147 | beam(t, n/2, 2) 148 | fd(t, n/2) 149 | post(t, n) 150 | 151 | def draw_h(t, n): 152 | post(t, 2*n) 153 | hangman(t, n, 1) 154 | skip(t, n) 155 | post(t, 2*n) 156 | 157 | def draw_i(t, n): 158 | beam(t, n, 2) 159 | fd(t, n/2) 160 | post(t, 2*n) 161 | fd(t, n/2) 162 | 163 | def draw_j(t, n): 164 | beam(t, n, 2) 165 | arc(t, n/2, 90) 166 | fd(t, 3*n/2) 167 | skip(t, -2*n) 168 | rt(t) 169 | skip(t, n/2) 170 | 171 | def draw_k(t, n): 172 | post(t, 2*n) 173 | stump(t, n, 180) 174 | vshape(t, 2*n, 0.5) 175 | fdlt(t, n) 176 | skip(t, n) 177 | 178 | def draw_l(t, n): 179 | post(t, 2*n) 180 | fd(t, n) 181 | 182 | def draw_n(t, n): 183 | post(t, 2*n) 184 | skip(t, n) 185 | diagonal(t, -n, 2*n) 186 | post(t, 2*n) 187 | 188 | def draw_m(t, n): 189 | post(t, 2*n) 190 | draw_v(t, n) 191 | post(t, 2*n) 192 | 193 | def draw_o(t, n): 194 | skip(t, n) 195 | circle(t, n) 196 | skip(t, n) 197 | 198 | def draw_p(t, n): 199 | bump(t, n, 1) 200 | skip(t, n/2) 201 | 202 | def draw_q(t, n): 203 | draw_o(t, n) 204 | diagonal(t, -n/2, n) 205 | 206 | def draw_r(t, n): 207 | draw_p(t, n) 208 | diagonal(t, -n/2, n) 209 | 210 | def draw_s(t, n): 211 | fd(t, n/2) 212 | arc(t, n/2, 180) 213 | arc(t, n/2, -180) 214 | fdlt(t, n/2, -90) 215 | skip(t, 2*n) 216 | lt(t) 217 | 218 | def draw_t(t, n): 219 | beam(t, n, 2) 220 | skip(t, n/2) 221 | post(t, 2*n) 222 | skip(t, n/2) 223 | 224 | def draw_u(t, n): 225 | post(t, 2*n) 226 | fd(t, n) 227 | post(t, 2*n) 228 | 229 | def draw_v(t, n): 230 | skip(t, n/2) 231 | vshape(t, n, 2) 232 | skip(t, n/2) 233 | 234 | def draw_w(t, n): 235 | draw_v(t, n) 236 | draw_v(t, n) 237 | 238 | def draw_x(t, n): 239 | diagonal(t, n, 2*n) 240 | skip(t, n) 241 | diagonal(t, -n, 2*n) 242 | 243 | def draw_v(t, n): 244 | skip(t, n/2) 245 | diagonal(t, -n/2, 2*n) 246 | diagonal(t, n/2, 2*n) 247 | skip(t, n/2) 248 | 249 | def draw_y(t, n): 250 | skip(t, n/2) 251 | stump(t, n) 252 | vshape(t, n, 1) 253 | rt(t) 254 | fdlt(t, n) 255 | skip(t, n/2) 256 | 257 | def draw_z(t, n): 258 | beam(t, n, 2) 259 | diagonal(t, n, 2*n) 260 | fd(t, n) 261 | 262 | def draw_(t, n): 263 | # draw a space 264 | skip(t, n) 265 | 266 | if __name__ == '__main__': 267 | world = TurtleWorld() 268 | 269 | # create and position the turtle 270 | size = 20 271 | bob = Turtle() 272 | bob.delay = 0.01 273 | 274 | for f in [draw_h, draw_e, draw_l, draw_l, draw_o]: 275 | f(bob, size) 276 | skip(bob, size) 277 | 278 | wait_for_user() -------------------------------------------------------------------------------- /output.txt: -------------------------------------------------------------------------------- 1 | Aqqle 2 | Banana 3 | Cheery 4 | qitaya -------------------------------------------------------------------------------- /polygon.py: -------------------------------------------------------------------------------- 1 | """This module contains code from 2 | Think Python by Allen B. Downey 3 | http://thinkpython.com 4 | 5 | Copyright 2012 Allen B. Downey 6 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 7 | 8 | """ 9 | 10 | import math 11 | 12 | try: 13 | # see if Swampy is installed as a package 14 | from swampy.TurtleWorld import * 15 | except ImportError: 16 | # otherwise see if the modules are on the PYTHONPATH 17 | from TurtleWorld import * 18 | 19 | 20 | def square(t, length): 21 | """Draws a square with sides of the given length. 22 | 23 | Returns the Turtle to the starting position and location. 24 | """ 25 | for i in range(4): 26 | fd(t, length) 27 | lt(t) 28 | 29 | 30 | def polyline(t, n, length, angle): 31 | """Draws n line segments. 32 | 33 | t: Turtle object 34 | n: number of line segments 35 | length: length of each segment 36 | angle: degrees between segments 37 | """ 38 | for i in range(n): 39 | fd(t, length) 40 | lt(t, angle) 41 | 42 | 43 | def polygon(t, n, length): 44 | """Draws a polygon with n sides. 45 | 46 | t: Turtle 47 | n: number of sides 48 | length: length of each side. 49 | """ 50 | angle = 360.0/n 51 | polyline(t, n, length, angle) 52 | 53 | 54 | def arc(t, r, angle): 55 | """Draws an arc with the given radius and angle. 56 | 57 | t: Turtle 58 | r: radius 59 | angle: angle subtended by the arc, in degrees 60 | """ 61 | arc_length = 2 * math.pi * r * abs(angle) / 360 62 | n = int(arc_length / 4) + 1 63 | step_length = arc_length / n 64 | step_angle = float(angle) / n 65 | 66 | # making a slight left turn before starting reduces 67 | # the error caused by the linear approximation of the arc 68 | lt(t, step_angle/2) 69 | polyline(t, n, step_length, step_angle) 70 | rt(t, step_angle/2) 71 | 72 | 73 | def circle(t, r): 74 | """Draws a circle with the given radius. 75 | 76 | t: Turtle 77 | r: radius 78 | """ 79 | arc(t, r, 360) 80 | 81 | 82 | # the following condition checks whether we are 83 | # running as a script, in which case run the test code, 84 | # or being imported, in which case don't. 85 | 86 | if __name__ == '__main__': 87 | world = TurtleWorld() 88 | 89 | bob = Turtle() 90 | bob.delay = 0.001 91 | 92 | # draw a circle centered on the origin 93 | radius = 100 94 | pu(bob) 95 | fd(bob, radius) 96 | lt(bob) 97 | pd(bob) 98 | circle(bob, radius) 99 | 100 | wait_for_user() -------------------------------------------------------------------------------- /polygon.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/polygon.pyc -------------------------------------------------------------------------------- /pronounce.py: -------------------------------------------------------------------------------- 1 | """This module contains a code example related to 2 | 3 | Think Python, 2nd Edition 4 | by Allen Downey 5 | http://thinkpython2.com 6 | 7 | Copyright 2015 Allen Downey 8 | 9 | License: http://creativecommons.org/licenses/by/4.0/ 10 | """ 11 | 12 | from __future__ import print_function, division 13 | 14 | 15 | def read_dictionary(filename='c06d'): 16 | """Reads from a file and builds a dictionary that maps from 17 | each word to a string that describes its primary pronunciation. 18 | 19 | Secondary pronunciations are added to the dictionary with 20 | a number, in parentheses, at the end of the key, so the 21 | key for the second pronunciation of "abdominal" is "abdominal(2)". 22 | 23 | filename: string 24 | returns: map from string to pronunciation 25 | """ 26 | d = dict() 27 | fin = open(filename) 28 | for line in fin: 29 | 30 | # skip over the comments 31 | if line[0] == '#': continue 32 | 33 | t = line.split() 34 | word = t[0].lower() 35 | pron = ' '.join(t[1:]) 36 | d[word] = pron 37 | 38 | return d 39 | 40 | 41 | if __name__ == '__main__': 42 | d = read_dictionary() 43 | for k, v in d.items(): 44 | print(k, v) -------------------------------------------------------------------------------- /pronounce.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/pronounce.pyc -------------------------------------------------------------------------------- /rename.py: -------------------------------------------------------------------------------- 1 | # change the name to fit Github listing convention 2 | import os 3 | 4 | for file in os.listdir(): 5 | if file.startswith(("ex3", "ex4", "ex5", "ex6", "ex7", "ex8", "ex9")): 6 | os.rename(file, file.replace("ex", "ex0")) 7 | -------------------------------------------------------------------------------- /reverse_pair.py: -------------------------------------------------------------------------------- 1 | """This module contains a code example related to 2 | 3 | Think Python, 2nd Edition 4 | by Allen Downey 5 | http://thinkpython2.com 6 | 7 | Copyright 2015 Allen Downey 8 | 9 | License: http://creativecommons.org/licenses/by/4.0/ 10 | """ 11 | 12 | from __future__ import print_function, division 13 | 14 | 15 | from inlist import in_bisect, make_word_list 16 | 17 | 18 | def reverse_pair(word_list, word): 19 | """Checks whether a reversed word appears in word_list. 20 | 21 | word_list: list of strings 22 | word: string 23 | """ 24 | rev_word = word[::-1] 25 | return in_bisect(word_list, rev_word) 26 | 27 | import time 28 | if __name__ == '__main__': 29 | st = time.time() 30 | word_list = make_word_list() 31 | ctr = 0 32 | for word in word_list: 33 | if reverse_pair(word_list, word): 34 | ctr = ctr + 1 35 | #print(word, word[::-1]) 36 | et = time.time() - st 37 | print (ctr) 38 | print (et) 39 | 40 | -------------------------------------------------------------------------------- /shelf.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dexhunter/TP_solutions/d0abae261eda1dca99043e17e8a1e614caad2140/shelf.pkl -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | """This module contains a code example related to 2 | 3 | Think Python, 2nd Edition 4 | by Allen Downey 5 | http://thinkpython2.com 6 | 7 | Copyright 2015 Allen Downey 8 | 9 | License: http://creativecommons.org/licenses/by/4.0/ 10 | """ 11 | 12 | from __future__ import print_function, division 13 | 14 | from Card import Hand, Deck 15 | from collections import defaultdict 16 | 17 | class Hist(dict): 18 | """A map from each item (x) to its frequency.""" 19 | 20 | def __init__(self, seq=[]): 21 | "Creates a new histogram starting with the items in seq." 22 | for x in seq: 23 | self.count(x) 24 | 25 | def count(self, x, f=1): 26 | "Increments (or decrements) the counter associated with item x." 27 | self[x] = self.get(x, 0) + f 28 | if self[x] == 0: 29 | del self[x] 30 | 31 | 32 | class PokerHand(Hand): 33 | """Represents a poker hand.""" 34 | 35 | all_labels = ['straightflush', 'fourkind', 'fullhouse', 'flush', 36 | 'straight', 'threekind', 'twopair', 'pair', 'highcard'] 37 | 38 | def make_histograms(self): 39 | """Computes histograms for suits and hands. 40 | 41 | Creates attributes: 42 | 43 | suits: a histogram of the suits in the hand. 44 | ranks: a histogram of the ranks. 45 | sets: a sorted list in descending order of the rank sets in the hand. 46 | """ 47 | self.suits = Hist() 48 | self.ranks = Hist() 49 | 50 | for c in self.cards: 51 | self.suits.count(c.suit) 52 | self.ranks.count(c.rank) 53 | 54 | self.sets = list(self.ranks.values()) 55 | self.sets.sort(reverse=True) 56 | 57 | def has_highcard(self): 58 | """Returns True if this hand has a high card.""" 59 | return len(self.cards) 60 | 61 | def check_sets(self, *t): 62 | """Checks whether self.sets contains sets that are 63 | at least as big as the requirements in t. 64 | 65 | t: list of int 66 | """ 67 | for need, have in zip(t, self.sets): 68 | if need > have: 69 | return False 70 | return True 71 | 72 | def has_pair(self): 73 | """Checks whether this hand has a pair.""" 74 | return self.check_sets(2) 75 | 76 | def has_twopair(self): 77 | """Checks whether this hand has two pair.""" 78 | return self.check_sets(2, 2) 79 | 80 | def has_threekind(self): 81 | """Checks whether this hand has three of a kind.""" 82 | return self.check_sets(3) 83 | 84 | def has_fourkind(self): 85 | """Checks whether this hand has four of a kind.""" 86 | return self.check_sets(4) 87 | 88 | def has_fullhouse(self): 89 | """Checks whether this hand has a full house.""" 90 | return self.check_sets(3, 2) 91 | 92 | def has_flush(self): 93 | """Checks whether this hand has a flush.""" 94 | for val in self.suits.values(): 95 | if val >= 5: 96 | return True 97 | return False 98 | 99 | def has_straight(self): 100 | """Checks whether this hand has a straight.""" 101 | # make a copy of the rank histogram before we mess with it 102 | ranks = self.ranks.copy() 103 | ranks[14] = ranks.get(1, 0) 104 | 105 | # see if we have 5 in a row 106 | return self.in_a_row(ranks, 5) 107 | 108 | def in_a_row(self, ranks, n=5): 109 | """Checks whether the histogram has n ranks in a row. 110 | 111 | hist: map from rank to frequency 112 | n: number we need to get to 113 | """ 114 | count = 0 115 | for i in range(1, 15): 116 | if ranks.get(i, 0): 117 | count += 1 118 | if count == n: 119 | return True 120 | else: 121 | count = 0 122 | return False 123 | 124 | def has_straightflush(self): 125 | """Checks whether this hand has a straight flush. 126 | 127 | Clumsy algorithm. 128 | """ 129 | # make a set of the (rank, suit) pairs we have 130 | s = set() 131 | for c in self.cards: 132 | s.add((c.rank, c.suit)) 133 | if c.rank == 1: 134 | s.add((14, c.suit)) 135 | 136 | # iterate through the suits and ranks and see if we 137 | # get to 5 in a row 138 | for suit in range(4): 139 | count = 0 140 | for rank in range(1, 15): 141 | if (rank, suit) in s: 142 | count += 1 143 | if count == 5: 144 | return True 145 | else: 146 | count = 0 147 | return False 148 | 149 | def has_straightflush(self): 150 | """Checks whether this hand has a straight flush. 151 | 152 | Better algorithm (in the sense of being more demonstrably 153 | correct). 154 | """ 155 | # partition the hand by suit and check each 156 | # sub-hand for a straight 157 | #d = {} 158 | #for c in self.cards: 159 | # d.setdefault(c.suit, PokerHand()).add_card(c) 160 | 161 | d = defaultdict(PokerHand) 162 | for c in self.cards: 163 | d[c.suit].add_card(c) 164 | 165 | # see if any of the partitioned hands has a straight 166 | for hand in d.values(): 167 | if len(hand.cards) < 5: 168 | continue 169 | hand.make_histograms() 170 | if hand.has_straight(): 171 | return True 172 | return False 173 | 174 | def classify(self): 175 | """Classifies this hand. 176 | 177 | Creates attributes: 178 | labels: 179 | """ 180 | self.make_histograms() 181 | 182 | self.labels = [] 183 | for label in PokerHand.all_labels: 184 | f = getattr(self, 'has_' + label) 185 | if f(): 186 | self.labels.append(label) 187 | 188 | 189 | class PokerDeck(Deck): 190 | """Represents a deck of cards that can deal poker hands.""" 191 | 192 | def deal_hands(self, num_cards=5, num_hands=10): 193 | """Deals hands from the deck and returns Hands. 194 | 195 | num_cards: cards per hand 196 | num_hands: number of hands 197 | 198 | returns: list of Hands 199 | """ 200 | hands = [] 201 | for i in range(num_hands): 202 | hand = PokerHand() 203 | self.move_cards(hand, num_cards) 204 | hand.classify() 205 | hands.append(hand) 206 | return hands 207 | 208 | 209 | def main(): 210 | # the label histogram: map from label to number of occurances 211 | lhist = Hist() 212 | 213 | # loop n times, dealing 7 hands per iteration, 7 cards each 214 | n = 10000 215 | for i in range(n): 216 | if i % 1000 == 0: 217 | print(i) 218 | 219 | deck = PokerDeck() 220 | deck.shuffle() 221 | 222 | hands = deck.deal_hands(7, 7) 223 | for hand in hands: 224 | for label in hand.labels: 225 | lhist.count(label) 226 | 227 | # print the results 228 | total = 7.0 * n 229 | print(total, 'hands dealt:') 230 | 231 | for label in PokerHand.all_labels: 232 | freq = lhist.get(label, 0) 233 | if freq == 0: 234 | continue 235 | p = total / freq 236 | print('%s happens one time in %.2f' % (label, p)) 237 | 238 | 239 | if __name__ == '__main__': 240 | #main() 241 | p = PokerDeck() 242 | # print(p) 243 | z = p.deal_hands() 244 | print(p,'\n') 245 | for i in z: 246 | print(i.labels) -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- 1 | Apple 2 | Banana 3 | Cheery 4 | pitaya -------------------------------------------------------------------------------- /test_ex124.py: -------------------------------------------------------------------------------- 1 | def initialize_word_list() : 2 | """This subroutine initializes the list of words. If a word is in this list, 3 | then it is a word""" 4 | word_list = [] 5 | f = open("words.txt","r") 6 | for line in f: 7 | word = line.strip() 8 | word_list.append ( word ) 9 | f.close() 10 | return word_list 11 | 12 | def string_to_tuple( word ) : 13 | """Convert string word into a tuple suitable for use as a key to a dictionary 14 | of anagrams""" 15 | this_word_list = list(word) # convert the string to a list so we can sort it 16 | this_word_list.sort() 17 | this_word_tuple = tuple( this_word_list ) # Conver the list to a tuple which can be the key to a dictionary 18 | return this_word_tuple 19 | 20 | def make_dict_of_anagrams ( word_list ) : 21 | """This function returns a dictionary of lists of words which are anagrams. 22 | The keys to the dictionaries are tuples of the letters in the words, sorted""" 23 | anagram_dict = dict() 24 | for word in word_list: 25 | this_word_tuple = string_to_tuple ( word ) 26 | # If key is in the dictionary, return its value. If not, insert key with a 27 | # value of default and return default. default defaults to None. 28 | # See exercise 11-2 29 | anagram_dict[this_word_tuple] = \ 30 | anagram_dict.setdefault( this_word_tuple, [] ) + [word] 31 | return anagram_dict 32 | 33 | def main() : 34 | word_list = initialize_word_list() 35 | anagram_dict=make_dict_of_anagrams( word_list ) 36 | i = 0 37 | for word in word_list : 38 | key = string_to_tuple(word) 39 | anagram_list = anagram_dict[key] 40 | # if there are anagrams, then print them. Most words have no anagrams 41 | if len ( anagram_list ) > 1 : 42 | print anagram_list 43 | i += 1 44 | if i > 200 : # I just want 200 anagrams as a proof of concept 45 | break 46 | # Part 2 of the problem: output the list sorted by length 47 | anagram_list_length_list = [] 48 | for key in anagram_dict.keys() : 49 | anagram_list_length_list.append( (len(anagram_dict[key]), key) ) 50 | anagram_list_length_list.sort() 51 | for i in range( len ( anagram_list_length_list ) ) : 52 | key = anagram_list_length_list[i][1] 53 | anagram = anagram_dict[key] 54 | if len(anagram) > 1 : 55 | print anagram 56 | 57 | DEBUG = False 58 | 59 | 60 | # To memoize the function children_of_word, we remember which words we already 61 | # know to be children 62 | children_dict = {} 63 | 64 | def children_of_word ( word ) : 65 | """This function returns a list of children of the word. A word is a "child" 66 | of this word if it has 1 letter removed from this word and is in the word list""" 67 | global word_list # word_list doesn't change and it is huge, so it is okay 68 | # to pass globally 69 | children_of_word_list = [] 70 | # Here are some corner cases. 71 | if word == "I" or word == "a" or word == "A" or word == "": 72 | return [word] 73 | if word in children_dict : 74 | return children_dict[word] 75 | for i in range( 0, len ( word ) ) : 76 | if i == 0 : 77 | potential_child_word = word[1:] 78 | elif i==len(word)-1 : 79 | potential_child_word = word[:-1] 80 | else : 81 | potential_child_word = word[:i] + word[i+1:] 82 | if potential_child_word in word_list : # Would this be faster in a dict? 83 | if DEBUG : 84 | print potential_child_word, 85 | # since potential_child_word is known to be in the word list, technically, it is 86 | # now a child_word and not a potential_child_word 87 | children_of_word_list.extend ( \ 88 | children_of_word ( potential_child_word ) ) 89 | # momoize this list of children words of potential_child_word 90 | children_dict[potential_child_word] = children_of_word_list 91 | return children_of_word_list 92 | 93 | 94 | 95 | if __name__ == "__main__" : 96 | word_list = initialize_word_list() 97 | solutions={} 98 | for word in word_list : 99 | solutions[word] = children_of_word( word ) 100 | for word in solutions.keys() : 101 | print word,":", solutions[word] 102 | -------------------------------------------------------------------------------- /test_ex93.py: -------------------------------------------------------------------------------- 1 | #test run for exercise 9-3 2 | import string 3 | 4 | def findmincomb(num_letter, words, alphabet): 5 | global min_num, min_comb 6 | # find miniset in resurcive way 7 | def mincomb(remain, alphabet, comb, pre_set): 8 | global min_num, min_comb 9 | # get enough letters 10 | if remain <= 0: 11 | pre_num = len(pre_set) 12 | if pre_num < min_num: # update 13 | min_num = pre_num 14 | min_comb = comb.copy() 15 | print(min_num, min_comb) 16 | else: 17 | comb.append(None) 18 | for i in range(len(alphabet)): 19 | letter = alphabet[i] 20 | cur_set = pre_set | cont[letter] 21 | print(comb, letter, len(cur_set)) 22 | # only when current set small the minimum set, get next letter 23 | if len(cur_set) < min_num: 24 | comb[-1] = letter 25 | mincomb(remain-1, alphabet[i+1:], comb, cur_set) 26 | comb.pop() 27 | 28 | # build dictionary for every letter in alphabet 29 | # key: letter, value: set of words contain letter 30 | cont = { 31 | letter : { 32 | word 33 | for word in words 34 | if letter in word 35 | } 36 | for letter in alphabet 37 | } 38 | 39 | # get a temporay minset 40 | min_tuple = sorted(cont.items(), key = lambda x: len(x[1]))[:num_letter] 41 | min_comb = [item[0] for item in min_tuple] 42 | min_num = len(set.union(*(item[1] for item in min_tuple))) 43 | print(min_num, min_comb) 44 | 45 | # do the really work 46 | mincomb(num_letter, alphabet, [], set()) 47 | 48 | if __name__ == '__main__': 49 | with open('words.txt', 'r') as fin: 50 | words = [line.strip() for line in fin] 51 | global min_num, min_comb 52 | findmincomb(5, words, string.ascii_lowercase) 53 | print(min_num, min_comb) -------------------------------------------------------------------------------- /xmax.py: -------------------------------------------------------------------------------- 1 | def xmas_tri(i, t=0, nrow=0): 2 | """Draw a Christmas triangle 3 | 4 | i : number of rows to print out 5 | t : the amount of asterix to initialize 6 | nrow : total number of rows 7 | """ 8 | if i == 0: 9 | return 0 10 | else: 11 | print ' ' * ( i + 1 + nrow) + 'x' * ( t * 2 + 1 ) 12 | return xmas_tri( i - 1, t + 1 , nrow) 13 | 14 | 15 | 16 | def xmas_trunk(n): 17 | node = n/2 + 1 18 | 19 | for i in range(n/4-1): 20 | print " " * (n-n/4) + "x" * node 21 | 22 | 23 | 24 | def xmas_bot(n): 25 | node = n/2 + 1 26 | for i in range(n/2): 27 | print " " * (n-n/4) + "x" * node 28 | 29 | 30 | def xmas_draw(n): 31 | xmas_tri(n/3, 0, (n/3)*2) 32 | xmas_trunk(n) 33 | xmas_tri(n/3, n/3, (n/3) ) 34 | xmas_trunk(n) 35 | xmas_tri(n/3, (n/3) * 2, 0) 36 | xmas_bot(n) 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | if __name__ == '__main__': 46 | n = input("Please give n: ") 47 | xmas_draw(n) 48 | --------------------------------------------------------------------------------