Re: [Tutor] help with random.randint

2010-02-03 Thread Eike Welk
On Wednesday February 3 2010 12:26:43 David wrote:
> thanks for the explanation, all this is really helpful -- I certainly
> have learned sth. today!
> I wonder, though, how I would get my number pairs, which I need later
> on, if I were to follow your solution. I am asking because as I
> understand your code, the list terms is a list of integers here, but not
> of x,y pairs, right? (I can see that this was a problem of my code right
> from the start, btw.)

Maybe I don't understand you correctly; but if you know that you only need two 
random numbers I would create the list like this:

import random
xy = [random.randint(1, 99), random.randint(1, 99)]



Or maybe a use tuple and a little code beautification:

import random
randint = random.randint

xy = (randint(1, 99), randint(1, 99))



Off course you can put these small lists or tuples into another list:

import random
randint = random.randint

num_terms = 5
terms =  []
for i in range(num_terms):
 terms += [(randint(1, 99), randint(1, 99))]

print terms



Eike.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-03 Thread Wayne Werner
On Wed, Feb 3, 2010 at 5:26 AM, David  wrote:

> Hello Eike,
>
> thanks for the explanation, all this is really helpful -- I certainly have
> learned sth. today!
> I wonder, though, how I would get my number pairs, which I need later on,
> if I were to follow your solution. I am asking because as I understand your
> code, the list terms is a list of integers here, but not of x,y pairs,
> right? (I can see that this was a problem of my code right from the start,
> btw.)
>
> David


I'll refer you to what I posted in (what appeared to me as) your other
thread:

If you want the unique pairs (i.e. (12,7) is equivalent to (7,12)), I
*think* you can do a simple chain:

pool = []
for x in xrange(1,13):
for y in xrange(x, 13):
pool.append((x,y))

because that will give you the sets ordered by the smallest - you'll get
1x1-12, then 2x2-12, etc.

HTH,
Wayne
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint (cont. -- now: pseudo code)

2010-02-03 Thread Wayne Werner
On Wed, Feb 3, 2010 at 12:12 AM, David  wrote:

> def createQuestions:
>generate all multiplication combinations possible
>append as tuple to pool
>eliminate 'mirrored doubles' (i.e. 7x12 and 12x7)
>randomize pool
>
>
I haven't really looked through most of this stuff - but your mirrored
doubles has a somewhat cleaner solution than generating all then removing
the duplicates, I think.

Referring to here:
http://docs.python.org/reference/expressions.html#notin

I *think* you can create a list of all the non-mirrored pairs this way:

pool = []
for x in xrange(1,13):
for y in xrange(x, 13):
pool.append((x,y))

Then I would shuffle the pairs and the pairs within:

i.e.:

for x in xrange(len(pool)): # We want the index, not just the element
if random.randint(0,1):
 pool[x] = pool[x][::-1]# A simple reversal swaps the values
else:
pass

now you have two options - either shuffle your pool, or pick random elements
and pop them out of your list:

(this worked at least once on a 10 element list):

while pool:
pool.pop(random.randint(0, len(pool)-1)))

of course you'd probably assign that tuple to some useful value or function
call.

But that's what I'd do... and given the fact that I was actually planning to
make a "game" somewhat like this myself, this gives me a good excuse to
write some of the code ^_^

HTH, and thanks for asking a question that motivates,
Wayne
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-03 Thread David

Hello Eike,

thanks for the explanation, all this is really helpful -- I certainly 
have learned sth. today!
I wonder, though, how I would get my number pairs, which I need later 
on, if I were to follow your solution. I am asking because as I 
understand your code, the list terms is a list of integers here, but not 
of x,y pairs, right? (I can see that this was a problem of my code right 
from the start, btw.)


David

On 03/02/10 19:08, Eike Welk wrote:

Hello David!

On Wednesday February 3 2010 04:21:56 David wrote:


import random
terms =  []
for i in range(2):
terms = random.randint(1, 99)
print terms


Here is an other solution, which is quite easy to understand and short:

import random
terms =  []
for i in range(2):
 terms += [random.randint(1, 99)]
print terms


Note the rectangular brackets around "[random.randint(1, 99)]". This creates a
list which a single number in it. This small list can then be added to the
already existing list "terms".


Eike.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor



___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-03 Thread Eike Welk
Hello David!

On Wednesday February 3 2010 04:21:56 David wrote:
> 
> import random
> terms =  []
> for i in range(2):
>   terms = random.randint(1, 99)
> print terms

Here is an other solution, which is quite easy to understand and short:

import random
terms =  []
for i in range(2):
terms += [random.randint(1, 99)]
print terms


Note the rectangular brackets around "[random.randint(1, 99)]". This creates a 
list which a single number in it. This small list can then be added to the 
already existing list "terms".


Eike.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint (cont. -- now: pseudo code)

2010-02-03 Thread spir
On Wed, 03 Feb 2010 14:12:42 +0800
David  wrote:

> Hello Benno, list,
> 
> thanks for those clarifications, which, well, clarify things ;-)
> 
> This is my latest creation:
> 
> import random
> 
> def createTerms():
>  terms =  []
>  for i in range(2):
>  terms.append(random.randint(1, 99))
>  j = terms[0]
>  k = terms[1]
>  print "%3d\nx%2d" % (j, k)
> 
> createTerms()

I find 
   j,k = terms
clearer. (This will automagically unpack items from terms.)

> Which works. However, it merely prints a multiplication task. Anyway, 
> this was just a prelude. In the end, I want far more, namely to create, 
> ask, and verify some multiplication questions. Here is my pseudo code of 
> this little project:
> 
> 
> 
> pool = []
> correct = 0
> incorrect = 0
> 
> def createQuestions:
>  generate all multiplication combinations possible
>  append as tuple to pool
>  eliminate 'mirrored doubles' (i.e. 7x12 and 12x7)
Unneeded. Instead building all combinations looping with j=1..n & k=1..n, 
directly avoid duplicates using j=1..n & k=j..n. (not 100% sure, though)

>  randomize pool
> 
> def askQuestions:
>  for question in pool:
>  calculate solution
>  take answer from user
>  if user answer == solution:
>  correct += 1
>  remove question from pool
>  else:
>  incorrect += 1
> 
> def showStats:
>  print number of questions asked
>  print number of questions answered correctly
>  print percentage of correct answers
> 
> def askFaultyAnswers:
>  answer = raw_input("Try again the incorrect questions? (y/n) ")
>  if answer == "y":
>  aksQuestions()
>  else:
>  break
> 
> 
> createQuestions()
> askQuestions()
> showStats()
> askFaultyAnswers()
> print "good-bye!"
> 
> 
> 
> I think it is sensible to
> 
> * first create all possible solutions, then
> * kick out doublettes, and only then
> * ask questions
> 
> I have some questions though:
> 
> Is the overall structure and flow of this program okay? What are the 
> main problems you can spot immediately?
> 
> In the very end I would like to take this code as a basis for a wxPython 
> program. Are there any structural requirements I am violating here?

You should from start on organize your code into funcs that will be so-called 
"callback functions", meaning functions that will be called by user actions 
(typically button press). Hope it's clear. This does not prevent an OO 
structure of the code, indeed, the funcs can well be object methods if this 
matches the problem.

> If I want to limit the number of questions asked, say to 20, would I 
> operate with slicing methods on the randomised pool?

?

> How would you go about showing stats for the second run (i.e. the 
> FaultyAnswers)? Right now I am thinking of setting the global variables 
> correct and incorrect to 0 from _within_ askFaultyAnswers; then I would 
> run showStats() also from _within_ askFaultyAnswers. Good idea?

I would have a kind of overall "UserTest" object with methods generating and 
storing test data (numbers), asking questions and getting answers, recording 
and outputing results.
This is an OO point of view. You may organise things differently (but even then 
an OO pov sometimes helps structuring a pb).

Denis


la vita e estrany

http://spir.wikidot.com/
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-03 Thread spir
On Wed, 03 Feb 2010 11:21:56 +0800
David  wrote:

> Hello list,
> 
> I thought this was easy even for me, but I was wrong, I guess.
> Here is what I want to do: take two random numbers between 1 and 99, and 
> put them into a list.
> 
> import random
> terms =  []
> for i in range(2):
>   terms = random.randint(1, 99)
> print terms
> 
> This prints just one number (the last one generated in the loop?)

Yo, terms now refers to a simple integer. What you want is instead:
for i in range(2):
term = random.randint(1, 99)
terms.append(term)  # put new item at end of list
print terms


> So I tried to change line 4 to the following:
>   terms += random.randint(1, 99)

This is equivalent to
   terms = terms + random.randint(1, 99)
Because the first operand is a list, python won't do an addition (yes, the 
operator can be misleading, I would personly prefer eg '++' to avoid 
ambiguity), but a so-called "concatenation" (yes, that word is ugly ;-). This 
"glues" together 2 sequences (lists or strings). In this case, you get an error 
because the second operand is not a sequence.

Denis


la vita e estrany

http://spir.wikidot.com/
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint (cont. -- now: pseudo code)

2010-02-03 Thread Hugo Arts
On Wed, Feb 3, 2010 at 10:06 AM, David  wrote:
> Bob,
>
> brilliant stuff -- I am truly awed by this. Create a default-filled matrix
> and mark combinations used so as to take them out of the game? Wow. This is
> new to me.
>
> On 03/02/10 15:46, bob gailer wrote
>
>> def askQuestions(): # generate and ask questions:
>> for i in range(NQ):
>> while 1: # loop till we get an unused combo
>> x, y = [random.randint(1,MAX) for i in 'ab']
>> if mtable[x][y] == 1: # combo is available
>> break
>> askQuestion(x,y)
>> # indicate asked
>> mtable[x][y] = 0
>> mtable[y][x] = 0
>
> Here you lose me, though. Where does mtable come from, what does it do? You
> don't introduce it as a variable, and when I google it, nothing much comes
> of if...
>

I think mtable should be replaced by the pool variable defined at the
top. Then it makes sense. Second, I think a two-dimensional approach
is rather wasteful here, it's clearer and simpler to keep a list of
generated questions (you already do that anyway), and for each new
question answered, do:

if (x, y) in generated:
continue
else:
generated.append((x, y))


The random generating approach is more efficient if you're only going
to use a small subset of the possible set of questions. If you're
going to use almost the entire set, though, calculating them is more
efficient, since the random generator will come across more and more
duplicates as it fills up the array. Here's an alternative approach
that uses itertools.combinations to calculate all possible sequences
and then shuffles:

import itertools
import random

# maximum number and number of questions
MAX = 20
NQ = 10

def gen_questions():
# start at 2, since 0 * x and 1 * x aren't very interesting
q = list(itertools.combinations(range(2, MAX), 2))
random.shuffle(q)
return q

Note that, if MAX is high, it will take a very long time to generate
all possible questions. (1000 was a second or so on my computer, but
10.000 took longer than I was willing to wait). If you're not going to
use all of those questions, (and it's likely you won't, since a range
of ten numbers already provides 45 different questions), then the
random generation is better.

Hugo
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-03 Thread Hugo Arts
On Wed, Feb 3, 2010 at 8:19 AM, David  wrote:
> Hello Bob,
>
> thanks for your comments!
>
>
> On 03/02/10 14:51, bob gailer wrote:
>
>> or if you seek terseness:
>>
>> terms = [random.randint(1, 99) for i in 'ab']
>
> Do I understand correctly that 'ab' here merely serves to produce a 'dummy
> sequence' over which I can run the for loop?
>

That is correct. you could have used any two-character sequence. I
think the range(2) call is clearer and more pythonic though. And it's
not that much longer

Hugo
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint (cont. -- now: pseudo code)

2010-02-03 Thread David

Bob,

brilliant stuff -- I am truly awed by this. Create a default-filled 
matrix and mark combinations used so as to take them out of the game? 
Wow. This is new to me.


On 03/02/10 15:46, bob gailer wrote


def askQuestions(): # generate and ask questions:
for i in range(NQ):
while 1: # loop till we get an unused combo
x, y = [random.randint(1,MAX) for i in 'ab']
if mtable[x][y] == 1: # combo is available
break
askQuestion(x,y)
# indicate asked
mtable[x][y] = 0
mtable[y][x] = 0


Here you lose me, though. Where does mtable come from, what does it do? 
You don't introduce it as a variable, and when I google it, nothing much 
comes of if...


David
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint (cont. -- now: pseudo code)

2010-02-02 Thread bob gailer

David wrote:

[snip]


My suggestion (untested):

MAX = 12
NQ = 20 # of questions to ask

# create a 2 dimensional array of 1's
row = [1]*MAX
pool = [row[:] for i in range(MAX)]

incorrect = [] # store incorrectly answered combos here

def askQuestions():  # generate and ask questions:
 for i in range(NQ):
   while 1: # loop till we get an unused combo
 x, y = [random.randint(1,MAX) for i in 'ab']
 if mtable[x][y] == 1: # combo is available
   break
   askQuestion(x,y)
   # indicate asked
   mtable[x][y] = 0
   mtable[y][x] = 0
 showStats()

def askQuestion(x,y):
 solution = x*y
 # take answer from user
 ok =  user answer == solution
 if ok:
   correct += 1
 else:
   incorrect.append((x,y))
 return ok

def askFaultyAnswers():
 answer = raw_input("Try again the incorrect questions? (y/n) ")
 if answer == "y":
   correct = 0
   for x,y in incorrect:
 ok = askQuestion(x,y)
 # could use ok to remove combo from incorrect list.
 showStats()

askQuestions()
askFaultyAnswers()
print "good-bye!"






I think it is sensible to

* first create all possible solutions, then
* kick out doublettes, and only then
* ask questions

I have some questions though:

Is the overall structure and flow of this program okay? What are the 
main problems you can spot immediately


Calculating kicking randomizing is overkill. My code uses a 2 dimension 
array to track which x,y combos are available.


break is only valid within a loop.

Recursively calling askQuestions is not a good idea. Save recursion for 
when it is is meaningful. Use a loop instead.


There is no need for an incorrect counter. we can calculate it later 
(incorrect = NQ -correct)




In the very end I would like to take this code as a basis for a 
wxPython program. Are there any structural requirements I am violating 
here?


Not that I can see. It is common practice to separate logic from display.


If I want to limit the number of questions asked, say to 20, would I 
operate with slicing methods on the randomised pool?


My solution does not use a randomized pool. Just a loop over range(NQ)


How would you go about showing stats for the second run (i.e. the 
FaultyAnswers)? Right now I am thinking of setting the global 
variables correct and incorrect to 0 from _within_ askFaultyAnswers; 
then I would run showStats() also from _within_ askFaultyAnswers. Good 
idea?


Yes indeed. That is what I did before reading your comment! Great minds 
think alike.


--
Bob Gailer
919-636-4239
Chapel Hill NC

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-02 Thread David

Hello Bob,

thanks for your comments!


On 03/02/10 14:51, bob gailer wrote:


or if you seek terseness:

terms = [random.randint(1, 99) for i in 'ab']


Do I understand correctly that 'ab' here merely serves to produce a 
'dummy sequence' over which I can run the for loop?


David

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-02 Thread bob gailer

David wrote:

Hello list,

I thought this was easy even for me, but I was wrong, I guess.
Here is what I want to do: take two random numbers between 1 and 99, 
and put them into a list. 

[snip]

Or you can use list comprehension:

terms = [random.randint(1, 99) for i in range(2)]

or if you seek terseness:

terms = [random.randint(1, 99) for i in 'ab']


--
Bob Gailer
919-636-4239
Chapel Hill NC

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint (cont. -- now: pseudo code)

2010-02-02 Thread David

Hello Benno, list,

thanks for those clarifications, which, well, clarify things ;-)

This is my latest creation:

import random

def createTerms():
terms =  []
for i in range(2):
terms.append(random.randint(1, 99))
j = terms[0]
k = terms[1]
print "%3d\nx%2d" % (j, k)

createTerms()

Which works. However, it merely prints a multiplication task. Anyway, 
this was just a prelude. In the end, I want far more, namely to create, 
ask, and verify some multiplication questions. Here is my pseudo code of 
this little project:




pool = []
correct = 0
incorrect = 0

def createQuestions:
generate all multiplication combinations possible
append as tuple to pool
eliminate 'mirrored doubles' (i.e. 7x12 and 12x7)
randomize pool

def askQuestions:
for question in pool:
calculate solution
take answer from user
if user answer == solution:
correct += 1
remove question from pool
else:
incorrect += 1

def showStats:
print number of questions asked
print number of questions answered correctly
print percentage of correct answers

def askFaultyAnswers:
answer = raw_input("Try again the incorrect questions? (y/n) ")
if answer == "y":
aksQuestions()
else:
break


createQuestions()
askQuestions()
showStats()
askFaultyAnswers()
print "good-bye!"



I think it is sensible to

* first create all possible solutions, then
* kick out doublettes, and only then
* ask questions

I have some questions though:

Is the overall structure and flow of this program okay? What are the 
main problems you can spot immediately?


In the very end I would like to take this code as a basis for a wxPython 
program. Are there any structural requirements I am violating here?


If I want to limit the number of questions asked, say to 20, would I 
operate with slicing methods on the randomised pool?


How would you go about showing stats for the second run (i.e. the 
FaultyAnswers)? Right now I am thinking of setting the global variables 
correct and incorrect to 0 from _within_ askFaultyAnswers; then I would 
run showStats() also from _within_ askFaultyAnswers. Good idea?


Many thanks for your guidance and input!

David






On 03/02/10 12:25, Benno Lang wrote:

On Wed, Feb 3, 2010 at 12:21 PM, David  wrote:

Hello list,

I thought this was easy even for me, but I was wrong, I guess.
Here is what I want to do: take two random numbers between 1 and 99, and put
them into a list.

import random
terms =  []
for i in range(2):
terms = random.randint(1, 99)


All you're doing here is assigning an integer value to 'terms', twice.
This assignment means 'terms' is no longer a list, but is now just an
int. What you want is probably:
terms.append (random.randint(1, 99))


So I tried to change line 4 to the following:
terms += random.randint(1, 99)


You can't freely mix types with python operators, i.e. a_list += an_int
But you can use += with 2 ints or 2 lists, so you could do:
terms += [random.randint(1, 99)]
I think using append is much nicer though.


I understand this error thus: once an int has been placed into the list
terms, no further int can be added. But: terms is a mutable list, and NOT an
'int' object!


The int was never added to the list in the first place, because list
+= int is not something Python understands.


So here are my questions: what is the problem, and how can I generate two
random numbers and store them (preferably in a tuple)?


I hope what I wrote above answers the first question.
IIRC tuples are immutable, so you either to create the list first and
then convert it to a tuple:
terms_tuple = tuple(terms)

Or you can create a tuple from the beginning (without a loop):
terms_tuple = (random.randint(1, 99), random.randint(1, 99))

HTH,
benno



___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help with random.randint

2010-02-02 Thread Benno Lang
On Wed, Feb 3, 2010 at 12:21 PM, David  wrote:
> Hello list,
>
> I thought this was easy even for me, but I was wrong, I guess.
> Here is what I want to do: take two random numbers between 1 and 99, and put
> them into a list.
>
> import random
> terms =  []
> for i in range(2):
>        terms = random.randint(1, 99)

All you're doing here is assigning an integer value to 'terms', twice.
This assignment means 'terms' is no longer a list, but is now just an
int. What you want is probably:
terms.append (random.randint(1, 99))

> So I tried to change line 4 to the following:
>        terms += random.randint(1, 99)

You can't freely mix types with python operators, i.e. a_list += an_int
But you can use += with 2 ints or 2 lists, so you could do:
terms += [random.randint(1, 99)]
I think using append is much nicer though.

> I understand this error thus: once an int has been placed into the list
> terms, no further int can be added. But: terms is a mutable list, and NOT an
> 'int' object!

The int was never added to the list in the first place, because list
+= int is not something Python understands.

> So here are my questions: what is the problem, and how can I generate two
> random numbers and store them (preferably in a tuple)?

I hope what I wrote above answers the first question.
IIRC tuples are immutable, so you either to create the list first and
then convert it to a tuple:
terms_tuple = tuple(terms)

Or you can create a tuple from the beginning (without a loop):
terms_tuple = (random.randint(1, 99), random.randint(1, 99))

HTH,
benno
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor