# Probable Iterations (#141)

**URL:** <https://www.ruby-forum.com/t/probable-iterations-141/116321>\
**Category:** Ruby\
**Created:** [October 4, 2007, 2:15pm UTC](https://www.ruby-forum.com/t/probable-iterations-141/116321 "2007-10-04T14:15:14Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![bbazzarrakk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/47e85d/32.png) [@bbazzarrakk](https://www.ruby-forum.com/u/bbazzarrakk)\
**Post date:** [October 4, 2007, 2:15pm UTC](https://www.ruby-forum.com/t/probable-iterations-141/116321/1 "2007-10-04T14:15:14Z")

</div>

As a couple of solvers noted, this is an easy problem that’s really just  
about  
counting. In fact, you can solve the entire problem without ever  
rolling a die.

The trick is really in how you think about the problem. Basically we  
want to  
enumerate all of the possible rolls from:

[1, 1, 1, 1, 1, 1]

to:

[6, 6, 6, 6, 6, 6]

Let me show you that one more time though, minus some Ruby syntax  
characters:

111111 to 666666

Now it starts to look like counting, right? It almost is. If we  
counted  
straight between those two numbers though, we would pick up some digits  
that  
aren’t on our dice. But if we drop the digits on both sides by one:

000000 to 555555

Now that is counting, in base six, and it’s just a quick transliteration  
to  
adjust the digits up. We’re going to look at a solution that does just  
that.

While I put the code together that I’m going to show you, it’s heavily  
inspired  
from many of the submissions I liked. Let’s just say that this week’s  
showcased  
solution belongs to everyone.

Here’s the argument processing code:

#!/usr/bin/env ruby -wKU

MODE = if ARGV.first =~ /-([sv])/  
ARGV.shift  
$1  
end

unless ARGV.size == 2  
abort “Usage: #{File.basename($PROGRAM\_NAME)} [-s|-v] NUM\_DICE  
MIN\_FIVES”  
end  
NUM\_DICE, MIN\_FIVES = ARGV.map { |n| Integer(n) }

# …

This code should be pretty easy to break down. We check to see if the  
first  
argument looks like a switch and store it in the MODE constant when it  
does.  
Note that the code doesn’t provide an else branch for this check, but  
Ruby will  
default the constant to nil for us when the if condition fails to match.

The next bit of code just ensures that we have the two required  
arguments,  
converts them or throws an error if they are not what we expected, and  
stores  
them in constants for future use.

We’re now ready for the counting code:

# …

desirable\_outcomes = 0  
POSSIBLE\_OUTCOMES = 6 \*\* NUM\_DICE

POSSIBLE\_OUTCOMES.times do |i|  
outcome = i.to\_s(6).rjust(NUM\_DICE, “0”)  
if desirable = outcome.count(“4”) \>= MIN\_FIVES  
desirable\_outcomes += 1  
end  
if MODE == “v” or (MODE == “s” and (i % 50\_000).zero?)  
puts “%#{NUM\_DICE}d [%s]#{’ \<==’ if desirable}” %  
[i + 1, outcome.tr(“0-5”, “1-6”).gsub(/(\d)(\d)/, ‘\1,\2’)]  
end  
end

# …

This is the heart of the code and, as you can see, still quite simple.  
We begin  
by defining the range we will iterate over, from zero to the maximum  
count on  
the requested number of dice.

The times() iterator does the actual count. Remember that we really  
want these  
numbers in base six. The first line of the iterator does the  
conversion,  
padding with zeros to ensure we have the right number of “dice.”

The first if branch is our test for the minimum number of fives. When  
found, we  
bump a global counter that can later be used to generate results.

The final if statement handles printing for either of the inspection  
modes. If  
we’re in verbose mode, or sample mode and on a 50,000th iteration, the  
code  
prints the result index, the dice values, and an indicator arrow for  
rolls that  
were flagged as desirable. This is where you see the code to bump all  
of the  
digits so they will match pips on a die.

The final bit of code, just prints the results:

# …

puts if MODE  
puts “Number of desirable outcomes is #{desirable\_outcomes}”  
puts “Number of possible outcomes is #{POSSIBLE\_OUTCOMES}”  
puts  
puts “Probability is #{desirable\_outcomes / POSSIBLE\_OUTCOMES.to\_f}”

This is as easy as it gets. We show the desirable, the possible, and  
calculate  
the odds from the two of them. The first line just sneaks in a line of  
padding  
between any sampling and the end results.

Again, this code combined things I liked from many of the solutions, so  
they are  
definitely worth a look. Especially don’t miss Alex LeDonne’s second  
solution  
which uses some math to skip counting at all, when it can get away with  
it.

As always, my thanks to all who took the time to solve this quiz. I  
feel like  
we always get creative results for the simple problems.

Tomorrow we will tackle one of the all time famous tough problems, and  
see if we  
just can’t solve it reasonably well with minimal knowledge of the  
domain…
