on writing a while loop for rolling two dice

dn PythonList at DancesWithMice.info
Sat Aug 28 18:42:28 EDT 2021


On 29/08/2021 08.46, Hope Rouselle wrote:
> Here's my solution:
> 
> --8<---------------cut here---------------start------------->8---
> def how_many_times():
>   x, y = 0, 1
>   c = 0
>   while x != y:
>     c = c + 1
>     x, y = roll()
>   return c, (x, y)

> 
> Why am I unhappy?  I'm wish I could confine x, y to the while loop.  The
> introduction of ``x, y = 0, 1'' must feel like a trick to a novice.  How
> would you write this?



> ram at zedat.fu-berlin.de (Stefan Ram) writes:
>> """Rolls two dice until both yield the same value.
>> Returns the number of times the two dice were rolled
>> and the final value yielded."""
>> roll_count = 0
>> while True:
>>     outcome = roll_two_dice()
>>     roll_count += 1
>>     if outcome[ 0 ]== outcome[ 1 ]: break
>> return roll_count, outcome[ 0 ]
> 
> You totally convinced me.  Thanks.


On the other hand...
whilst you expressed concern about the apparently disconnected 'set up'
necessary before the loop, this solution adds a "True/Forever" and a
"Break" construct, which some may deem not that much better (if at all)

The idea of abrogating the while-condition but then adding another
(disconnected) condition to break, seems to hold equal potential for
confusion. or the type of dissatisfaction which motivated the original
question!

Looking at that from the inside-out, the loop's contents perform two
functions: the rolling and counting (per Statement of Requirements), but
also a loop-controlling element. Thus the reader's question: "what does
this loop do?" is conflated with "how many times does it do it?".


Let's go completely off-the-rails, why not use a never-ending range() to
fuel a for-loop 'counter', and within that loop perform the dice-roll(s)
and decide if it is time to 'break'. The range replaces the "True". The
for-loops index or 'counter' will deliver the desired result.

Neat? No!
Readable? No!
An improvement over the while-True? Definitely not!
Yet, the mechanism is the same AND offers a built-in counter. Hmmm...


Returning to the concern:

x, y = 0, 1
c = 0

The first line is purely to ensure that the loop executes at least once,
ie the two assigned-values are not 'real'. Hence the disquiet!

Initiating the counter is unavoidable (@Chris' suggestion notwithstanding).

However, remember that Python (like decent DBs) has a concept (and an
idiom) of a value to be used when we don't (yet) know what the value
is/should be! Further that Python allows such a value to be used in
comparisons:

>>> None != None
False
>>> None == None
True

Leading to:

c, x, y = 0, None, None
while ...


Which solution reverts to the original loop-contents. which seem more
obvious and thus more readable. (YMMV!)

Simplicity over 'being clever'...
-- 
Regards,
=dn


More information about the Python-list mailing list