Newb ??

C

Chad Everett

Hi all, I am new to the group. Trying to learn Python programming on my
own. I am working through Michael Dawson's Book Python Programming for the
absolute beginner.

I am tring to write a program that is a number guessing game. I want to be
able to give the user 5 tries to guess the number before the program ends.

I get the result that I want when the user misses after the 5th try. But it
does not go down to my closing statement to end. Rather is askes for
another guess.

I appreciate any help you can give. If this is not the correct group for
these types of questions, I apologize and hope that you can direct me to
another NG.

Thanks,
Chad

import random

print "\tWelcome to 'Guess my Number'!"
print "\nI'm Thinking of a Number between 1 and 100."
print "\nTry to Guess it in as few attempts as possible.\n"

#Set the initial values
the_number = random.randrange(100) + 1
guess = int(raw_input("Take a guess:"))
tries = 1

#Guessing Loop

while (guess != the_number):
if (guess >the_number):
print "Lower..."
else:
print "Higher..."
guess = int(raw_input("Take another Guess:"))
tries +=1
if tries == 5:
print "Sorry you lose."
print "The Correct Number was ", the_number


print "You guess correctly!!"
print "The number was:", the_number
print "You got it correct in", tries, "tries"

raw_input("Press Enter to exit the program")
 
M

mensanator

Chad said:
Hi all, I am new to the group. Trying to learn Python programming on my
own. I am working through Michael Dawson's Book Python Programming for the
absolute beginner.

I am tring to write a program that is a number guessing game. I want to be
able to give the user 5 tries to guess the number before the program ends.

I get the result that I want when the user misses after the 5th try. But it
does not go down to my closing statement to end. Rather is askes for
another guess.

Because even after 5 tries, guess != the_number. You won't get past
the while loop until it does. When there have been 5 misses, try
setting
guess=the_number.
 
J

jmdeschamps

Because even after 5 tries, guess != the_number. You won't get past
the while loop until it does. When there have been 5 misses, try
setting
guess=the_number.

here is your corrected version:
##FROM here it's good
import random

print "\tWelcome to 'Guess my Number'!"
print "\nI'm Thinking of a Number between 1 and 100."
print "\nTry to Guess it in as few attempts as possible.\n"

#Set the initial values
## Here you always get 100, randrange is from start to end+1
the_number = random.randrange(0,101)
##This is OK
guess = int(raw_input("Take a guess:"))
tries = 1

#Guessing Loop

while (guess != the_number):
if (guess >the_number):
print "Lower..."
else:
print "Higher..."
guess = int(raw_input("Take another Guess:"))
tries +=1
if tries == 5:
## Missing break to explicitly leave loop after 5
break
## Then test to see if last guess equals the_number
if guess != the_number:
print "Sorry you lose."
print "The Correct Number was ", the_number
else:
print "You guess correctly!!"
print "The number was:", the_number
print "You got it correct in", tries, "tries"

raw_input("Press Enter to exit the program")
 
S

Steve Holden

Chad said:
Hi all, I am new to the group. Trying to learn Python programming on my
own. I am working through Michael Dawson's Book Python Programming for the
absolute beginner.

I am tring to write a program that is a number guessing game. I want to be
able to give the user 5 tries to guess the number before the program ends.

I get the result that I want when the user misses after the 5th try. But it
does not go down to my closing statement to end. Rather is askes for
another guess.

I appreciate any help you can give. If this is not the correct group for
these types of questions, I apologize and hope that you can direct me to
another NG.

Thanks,
Chad

import random

print "\tWelcome to 'Guess my Number'!"
print "\nI'm Thinking of a Number between 1 and 100."
print "\nTry to Guess it in as few attempts as possible.\n"

#Set the initial values
the_number = random.randrange(100) + 1
guess = int(raw_input("Take a guess:"))
tries = 1

#Guessing Loop

while (guess != the_number):
if (guess >the_number):
print "Lower..."
else:
print "Higher..."
guess = int(raw_input("Take another Guess:"))
tries +=1
if tries == 5:
print "Sorry you lose."
print "The Correct Number was ", the_number


print "You guess correctly!!"
print "The number was:", the_number
print "You got it correct in", tries, "tries"

raw_input("Press Enter to exit the program")
I don't personally think the two possible solutions you've been given
are very pythonic. All you really need to do to get the loop termination
conditions right (he says confidently, and with absolutely no testing at
all) is change the while line to

while guess != the_number and tries <=5:

but there are other things wrong with the program. In "pseudo-code"
(stuff that helps you think about the problem without being able to feed
it into an interpreter) your solution should be

while not guessed and guesses < 5
guess number
if guessed
congratulate user
else
crow and rub user's face in it

At present your code will always tell the user she guessed correctly,
even after it's told her she lost. See if this (tested) rewrite makes
sense to you:


import random

print "\tWelcome to 'Guess my Number'!"
print "\nI'm Thinking of a Number between 1 and 100."
print "\nTry to Guess it in as few attempts as possible.\n"

#Set the initial values
the_number = random.randrange(100) + 1
guess = int(raw_input("Take a guess:"))
tries = 1

#Guessing Loop

while guess != the_number and tries < 5:
if (guess >the_number):
print "Lower..."
else:
print "Higher..."
guess = int(raw_input("Take another Guess:"))
tries +=1

if guess == the_number:
print "You guess correctly!!"
print "The number was:", the_number
print "You got it correct in", tries, "tries"
else:
print "Sorry you lose."
print "The Correct Number was ", the_number

regards
Steve
 
B

bonono

I would rather to do the loop as :

max_try = 5
for x in xrange(max_try):
g = int(raw_input(["Take a guess","Take another guess"][x != 0]))
if g == number:
print "bingo, hit it in %i tries" % x + 1
break
elif g < number: print "try higher"
else: print "try lower"
else: print "sorry, you lose, the number is %i" % number
 
J

jmdeschamps

## Here you always get 100...

This is false , sorry for the wrong comment on this part, it should
rather be:
## randrange is from start to end-1
the_number = random.randrange(1,101)
JM
(But the rest of my comment seems OK)
 
N

Norman Silverstone

:
< snip >

I am also working my way slowly through this book which I find quite
challenging. What I am thinking about at the moment is how to program for
the computer to guess the number which I select. I know it can be done but
I suspect it requires an approach which I have not yet learnt. I would
welcome suggestions on the best way to approach this problem.

Norman
 
C

Chad Everett

Hey guys,

Thanks for your help. I am glad to know there is a community out there
willing to put the effort out to help us newbies. I will work on it. Some
of the suggestions are things that I have not covered yet but I am sure I
will figure it out.

Thanks again.

I am sure I will be back with more questions before too long.

Chad
 
A

Alex Martelli

Norman Silverstone said:
challenging. What I am thinking about at the moment is how to program for
the computer to guess the number which I select. I know it can be done but
I suspect it requires an approach which I have not yet learnt. I would
welcome suggestions on the best way to approach this problem.

I assume the way the computer is going to guess is by trying some
number, and you respond either that it's guessed right, or to go lower,
or to go higher.

In that case, think of "bisection". Originally, all the computer knows
is that the number is in some range, say 0 to 100. It can then guess
the midpoint, 50. If it's right, yay! Otherwise: if it's told to go
lower, then the range is now 0 to 49 -- if higher, it's 51 to 100; in
each case the range was just halved (actually, a bit more than halved).

It does not take many halvings to squeeze even a pretty large original
range down to a range which only includes one possible number... that's
because "2 to the power of N" grows VERY fast with N, as the old story
about the inventor of chess shows (the king told him to ask for a
reward, and all he wanted was some rice -- one grain on the first cell
of the chessboard, two on the next, then four, eight... all the way
through the 64 squares of the board; the kind thought the inventor was
being very moderate in his request, and granted it... to soon find out
that not enough rice existed in the world to satisfy the request...;-).

Well, repeated halving is just like repeated doubling "backwards", so it
squeezes vast ranges of possibilities down to tiny ones just as fast as
repeated doubling produces oceans of rice from a small chessboard;-).


Alex
 
N

Norman Silverstone

I assume the way the computer is going to guess is by trying some
number, and you respond either that it's guessed right, or to go lower,
or to go higher.

Yes, that is correct.
In that case, think of "bisection". Originally, all the computer knows
is that the number is in some range, say 0 to 100. It can then guess
the midpoint, 50. If it's right, yay! Otherwise: if it's told to go
lower, then the range is now 0 to 49 -- if higher, it's 51 to 100; in
each case the range was just halved (actually, a bit more than halved).

Thank you, I thought that might be the case. So, I will have to settle
down and try to write some pseudo-code first. I hope to be back.

Norman
 
S

Steven D'Aprano

Thank you, I thought that might be the case. So, I will have to settle
down and try to write some pseudo-code first. I hope to be back.

Heh, you will find that Python is practically executable pseudo-code!

Untested:


def guess_number():
# please don't cheat the poor computer...
print "Guess a number."
lo = 0
hi = 100
while True:
guess = (lo+hi)//2
ans = raw_input("Is it %d? y/n " % guess)
if ans in ('y', 'yes'):
break
ans = raw_input("Too high? y/n ")
if ans in ("y", "yes"):
hi = guess-1
else:
lo = guess+1

This should run, and it will *almost* do what you want.
 
N

Norman Silverstone

Heh, you will find that Python is practically executable pseudo-code!

Untested:


def guess_number():
# please don't cheat the poor computer...
print "Guess a number."
lo = 0
hi = 100
while True:
guess = (lo+hi)//2
ans = raw_input("Is it %d? y/n " % guess)
if ans in ('y', 'yes'):
break
ans = raw_input("Too high? y/n ")
if ans in ("y", "yes"):
hi = guess-1
else:
lo = guess+1

This should run, and it will *almost* do what you want.

Thanks for that but I think it is too simplistic. It appears OK for the
first guess, which is 50 but, what about the next guess. If the guess is
too high then the next guess has to be 50/2. However, if it is too low
then the next guess must be first guess + (100-second guess)/2. In general
terms, if guess is too high then next guess must (guess - lowest
possible)/2 and if too low then it is guess + (highest possible -
guess)/2.

Comments please.

Norman
 
S

Steve Holden

Norman said:
Thanks for that but I think it is too simplistic. It appears OK for the
first guess, which is 50 but, what about the next guess. If the guess is
too high then the next guess has to be 50/2. However, if it is too low
then the next guess must be first guess + (100-second guess)/2. In general
terms, if guess is too high then next guess must (guess - lowest
possible)/2 and if too low then it is guess + (highest possible -
guess)/2.

Comments please.

Norman
Effectively you want to start with a minposs and maxposs, which are set
to 0 and 100 respectively. Your guess should bisect the range (as nearly
as it can given that you are dealing with integers, and you have to be
careful to get the awkward boundary conditions right). So your first
guess will be 50. If your guess is too low then replace minposs with
your guess (in this case 50); if too high, replace maxposs with your
guess; loop to generate the next guess, and so on. In practice since
log2(100) > 5 your five guesses won't always be enough (though seven
should be).

Hope this helps.

regards
Steve
 
F

Fredrik Lundh

Norman said:
Thanks for that but I think it is too simplistic. It appears OK for the
first guess, which is 50 but, what about the next guess.

did you test the script?


If the guess is
 
F

Fredrik Lundh

Norman said:
Thanks for that but I think it is too simplistic. It appears OK for the
first guess, which is 50 but, what about the next guess.

did you test the script? here's a simulator:

import re

number = 0
guess = None
count = 0

def raw_input(prompt):
global count, guess
reply = "n"
m = re.search("\d+", prompt)
if m:
# guess a number
count = count + 1
guess = int(m.group())
if guess == number:
reply = "y"
else:
# check if too high
if guess > number:
reply = "y"
print prompt, reply
return reply

def guess_number():
# please don't cheat the poor computer...
print "Guess a number."
lo = 0
hi = 100
while True:
guess = (lo+hi)//2
ans = raw_input("Is it %d? y/n " % guess)
if ans in ('y', 'yes'):
break
ans = raw_input("Too high? y/n ")
if ans in ("y", "yes"):
hi = guess-1
else:
lo = guess+1

for number in range(0, 100+1):
print "NUMBER IS", number
count = 0
guess_number()
print "SUCCESS AFTER", count, "GUESSES"

# end
Comments please.

if this had been a java "let's pretend you're the java runtime" certification
question, you would have failed.

</F>
 
D

Dennis Lee Bieber

Thanks for that but I think it is too simplistic. It appears OK for the
first guess, which is 50 but, what about the next guess. If the guess is
too high then the next guess has to be 50/2. However, if it is too low
then the next guess must be first guess + (100-second guess)/2. In general
terms, if guess is too high then next guess must (guess - lowest
possible)/2 and if too low then it is guess + (highest possible -
guess)/2.
I'm having trouble following that -- I think you may be complicating
things more than you need to...

The basic algorithm only needs to know the "current" low and high
end of the range.

new_guess = (current_low + current_high) / 2

Match: break out of loop, with a successful guess
Low: current_low = new_guess; repeat #could be new_guess +1
#as you know it can not
#be "new_guess"
High: current_high = new_guess; repeat #or new_guess-1


Say the number is 78
low high guess result
0 100 (0+100)/2 => 50 LOW
50 100 (50+100)/2 => 75 LOW
75 100 (75+100)/2 => 88 HIGH (rounded up)
75 88 (75+88)/2 => 82 HIGH (rounded up)
75 82 (75+82)/2 => 79 HIGH (rounded up)
75 79 (75+79)/2 => 77 LOW
77 79 (77+79)/2 => 78 MATCH

NOTE: if you use the +1/-1 adjustments (to eliminate the guess
itself from being an end-point, as you know it can not be that value)
the above will converge to a match one step sooner.
--
 
S

Steven D'Aprano

Effectively you want to start with a minposs and maxposs, which are set
to 0 and 100 respectively. Your guess should bisect the range (as nearly
as it can given that you are dealing with integers, and you have to be
careful to get the awkward boundary conditions right). So your first
guess will be 50. If your guess is too low then replace minposs with
your guess (in this case 50); if too high, replace maxposs with your
guess; loop to generate the next guess, and so on. In practice since
log2(100) > 5 your five guesses won't always be enough (though seven
should be).

Dude, that's what my code does, although I admit I took zero care to get
the awkward boundary conditions right, nor did I put code in to stop the
game after five attempts.
 
F

Fredrik Lundh

Steven said:
Dude, that's what my code does, although I admit I took zero care to get
the awkward boundary conditions right, nor did I put code in to stop the
game after five attempts.

as my simulator shows, your code needs 5.87 attempts to make a correct
guess, on average.

if you add a 5-guess limit, it will find the right number only in 30% of all
runs. here's a complete list of (max number of guesses; % chance that
you'll find the right answer given an even distribution of target numbers)

1 1.0
2 3.0
3 6.9
4 14.9
5 30.7
6 62.4
7 100.0

fwiw, you may improve things slightly by special-casing the first guess:

http://www.pomona.edu/Magazine/pcmfl00/1.shtml

</F>
 
N

Norman Silverstone

did you test the script? here's a simulator:

< snip>

Fredrik, thank you very much indeed for taking the trouble to show me the
way. I am sorry that I made the comment I did, that will teach me to read
more carefully. It is said that there is no fool like an old fool and, as
I am approaching 78 years old, I think I qualify. It is also said that you
are never too old to learn so I am trying.

Now, I put the script you gave into an editor and ran it , (I use Ubuntu
Linux by the way). It certainly showed how the computer arrived at the
number guessed but guessed the number itself and gave me no chance to say
whether high or low. I noticed also that the numbers were all greater than
50 and the loop ran until the number guessed was 100, then it stopped.
Perhaps you can point out to me how I should go about debugging.

Incidentally, I am only just starting to learn about functions and have
not come across the module 're'. Also why is it (lo+hi)//2 and not
(lo+hi)/2.

Thanks again for your help.

Norman
 
A

Alex Martelli

Norman Silverstone said:
Incidentally, I am only just starting to learn about functions and have
not come across the module 're'. Also why is it (lo+hi)//2 and not
(lo+hi)/2.

Using // ensures truncation, which is what you want. A single / may mean
truncating division in the default legacy/compatibility mode, but with
the new division behavior (which one day will become standard) it means
true division, so that for example 1/2 means 0.5 -- better get used to
the new behavior ASAP (which is why you can ask for new division
behavior with -Qnew on Python's commandline or 'from __future__ import
division' at the top of your module -- to help you get used to it).


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top