Number Guesser: Please Review and Make it More Pythonic
I'm working on learning python, here is a simple program, I wrote:
def guesser(var, num1,possible):
if var == 'n':
cutoff = len(possible)/2
possible = possible[0:cutoff]
cutoff = possible[len(possible)/2]
#print possible
if (len(possible) == 1):
print "Your开发者_开发技巧 Number is:", possible
else:
var = raw_input("Is Your Number Bigger Than %s? (y/n): " %cutoff)
guesser(var, cutoff,possible)
elif var == 'y':
cutoff = len(possible)/2
possible = possible[cutoff:len(possible)]
cutoff = possible[len(possible)/2]
#print possible
#print cutoff
if (len(possible) == 1):
print "Your Number is:", possible
else:
var = raw_input("Is Your Number Bigger Than %s? (y/n): " %cutoff)
guesser(var, cutoff,possible)
else:
var = raw_input("Is Your Number Bigger Than 50? (y/n): ")
guesser(var, 50, possible)
possible = []
possible = range(1,101)
guesser('a', 50, possible)
Normally I would try to help with your code, but you have made it so way much too complicated that I think it would be easier for you to look at some code.
def guesser( bounds ):
a, b = bounds
mid = ( a + b ) // 2
if a == b: return a
if input( "over {0}? ".format( mid ) ) == "y":
new_bounds = ( mid, b )
else:
new_bounds = ( a, mid )
return guesser( new_bounds )
You should think about how your algorithm will work in abstract terms before diving in.
EDIT: Simplified the code at the expense of brevity.
Before doing it more pythonic I will probably make it more simple... the algorithm is much more complex than necessary. No need to use a list when two ints are enough.
def guesser(low = 0, up = 100):
print("Choose a number between %d and %d" % (low, up-1))
while low < up - 1:
mid = (low+up)//2
yn = raw_input("Is Your Number Smaller Than %s? (y/n): " % mid)
if yn not in ['y', 'n']: continue
low, up = (low, mid) if yn == 'y' else (mid, up)
print "Your Number is:", low
guesser()
More pythonic to use the bisect
module - and a class
of course :)
import bisect
hival= 50
class Guesser(list):
def __getitem__(self, idx):
return 0 if raw_input("Is your number bigger than %s? (y/n)"%idx)=='y' else hival
g=Guesser()
print "Think of a number between 0 and %s"%hival
print "Your number is: %s"%bisect.bisect(g,0,hi=hival)
Here is the definition of bisect.bisect
from the python library. As you can see, most of the algorithm is implemented here for you
def bisect_right(a, x, lo=0, hi=None):
"""Return the index where to insert item x in list a, assuming a is sorted.
The return value i is such that all e in a[:i] have e <= x, and all e in
a[i:] have e > x. So if x already appears in the list, a.insert(x) will
insert just after the rightmost x already there.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if x < a[mid]: hi = mid
else: lo = mid+1
return lo
bisect = bisect_right # backward compatibility
This is not as elegant as katrielalex's recursion, but it illustrates a basic class.
class guesser:
def __init__(self, l_bound, u_bound):
self.u_bound = u_bound
self.l_bound = l_bound
self.nextguess()
def nextguess(self):
self.guess = int((self.u_bound + self.l_bound)/2)
print 'Higher or lower than %i?' % self.guess
def mynumberishigher(self):
self.l_bound = self.guess
self.nextguess()
def mynumberislower(self):
self.u_bound = self.guess
self.nextguess()
精彩评论