>> Huh.  I must say that when I saw your program, it wasn't at all what I
>> expected - namely, you are changing all 26 letters at once, and then
>> recalculating.  I had assumed you were doing one letter at a time,
>> which I found to be much, much faster than doing all 26 at once.
> 
> Ok, I will post my other version as soon as I'm home again.

Here is the second version (which was my first version):
--------------------------------------------------------------------
require 'narray'
class NArray; include Enumerable; end
srand(1)

NUMS = %w(no one two three four five six seven eight nine ten eleven) +
  %w(twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen)
TENS = [nil] + %w(teen twenty thirty forty fifty sixty seventy eighty ninety)

class Fixnum
  def to_english
    return NUMS[self] if self < 20
    return TENS[self / 10] if (self % 10).zero?
    TENS[self / 10] + '-' + NUMS[self % 10]
  end
end

class String
  def to_na
    count = NArray.byte(26)
    each_byte do |b|
      count[b - ?a] += 1 if b >= ?a and b <= ?z
      count[b - ?A] += 1 if b >= ?A and b <= ?Z
    end
    count
  end
end

text = "This is a pangram from simon, it contains "
number = (0..99).map{|i| i.to_english.to_na + (i > 1 ? 's' : '').to_na}
guess = NArray.byte(26).fill!(1)
real = guess + text.to_na + 'and'.to_na + (number[1] * 26)

i, r, g, changed = nil, nil, nil, true
while changed do
  changed = false
  26.times do |i|
    g = guess[i]
    r = real[i]
    if g != r
      real.sbt! number[g]
      guess[i] = g = (g < r ? g : r) + rand((g - r).abs + 1)
      real.add! number[g]
      changed = true
    end
  end
end

s = guess.zip([*(' a'..' z')]).map{|g, l| g.to_english + l + (g>1 ? "'s":"")}
result = text + s[0..-2].join(', ') + ' and ' + s.last + '.'

puts result
puts(result.to_na == guess)
--------------------------------------------------------------------

It's quite similar except the loop.

cheers

Simon