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