Think Python/Answers
Chapter 1
Exercise 1.4
If you run a 10 kilometer race in 43 minutes 30 seconds, what is your average time per mile? What is your average speed in miles per hour? (Hint: there are 1.61 kilometers in a mile).
>>> 10/1.61 # Convert kilometers to miles 6.2111801242236018 >>> (43*60)+30 # Convert time to seconds 2610 >>> 2610/6.2111801242236018 # what is your average time (seconds) per mile 420.21000000000004 >>> 420.21000000000004/60 # what is your average time (minutes) per mile 7.0035000000000007 >>> 60/7.0035000000000007 # Miles per hour 8.5671449989291055
Comment: This is not valid, it ONLY works for 43min and 30 seconds to 10km's. Python should have a way to do this the proper way.
In order to do this the proper way, a person must do something like this.
43*60 -> convert the minutes to seconds.
2580+30 -> add the seconds
2610/10 -> divide by distance
261/60 -> change seconds into minutes
4.35 -> is the answer, now you must
.35*60 -> multiply the number after the decimal with 60
21 seconds..
End result = 4.21 minutes per KM, this technique works for all distances and times.
Chapter 2
Exercise 2.1
If you type an integer with a leading zero, you might get a confusing error:
>>> zipcode = 02492
^
SyntaxError: invalid token
Other number seem to work, but the results are bizarre:
>>> zipcode = 02132 >>> print zipcode 1114
So python is assuming you want to convert an octal number to a decimal number. In the base 8 numbering system where valid numbers are 0, 1, 2, 3, 4, 5, 6 and 7.
Base 8: 00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17 20 21 22 23 24 Base 10: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
Every 8 numbers we increment the left hand columns. This means that the left most column is the number of 'ones'. The one to the right of that is a tally of the number of 'eights', the one next to that is a tally of a full column of 'eight' times the 'eight column' - 64. The one next to that is 64*8 - 512 and so on. For more information read [Base Eight math].
That is why zipcode = 02492 is invalid as the digit 9 is not a valid octal number. We can do the conversion manually as follows:
>>> print 02132 1114 >>> (2*512)+(1*64)+(3*8)+(2*1) 1114 >>>
Exercise 2.4
The volume of a sphere with radius r is 4/3 π r3. What is the volume of a sphere with radius 5?
>>> pi = 3.1415926535897931 >>> r = 5 >>> 4/3*pi*r**3 # This is the wrong answer 392.69908169872411 >>> r = 5.0 # Radius can be a float here as well, but is not _necessary_. >>> 4.0/3.0*pi*r**3 # Using floats give the correct answer 523.59877559829886 >>>
Suppose the cover price of a book is $24.95, but bookstores get a 40% discount. Shipping costs $3 for the first copy and 75 cents for each additional copy. What is the total wholesale cost for 60 copies?
$24.95 Cost
$9.98 Discount per book
$14.97 Cost per book after discount
60 Total number of books
$898.20 Total cost not inc delivery
$3.00 First book delivery
59 Remaining books
$0.75 Delivery cost for extra books
$44.25 Total cost for extra books
$47.25 Total Delivery cost
$945.45 Total Bill
This answer is wrong because 40.0/100.0 return wrong value 0.40000000000000002 for more info see IEEE 754 (Standard for Floating-Point Arithmetic)
>>> (24.95-24.95*40.0/100.0)*60+3+0.75*(60-1)
945.44999999999993
>>> 24.95*0.6*60+0.75*(60-1)+3
945.45
If I leave my house at 6:52 am and run 1 mile at an easy pace (8:15 per mile), then 3 miles at tempo (7:12 per mile) and 1 mile at easy pace again, what time do I get home for breakfast?
Answer: 7:30 am
How I did it:
>>> start = (6*60+52)*60 >>> easy = (8*60+15)*2 >>> fast = (7*60+12)*3 >>> finish_hour = (start + easy + fast)/(60*60.0) >>> finish_floored = (start + easy + fast)/(60*60) #int() function can also be used to get integer value, but isn't taught yet. >>> finish_minute = (finish_hour - finish_floored)*60 >>> print 'Finish time was %d:%d' % (finish_hour,finish_minute) Finish time was 7:30 >>>
Chapter 3
Exercise 3.3
Python provides a built-in function called len that returns the length of a string, so the value of len('allen') is 5. 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.
>>> def right_justify(s):
... print (' '*(70-len(s))+s)
...
>>> right_justify('allen')
allen
>>>
Exercise 3.5
You can see my solution at [http://thinkpython.com/code/grid.py].
""" Solution to Exercise X.X on page X of Think Python Allen B. Downey """ # here is a mostly-straightforward solution to the # two-by-two version of the grid. def do_twice(f): f() f() def do_four(f): do_twice(f) do_twice(f) def print_beam(): print '+ - - - -', def print_post(): print '| ', def print_beams(): do_twice(print_beam) print '+' def print_posts(): do_twice(print_post) print '|' def print_row(): print_beams() do_four(print_post) def print_grid(): do_twice(print_row) print_beams() print_grid() # here is a less-straightforward solution to the # four-by-four grid def one_four_one(f, g, h): f() do_four(g) h() def print_plus(): print '+', def print_dash(): print '-', def print_bar(): print '|', def print_space(): print ' ', def print_end(): print def nothing(): "do nothing" def print1beam(): one_four_one(nothing, print_dash, print_plus) def print1post(): one_four_one(nothing, print_space, print_bar) def print4beams(): one_four_one(print_plus, print1beam, print_end) def print4posts(): one_four_one(print_bar, print1post, print_end) def print_row(): one_four_one(nothing, print4posts, print4beams) def print_grid(): one_four_one(print4beams, print_row, nothing) print_grid() comment = """ After writing a draft of the 4x4 grid, I noticed that many of the functions had the same structure: they would do something, do something else four times, and then do something else once. So I wrote one_four_one, which takes three functions as arguments; it calls the first one once, then uses do_four to call the second one four times, then calls the third. Then I rewrote print1beam, print1post, print4beams, print4posts, print_row and print_grid using one_four_one. Programming is an exploratory process. Writing a draft of a program often gives you insight into the problem, which might lead you to rewrite the code to reflect the structure of the solution. --- Allen """ print comment
Chapter 9
Exercise 9.1
fin = open('words.txt') for line in fin: word = line.strip() if len(word) >= 20: print (word)
Chapter 10
Exercise 10.1
Write a function that takes a list of numbers and returns the cumulative sum; that is, a new list where the ith element is the sum of the first i+1 elements from the original list. For example, the cumulative sum of [1, 2, 3] is [1, 3, 6].
def cumulative(a): cumulative = [] sum = 0 for i in a: sum += i cumulative.append(sum) return cumulative a = [1, 2, 3] print(cumulative(a))
Exercise 10.2
Write a function called chop that takes a list and modifies it, removing the first and last elements, and returns None.
>>> def chop(x): del x[:1] del x[-1:]
Then write a function called middle that takes a list and returns a new list that contains all but the first and last elements.
>>> def middle(x): res = [] i = 1 while i <= len(x)-2: res.append(x[i]) i += 1 return res
This can also be done simply with a slice.
>>> def middle(x): return x[1:-1]
Chapter 11
Exercise 11.1
Write a function that reads the words in words.txt and stores them as keys in a dictionary. It doesn’t matter what the values are. Then you can use the in operator as a fast way to check whether a string is in the dictionary.
englishdictionary = dict() fin = open('words.txt') line = fin.readline() def engdicdefine(): index = 0 while index <= 1000: word = line.strip() englishdictionary[word] = index index += 1 return englishdictionary
Exercise 11.2
def histogram(s): d = dict() for c in s: d[c] = 1 + d.get(c, 0) return d
Exercise 11.3
Dictionaries have a method called keys that returns the keys of the dictionary, in no particular order, as a list. Modify print_hist to print the keys and their values in alphabetical order.
v = {'p' : 1, 'a' : 1, 'r' : 2, 'o' : 1, 't' : 1} def print_hist(h): x = h.keys() y = list(x) y.sort() for c in y: print(c, h[c])
Exercise 11.4
def reverse_lookup(d,v): l = list() for c in d: if d[c] == v: l.append(c) return l
Chapter 12
Exercise 12.1
numbers = (1,2,3) def sumall(numbers): x = 0 for i in numbers: x = x + i print x sumall(numbers)
or
def sumall(*t): x = 0 for i in range(len(t)): x += t[i] return x
or
def sumall(*args): t = list(args) return sum(t)
Exercise 12.2
import random def sort_by_length(words): t = [] for word in words: t.append((len(word),word)) t.sort(reverse=True) res = [] for length, word in t: res.append(word) i=0 final = [] while i <= len(res)-2: if len(res[i]) == len(res[i+1]): y_list = [res[i], res[i+1]] random.shuffle(y_list) final = final + y_list i += 2 else: final.append(res[i]) i += 1 if i == len(res)-1: final.append(res[i]) return final
or
from random import shuffle def sort_by_length(words): r = [] d = dict() for word in words: d.setdefault(len(word), []).append(word) for key in sorted(d, reverse=True): if len(d[key]) > 1: shuffle(d[key]) r.extend(d[key]) return r
Exercise 12.3
import string def most_frequent(s): d = dict() inv = dict() for char in s: if char in string.ascii_letters: letter = char.lower() d[letter] = d.get(letter, 0) + 1 for letter, freq in d.items(): inv.setdefault(freq, []).append(letter) for freq in sorted(inv, reverse=True): print('{:.2%}:'.format(freq/(sum(list(inv)*len(inv[freq])))), ', '.join(inv[freq]))
Chapter 13
Exercise 13.7
from string import punctuation, whitespace, digits from random import randint from bisect import bisect_left def process_file(filename): h = dict() fp = open(filename) for line in fp: process_line(line, h) return h def process_line(line, h): line = line.replace('-', ' ') for word in line.split(): word = word.strip(punctuation + whitespace + digits) word = word.lower() if word != '': h[word] = h.get(word, 0) + 1 hist = process_file('emma.txt') def cum_sum(list_of_numbers): cum_list = [] for i, elem in enumerate(list_of_numbers): if i == 0: cum_list.append(elem) else: cum_list.append(cum_list[i-1] + elem) return cum_list def random_word(h): word_list = list(h.keys()) num_list = [] for word in word_list: num_list.append(h[word]) cum_list = cum_sum(num_list) i = randint(1, cum_list[-1]) pos = bisect_left(cum_list, i) return word_list[pos] print(random_word(hist))
Chapter 14
Exercise 14.3
import shelve def dict_of_signatures_and_words(filename='words.txt'): d = dict() for line in open(filename): word = line.lower().strip() signature = ''.join(sorted(word)) d.setdefault(signature, []).append(word) return d def db_of_anagrams(filename='anagrams', d=dict_of_signatures_and_words()): db = shelve.open(filename) for key, values in d.items(): if len(values)>1: for index, value in enumerate(values): db[value]=values[:index]+values[index+1:] db.close() def print_contents_of_db(filename='anagrams'): db = shelve.open(filename, flag='r') for key in sorted(db): print(key.rjust(12), '\t<==>\t', ', '.join(db[key])) db.close() db_of_anagrams() print_contents_of_db()
Exercise 14.5
# Replace urllib.request with urllib if you use Python 2. # I would love to see a more elegant solution for this exercise, possibly by someone who understands html. import urllib.request def check(zip_code): if zip_code == 'done': return break if len(zip_code) != 5: print('\nThe zip code must have five digits!') return continue def get_html(zip_code): gibberish = urllib.request.urlopen('http://www.uszip.com/zip/' + zip_code) less_gib = gibberish.read().decode('utf-8') return less_gib def extract_truth(code, key, delimiter): pos = code.find(key) + len(key) nearly_true = code[pos:pos+40] truth = nearly_true.split(delimiter)[0] return truth while True: zip_code = input('Please type a zip code (5 digits) or "done" if want to stop:\n') check(zip_code) code = get_html(zip_code) invalid_key = '(0 results)' if invalid_key in code: print('\nNot a valid zip code.') continue name_key = 'zip code of <strong>' name_del = '<' name = extract_truth(code, name_key, name_del) pop_key = 'Population:</b></td><td>' pop_del = ' <' name = extract_truth(code, pop_key, pop_del) if not 1 < len(pop) < 9: pop = 'not available' print('\n' + name) print('Population:', pop, '\n')
Chapter 15
Exercise 15.1
import math class Point(object): """represents a point in 2-D space""" def distance(p1, p2): distance = math.sqrt((p2.x - p1.x)**2 + (p2.y - p1.y)**2) return distance p1 = Point() p2 = Point() p1.x = 3 p1.y = 2 p2.x = 4 p2.y = 3 print(distance(p1, p2))
Chapter 16
Exercise 16.1
def print_time(t): print '%.2d:%.2d:%.2d' % (t.hour, t.minute, t.second)
or
# Solution for Python3 # More on string formatting: http://docs.python.org/py3k/library/string.html#formatspec def print_time(t): # 0 is a fill character, 2 defines the width print('{}:{:02}:{:02}'.format(t.hour, t.minute, t.second))
Exercise 16.2
def is_after(t1, t2): return (t1.hour, t1.minute, t1.second) > (t2.hour, t2.minute, t2.second)
Exercise 16.3
# Comment not by the author: This will give a wrong result, if (time.second + seconds % 60) > 60 def increment(time, seconds): n = seconds/60 time.second += seconds - 60.0*n time.minute += n m = time.minute/60 time.minute -= m*60 time.hour += m
or
# Solution for Python3 # Replace '//' by '/' for Python2 def increment(time, seconds): time.second += seconds time.minute += time.second//60 time.hour += time.minute//60 time.second %= 60 time.minute %= 60 time.hour %= 24
Exercise 16.4
# Solution for Python3 # Replace '//' by '/' for Python2 from copy import deepcopy def increment(time, seconds): r = deepcopy(time) r.second += seconds r.minute += r.second//60 r.hour += r.minute//60 r.second %= 60 r.minute %= 60 r.hour %= 24 return r
Exercise 16.5
class Time(object): """represents the time of day. attributes: hour, minute, second""" time = Time() time.hour = 11 time.minute = 59 time.second = 30 def time_to_int(time): minutes = time.hour * 60 + time.minute seconds = minutes * 60 + time.second return seconds def int_to_time(seconds): time = Time() minutes, time.second = divmod(seconds, 60) time.hour, time.minute = divmod(minutes, 60) return time def increment(time, addtime): seconds = time_to_int(time) return int_to_time(seconds + addtime) def print_time (x): print 'The time is %.2d : %.2d : %.2d' % (x.hour, x.minute, x.second) print_time (time) newtime = increment (time, 70) print_time (newtime)
Exercise 16.6
def time_to_int(time): minutes = time.hour * 60 + time.minute seconds = minutes * 60 + time.second return seconds def int_to_time(seconds): time = Time() minutes, time.second = divmod(seconds, 60) time.hour, time.minute = divmod(minutes, 60) return time def mul_time(time, factor): seconds = time_to_int(time) seconds *= factor seconds = int(seconds) return int_to_time(seconds) def average_pace(time, distance): return mul_time(time, 1/distance)
Exercise 16.7
Write a class definition for a Date object that has attributes day, month and year. Write a function called increment_date that takes a Date object, date, and an integer, n, and returns a new Date object that represents the day n days after date. Hint: “Thirty days hath September...” Challenge: does your function deal with leap years correctly? See wikipedia.org/wiki/Leap_year.
class Date(object): """represents a date. attributes: day, month, year""" def print_date(date): # German date format print('{}.{}.{}'.format(date.day, date.month, date.year)) def is_leap_year(year): # http://en.wikipedia.org/wiki/Leap_year#Algorithm if year % 4 == 0: if year % 100 == 0: if year % 400 == 0: return True return False return True return False def month_list(year): if is_leap_year(year): return [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] return [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] def days_of_year(year): if is_leap_year(year): return 366 return 365 def date_to_int(date): days = 0 for year in range(1, date.year): days += days_of_year(year) month_days = month_list(date.year) for month in range(1, date.month): days += month_days[month - 1] days += date.day - 1 return days def int_to_date(days): date = Date() date.year = 1 next_days = 365 while days >= next_days: date.year += 1 days -= next_days next_days = days_of_year(date.year) date.month = 1 next_days = 31 month_days = month_list(date.year) while days >= next_days: date.month += 1 days -= next_days next_days = month_days[date.month - 1] date.day = days + 1 return date def increment_date(date, n): days = date_to_int(date) return int_to_date(days + n) d1 = Date() d1.day, d1.month, d1.year = 8, 3, 2012 print_date(d1) d2 = increment_date(d1, 7) print_date(d2)
Exercise 16.8
1. Use the datetime module to write a program that gets the current date and prints the day of the week.
from datetime import date def current_weekday(): i = date.today().weekday() print(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'][i]) current_weekday()
2. Write a program that takes a birthday as input and prints the user’s age and the number of days, hours, minutes and seconds until their next birthday.
# Python3 solution. Replace "input" by "raw_input" for Python2. from datetime import datetime def time_until_birthday(): dob_input = input(('Please enter the date of your birth in ' 'the format "mm/dd/yyyy": ')) dob = datetime.strptime(dob_input, '%m/%d/%Y') now = datetime.now() if now > datetime(now.year, dob.month, dob.day): age = now.year - dob.year next_year = True else: age = now.year - dob.year - 1 next_year = False time_to_birthday = datetime(now.year + next_year, dob.month, dob.day) - now days = time_to_birthday.days hours, remainder = divmod(time_to_birthday.seconds, 3600) minutes, seconds = divmod(remainder, 60) print("\nYou are {} years old.".format(age)) print(("You have {0} days, {1} hours, {2} minutes and {3} " "seconds left until your next birthday.").format( days, hours, minutes, seconds)) time_until_birthday()
Chapter 17
Exercise 17.8
2.
from visual import scene, sphere scene.range = (256, 256, 256) scene.center = (128, 128, 128) t = range(0, 256, 51) for x in t: for y in t: for z in t: pos = x, y, z color = (x/255., y/255., z/255.) sphere(pos=pos, radius=10, color=color)
3. Download http://thinkpython.com/code/color_list.py and use the function read_colors to generate a list of the available colors on your system, their names and RGB values. For each named color draw a sphere in the position that corresponds to its RGB values.
# As there currently (2013-04-12) is no function read_colors in color_list.py # I use a workaround and simply import the variable COLORS from color_list.py. # I then use the function all_colors() on COLORS to get a list of the colors. from color_list import COLORS from visual import scene, sphere def all_colors(colors_string=COLORS): """Extract a list of unique RGB-tuples from COLORS. The tuples look like (r, g, b), where r, g and b are each integers in [0, 255]. """ # split the string into lines and remove irrelevant lines lines = colors_string.split('\n')[2:-2] # split the individual lines and remove the names numbers_only = [line.split()[:3] for line in lines] # turn strings into ints and rgb-lists into tuples rgb_tuples = [tuple([int(s) for s in lst]) for lst in numbers_only] # return a list of unique tuples return list(set(rgb_tuples)) def make_spheres(color_tuples=all_colors()): scene.range = (256, 256, 256) scene.center = (128, 128, 128) for (r, g, b) in color_tuples: sphere(pos=(r, g, b), radius=7, color=(r/255., g/255., b/255.)) if __name__ == '__main__': make_spheres()
Chapter 3.5
calculator
#recursion or recursive print "\n INDEX\n""\n C=1 for addition\n""\n C=2 for substraction\n""\n C=3 for multiplication\n""\n C=4 for division\n""\n C=5 for to find modulus\n""\n C=6 to find factorial\n" C=input("Enter your choice here: ") def add(x,y): c=x+y print x,"+",y,"=",c def sub(x,y): c=x-y print x,"-",y,"=",c def mul(x,y): c=x*y print x,"*",y,"=",c def div(x,y): c=x/y print x,"/",y,"=",c def mod(x,y): c=x%y print x,"%",y,"=",c if C==6: def f(n): if n==1: print n return n else: print n,"*", return n*f(n-1) n=input("enter your no here: ") print f(n) if C==1: a=input("Enter your first no here: ") b=input("Enter your second no here: ") add(a,b) elif C==2: a=input("Enter your first no here: ") b=input("Enter your second no here: ") sub(a,b) elif C==3: a=input("Enter your first no here: ") b=input("Enter your second no here: ") mul(a,b) elif C==4: a=input("Enter your first no here: ") b=input("Enter your second no here: ") div(a,b) elif C==5: a=input("Enter your first no here: ") b=input("Enter your second no here: ") mod(a,b)
palindrome
def first(word): return word[0] def last(word): return word[-1] def middle(word): return word[1:-1] def palindrome(word): if first(word)==last(word): word = middle(word) n=len(word) if n<2: print "palindrome" else: return palindrome(word) else: print "not palindrome" word=raw_input("Enter the string:") palindrome(word)
sum of all digits
def sum_of_n_numbers(number): if(number==0): return 0 else: return number + sum_of_n_numbers(number-1) num = raw_input("Enter a number:") num=int(num) sum = sum_of_n_numbers(num) print sum ###another answer in case of while loops def sum_of_Digits(number): sum=0 while number>0: digit=number%10 sum=sum+digit number=number/10 return sum num=raw_input("enter the number") num=int(num) sum_of_digits=sum_of_Digits(num) print sum_of_digits
Exercise 18.5
class Card(object): suit_names = ['Clubs', 'Diamonds', 'Hearts', 'Spades'] rank_names = [None, 'Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King'] def __init__(self, suit = 0, rank = 2): self.suit = suit self.rank = rank def __str__(self): return '%s of %s' % (Card.rank_names[self.rank], Card.suit_names[self.suit]) def __cmp__(self, other): c1 = (self.suit, self.rank) c2 = (other.suit, other.rank) return cmp(c1, c2) def is_valid(self): return self.rank > 0 class Deck(object): def __init__(self, label = 'Deck'): self.label = label self.cards = [] for i in range(4): for k in range(1, 14): card = Card(i, k) self.cards.append(card) def __str__(self): res = [] for card in self.cards: res.append(str(card)) print self.label return '\n'.join(res) def deal_card(self): return self.cards.pop(0) def add_card(self, card): self.cards.append(card) def shuffle(self): import random random.shuffle(self.cards) def sort(self): self.cards.sort() def move_cards(self, other, num): for i in range(num): other.add_card(self.deal_card()) def deal_hands(self, num_hands, num_cards): if num_hands*num_cards > 52: return 'Not enough cards.' l = [] for i in range(1, num_hands + 1): hand_i = Hand('Hand %d' % i) self.move_cards(hand_i, num_cards) l.append(hand_i) return l class Hand(Deck): def __init__(self, label = ''): self.cards = [] self.label = label # 18-6, 1-4: class PokerHand(Hand): def suit_hist(self): self.suits = {} for card in self.cards: self.suits[card.suit] = self.suits.get(card.suit, 0) + 1 return self.suits def rank_hist(self): self.ranks = {} for card in self.cards: self.ranks[card.rank] = self.ranks.get(card.rank, 0) + 1 return self.ranks def P(self): self.rank_hist() for val in self.ranks.values(): if val >= 2: return True return False def TP(self): self.rank_hist() count = 0 for val in self.ranks.values(): if val == 4: return True elif val >= 2 and val < 4: count += 1 return count >= 2 def TOAK(self): self.rank_hist() for val in self.ranks.values(): if val >= 3: return True return False def STRseq(self): seq = [] l = STRlist() self.rank_hist() h = self.ranks.keys() h.sort() if len(h) < 5: return [] # Accounts for high Aces: if 1 in h: h.append(1) for i in range(5, len(h)+1): if h[i-5:i] in l: seq.append(h[i-5:i]) return seq def STR(self): seq = self.STRseq() return seq != [] def FL(self): self.suit_hist() for val in self.suits.values(): if val >= 5: return True return False def FH(self): d = self.rank_hist() keys = d.keys() for key in keys: if d[key] >= 3: keys.remove(key) for key in keys: if d[key] >= 2: return True return False def FOAK(self): self.rank_hist() for val in self.ranks.values(): if val >= 4: return True return False def SFL(self): seq = self.STRseq() if seq == []: return False for list in seq: list_suits = [] for index in list: for card in self.cards: if card.rank == index: list_suits.append(card.suit) list_hist = histogram(list_suits) for key in list_hist.keys(): if list_hist[key] >= 5: return True return False def classify(self): self.scores = [] hands = ['Pair', 'Two-Pair', 'Three of a Kind', 'Straight', 'Flush', 'Full House', 'Four of a Kind', 'Straight Flush'] if self.P(): self.scores.append(1) if self.TP(): self.scores.append(2) if self.TOAK(): self.scores.append(3) if self.STR(): self.scores.append(4) if self.FL(): self.scores.append(5) if self.FH(): self.scores.append(6) if self.FOAK(): self.scores.append(7) if self.SFL(): self.scores.append(8) if self.scores != []: return hands[max(self.scores)-1] def STRlist(): s = [] for i in range(0,9): s.append(range(1,14)[i:i+5]) s.append([10,11,12,13,1]) return s def histogram(l): d = dict() for k in range(len(l)): d[l[k]] = 1 + d.get(l[k],0) return d # 18-6, 5: def p(config = '', trials = 10000, n = 1): """Estimates probability that the nth dealt hand will be config. A hand consists of seven cards.""" successes = 0 for i in range(1, trials + 1): deck = Deck('Deck %d' % i) deck.shuffle() box = Hand() deck.move_cards(box, (n-1)*7) hand = PokerHand('Poker Hand %d' % i) deck.move_cards(hand, 7) if hand.classify() == config: successes += 1 return 1.0*successes/trials #Iterate until first desired config.: if __name__ == '__main__': c = 1 while True: deck = Deck() deck.shuffle() hand = PokerHand('Poker Hand %d' % c) deck.move_cards(hand, 5) print hand print hand.SFL() if hand.SFL(): print hand.STRseq() break print '' c += 1 Code by Victor Alvarez
Appendix B
Exercise B.3
Write a function called bisection that takes a sorted list and a target value and returns the index of the value in the list, if it’s there, or None if it’s not.
from bisect import bisect_left def bisection(sorted_list, item): i = bisect_left(sorted_list, item) if i < len(sorted_list) and sorted_list[i] == item: return i else: return None if __name__ == '__main__': a = [1, 2, 3] print(bisection(a, 2)) # expect 1 b = [1, 3] print(bisection(b, 2)) # expect None c = [1, 2] print(bisection(c, 3)) # expect None