on writing a while loop for rolling two dice

Hope Rouselle hrouselle at jevedi.com
Sat Sep 4 09:53:25 EDT 2021


Chris Angelico <rosuav at gmail.com> writes:

> On Fri, Sep 3, 2021 at 4:33 AM Hope Rouselle <hrouselle at jevedi.com> wrote:
>> Yeah.  Here's a little context.  I came across this by processing a list
>> of exercises.  (I'm teaching a course --- you know that by now, I
>> guess.)  So the first thing I observed was the equal volume of work
>> dedicated to while loops and for loops --- so I decided to compared
>> which appeared more often in a certain sample of well-written Python
>> code.  It turns out the for loop was much more frequent.  Students have
>> been reporting too much work in too little time, so I decided to reduce
>> the number of exercises involving while loops.  When I began to look at
>> the exercises, to see which ones I'd exclude, I decided to exclude them
>> all --- lol! --- except for one.  The one that remained was this one
>> about rolling dice until a satisfying result would appear.  (All other
>> ones were totally more naturally written with a for loop.)
>>
>> So if I were to also write this with a for-loop, it'd defeat the purpose
>> of the course's moment.  Besides, I don't think a for-loop would improve
>> the readability here.
>
> It's on the cusp. When you ask someone to express the concept of "do
> this until this happens", obviously that's a while loop; but as soon
> as you introduce the iteration counter, it becomes less obvious, since
> "iterate over counting numbers until this happens" is a quite viable
> way to express this. However, if the students don't know
> itertools.count(), they'll most likely put in an arbitrary limit (like
> "for c in range(100000000)"), which you can call them out for.
>
>> But I thought your protest against the while-True was very well put:
>> while-True is not too readable for a novice.  Surely what's readable or
>> more-natural /to someone/ is, well, subjective (yes, by definition).
>> But perhaps we may agree that while rolling dice until a certain
>> success, we want to roll them while something happens or doesn't happen.
>> One of the two.  So while-True is a bit of a jump.  Therefore, in this
>> case, the easier and more natural option is to say while-x-not-equal-y.
>
> That may be the case, but in Python, I almost never write "while
> True". Consider the two while loops in this function:
>
> https://github.com/Rosuav/shed/blob/master/autohost_manager.py#L92
>
> Thanks to Python's flexibility and efficient compilation, these loops
> are as descriptive as those with actual conditions, while still
> behaving exactly like "while True". (The inner loop, "more pages",
> looks superficially like it should be a for loop - "for page in
> pages:" - but the data is coming from successive API calls, so it
> can't know.)

That's pretty nice.  I did suggest the same to my students, showing your
code to them, actually.  The course explicitly avoided talking about
regular values being considered True, but now I couldn't keep the truth
from them.

>> I don't see it.  You seem to have found what we seem to agree that it
>> would be the more natural way to write the strategy.  But I can't see
>> it.  It certainly isn't
>>
>> --8<---------------cut here---------------start------------->8---
>> def how_many_times_1():
>>   c, x, y = 0, None, None
>>   while x != y:
>>     c = c + 1
>>     x, y = roll()
>>   return c, x, y
>> --8<---------------cut here---------------end--------------->8---
>>
>> nor
>>
>> --8<---------------cut here---------------start------------->8---
>> def how_many_times_2():
>>   c, x, y = 0, None, None
>>   while x == y:
>>     c = c + 1
>>     x, y = dados()
>>   return c, x, y
>> --8<---------------cut here---------------end--------------->8---
>>
>> What do you have in mind?  I couldn't see it.
>
> You're overlaying two loops here. One is iterating "c" up from zero,
> the other is calling a function and testing its results. It's up to
> you which of these should be considered the more important, and which
> is a bit of extra work added onto it. With the counter as primary, you
> get something like this:
>
> for c in itertools.count():
>     x, y = roll()
>     if x == y: return c, x, y
>
> With the roll comparison as primary, you get this:
>
> c, x, y = 0, 0, 1
> while x != y:
>     x, y = roll()
>     c += 1
> return c, x, y
>
> Reworking the second into a do-while style (Python doesn't have that,
> so we have to write it manually):
>
> c = 0
> while "x and y differ":
>     x, y = roll()
>     c += 1
>     if x == y: break
> return c, x, y
>
> And at this point, it's looking pretty much identical to the for loop
> version. Ultimately, they're all the same and you can pick and choose
> elements from each of them.

I see.  That's why C must have added the do-while, but yeah --- it's not
really worth it.  (An educational investigation.  Thank you.)


More information about the Python-list mailing list