------art_4902_10931800.1152723123419
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

I let it run overnight in two irb sessions (with two different starter
sentences) and they both finally converged - but I don't know how long it
took.
Looking at the other solutions, I think I have plenty to learn about Ruby -
especially when to modify an existing class, such as Integer or FixNum, and
when to just do it in the domain-specific class.  Everything here is in the
domain-specific class but could be simpler in others.

iteration 2860162:
My sentence contains three 'a's, one 'b', three 'c's, two 'd's, thirty 'e's,
five 'f's, four 'g's, eight 'h's, nine 'i's, one 'j', one 'k',
one 'l', two 'm's, twenty-one 'n's, seventeen 'o's, one 'p', one 'q', eight
'r's, twenty-four 's's, twenty-two 't's, four 'u's, three 'v's,
eight 'w's, two 'x's, six 'y's and one 'z'.

iteration 3224814:
 John's cool pangram program created this sentence which contains exactly
eight 'a's, one 'b', seven 'c's, three 'd's, forty-one 'e's, eight
 'f's, five 'g's, thirteen 'h's, twelve 'i's, two 'j's, one 'k', four 'l's,
three 'm's, twenty-two 'n's, seventeen 'o's, three 'p's, one 'q'
, fifteen 'r's, thirty-three 's's, twenty-six 't's, four 'u's, seven 'v's,
seven 'w's, four 'x's, six 'y's and one 'z'.

I haven't tried a French version yet but it would likely work...

#
require 'Win32API'  # for checking the keyboard to stop and show the
progress

EXAMPLE_SENTENCE  Darren's ruby panagram program found this sentence which
contains exactly
       nine 'a's, two 'b's, five 'c's, four 'd's, thirty-five 'e's, nine
'f's,
       three 'g's,  nine 'h's, sixteen 'i's, one 'j', one 'k', two 'l's,
three 'm's,
       twenty-seven 'n's, fourteen 'o's,  three 'p's, one 'q', fifteen 'r's,
       thirty-four 's's, twenty-two 't's, six 'u's, six 'v's, seven 'w's,
six 'x's,
       seven 'y's, and one 'z'."


class Pangram
  DEFAULT_SENTENCE  John's cool pangram program created this sentence
which contains exactly"
  ENGLISH_NUMBERS  w[? one two three four five six seven eight nine ten
eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen
twenty]
  ENGLISH_THIRTY_PLUS  w[thirty forty fifty sixty seventy eighty ninety]
  #this isn't quite right for french: 21 and 31 and 41 are "thirty and
one"...
  FRENCH_NUMBERS  w[? un deux trois quatre cinq six sept huit neuf dix
onze douze treize quatorze quinze seize dix-sept dix-huit dix-neuf vingt]
  FRENCH_THIRTY_PLUS  w[trente quarante cinquante soixante soixante-dix
quatre-vingt quatre-vingt-dix]
  MAX_COUNT  0

  attr_accessor :sentence

  # expect args to be [sentence,number_words,thirty_plus]
  def initialize *args
    @attempts  ash.new(nil)
    @sentence  rgs[0] || DEFAULT_SENTENCE
    @words  rgs[1] || ENGLISH_NUMBERS
    @words  words.dup
    @thirty_plus  rgs[1] || ENGLISH_THIRTY_PLUS
    count  0
    @thirty_plus.each do |word|
      @words[count]  ord
      count + 0
    end

    extend_wordlist MAX_COUNT
    #puts "@sentence@sentence}"
    # only add one the first time, all the others already have the extra one

    @result  etter_frequency @sentence
    @result.each { |k,v| @result[k] +  }
    #puts full_sentence( @result )
    self
  end

  def distance hash1, hash2
    dist  
    hash1.each { |k,v| dist + v - hash2[k]).abs }
    return dist
  end

  def approximate current, start
    # apply each letter-word to an empty list
    approximation  }
    "a".upto("z") { |c| approximation[c]  tart }
    current.each do |k,v|
      @words[current[k]].split('').each do |c|
        approximation[c] +  if approximation[c] and approximation[c] > 
      end
    end
    return approximation
  end

  def unique_solution sentence,count
    #puts "#{count}: cryptcrypt} for #{sentence}"
    if @attempts[sentence] ! il
      puts "Oops, we've already tried this solution! (#{count} 
#{@attempts[sentence]})"
      return nil
    else
      @attempts[sentence]  ount
      return 1
    end
  end

  def make_randomly_similar! dest, src
    diffs  "
    dest.each { |k,v| diffs +  if v ! rc[k] }
    c  iffs[ (rand * diffs.length).to_i ].chr
    dest[c]  rc[c]
  end

  def solve
    iteration  
    hash  }
    s  ull_sentence( @result )
    hash  etter_frequency( s )
    w  in32API.new( "MSVCRT", "_kbhit", [], 'i')
    io  O.new(0)
    while hash ! result ## and unique_solution(s,iteration) ! il
      iteration + 
      dist  istance( hash, @result )
      puts "#{iteration}: #{dist}"
      c  ake_randomly_similar! @result, hash
      #puts "iteration #{iteration}: #{dist},#{c} 
#{hash.sort.collect{|i| i[1] }.join(',') }"
      s  ull_sentence( @result )
      hash  etter_frequency( s )
      if w.Call() > 0
        io.getc
        puts "iteration #{iteration}: #{dist}  #{hash.sort.collect {|i|
"#{i[0]}>#{i[1]}" }.join(',') }"
        puts s
      end
    end
    puts "\nSOLVED!\n #{s}"
    puts "iteration #{iteration}: #{dist}  #{hash.sort.collect {|i| i[1]
}.join(',') }"
    show_freq letter_frequency(s)
  end

  def full_sentence hash
    s  sentence.rstrip + " "
    "a".upto("x") do |letter|
      s + o_letter_count( letter, hash[letter] ) + ", "
    end
    s + o_letter_count( "y", hash["y"] ) + " and "
    s + o_letter_count( "z", hash["z"] ) + "."
    return s
  end

  def to_letter_count letter, count
    ret  #{@words[count]} '#{letter}'"
    ret + s" if count > 1
    return ret
  end

  def extend_wordlist count
    0.upto(count) do |n|
      @words[n]  words[10*(n/10).floor] + '-' + @words[n % 10] unless
@words[n]
      #puts "#{n}: #{@words[n]}"
    end
  end

  def show_freq hash
    hash.sort.each { |k, v| puts "#{k}: #{v}" }
  end

  def letter_frequency *sentence
    s  entence[0] || @sentence
    s  .downcase.gsub(/^a-z/,'')
    s.gsub!(/ |,|'|-|\./,'')
    freq  ash.new(0)
    "a".upto("z") { |c| freq[c]   }
    s.split('').each { |c| freq[c] +  }
    freq
  end
end

------art_4902_10931800.1152723123419--