bug-gnubg
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-gnubg] Crash running a commad file. Python Example


From: Michael Petch
Subject: Re: [Bug-gnubg] Crash running a commad file. Python Example
Date: Mon, 03 Jun 2013 17:35:52 -0600
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130509 Thunderbird/17.0.6

On 03/06/2013 1:45 AM, Ian Shaw wrote:
> Thanks for the example. Michael. It's so much easier when one has an
> example to use as a foundation. For example, I've never seen a loop
> iterating over two variables before; I'd have used a nested loop but
> this is both beautifully succinct and readable. -- Ian 

No problem. Having used Python for some time now I have found myself
using some of the standard import libraries to do some of the
processing. In this case itertools.combinations_with_replacement does
all the work to create a tuple of tuples containing the 21 different rolls.

In Python for loops and iteration generally occur on sequence types like
tuples and lists. Tuples are sequence (array) type objects that can't be
modified after creation. Lists can be modified and are more akin arrays
in other languages. Lists are surrounded by [] and tuples by () .
Generally lists are used to order similar types of data, and tuples are
meant to give structure to data. This isn't enforced so often people use
lists and tuples interchangeably.

With that being said, you can do this for assignments from tuples or lists.

name, age, birthday = ('Michael', 43, '1970-05-10')
print birthday, name, age

Output:

Michael 43 1970-05-10
1970-05-10 Michael 43

I put parentheses around the variables on the left hand side out of
habit, but this is the same:
(name, age, birthday) = ('Michael', 43, '1970-05-10')

If I had done this:

person = ('Michael', 43, '1970-05-10')

It would have assigned the whole tuple on the right side to the variable
'person'. I can then access each element of the tuple 'person' like this:

print person[0], person[1], person[2]

Elements of lists and tuples can be handled the same way. In all the
above I used a tuple, but I could have done it as a list. For example:

name, age, birthday = ['Michael', 43, '1970-05-10']
print birthday, name, age

Lists are enclosed in [] instead of ().

If you were now to execute this command (part of my 43Z-reply examples):

import itertools
print tuple(itertools.combinations_with_replacement (range(1,7), 2))

You would get a tuple of tuples that look like this:

((1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 2), (2, 3), (2, 4),
(2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4, 4), (4, 5), (4, 6),
(5, 5), (5, 6), (6, 6))

All 21 different rolls are represented, so all the leg work has been
done for us by itertools.combinations_with_replacement . range(1,7)
returns a list that looks like [1,2,3,4,5,6] which represents the unique
values allowed on each die. One disadvantage of
itertools.combinations_with_replacement is that this function is only
available in Python 2.7 and higher (GNUBG now ships with 2.7.x embedded) .

Like anything, there are many ways to arrive at the same result. Given
what we have seen above, we could have written the skeleton code of my
examples many different ways. For instance rather than using itertools.
combinations_with_replacement I could have done it the ugly way:

for roll in ((1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 2), (2,
3), (2, 4), (2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4, 4), (4,
5), (4, 6), (5, 5), (5, 6), (6, 6)):
    die1 = roll[0]
    die2 = roll[1]
    print die1, die2

Notice I used 'roll'. Each iteration retrieves the next tuple and then I
get the values for die1 and die2 from the 'roll' tuple. Since I can
extract values in tuples individually as shown earlier I can rewrite it as:

for die1, die2 in ((1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2,
2), (2, 3), (2, 4), (2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4,
4), (4, 5), (4, 6), (5, 5), (5, 6), (6, 6)):
    print die1, die2

As Ian mentioned previously most would probably use a nested loop to do
all this, and that works too:

for die1 in (1,2,3,4,5,6):
    for die2 in (1,2,3,4,5,6):
        if die1<=die2:
            print die1, die2

This would also process the 21 unique entries. The If statement gets rid
of the duplicates in this case. Without that we would have had all 36
possibilities.

The above can also be expressed as:

for die1 in range(1,7):
    for die2 in range(1,7):
        if die1<=die2:
            print die1, die2

Python has some advanced looping constructs that allow you to do this:

for (die1, die2) in [(x, y) for x in range(1,7) for y in range(1,7) if x
<= y]:
    print die1, die2

A list is being built between the [] with 2 nested for loops and the
roll tuple is only added to the list being generated if x<=y. Once the
list is built the outer for loop goes down the newly generated list of
tuples and does the processing.

-- 
Michael Petch
GNU Backgammon Developer
OpenPGP FingerPrint=D81C 6A0D 987E 7DA5 3219 6715 466A 2ACE 5CAE 3304




reply via email to

[Prev in Thread] Current Thread [Next in Thread]