# Panagrams (#86)

**URL:** <https://www.ruby-forum.com/t/panagrams-86/97515>\
**Category:** Ruby\
**Created:** [July 7, 2006, 5:03pm UTC](https://www.ruby-forum.com/t/panagrams-86/97515 "2006-07-07T17:03:29Z")\
**Posts on this page:** 1\
**Page:** 3

<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:** [July 12, 2006, 12:23am UTC](https://www.ruby-forum.com/t/panagrams-86/97515/41 "2006-07-12T00:23:21Z")

</div>

require “integer”

class Pangrams  
TIMES = 10000  
def pos\_add(str, arr26)  
(0…str.length).each do |i|  
next if (str[i]\< “a”[0])||(str[i]\>“z”[0])  
arr26[str[i]-“a”[0]]+=1  
end  
arr26  
end

def initialize  
@cardinals = Array.new(50) {|i| i.to\_i.to\_english }  
@ref\_array = []  
@cardinals.each do |num\_str|  
pos\_vec = Array.new(26, 0)  
pos\_vec = self.pos\_add(num\_str, pos\_vec)  
pos\_vec[“s”[0]-“a”[0]] += 1 unless num\_str == “one”  
@ref\_array \<\< pos\_vec  
end  
end

def do\_pangram  
@start\_str = "This is Nasir’s pangram and the count is "  
@start\_str\_cnt\_arr = Array.new(26, 0)  
@start\_str\_cnt\_arr = self.pos\_add(@start\_str, @start\_str\_cnt\_arr)  
@char\_cnt\_arr = Array.new(26, 0)  
#@nchar\_cnt\_arr = Array.new(26, 0)  
srand  
#0.upto(25) {|x| @char\_cnt\_arr[x]=rand(@cardinals.length) } #init  
loop do  
0.upto(25) {|x| @char\_cnt\_arr[x]=rand(@cardinals.length) } #init  
TIMES.times do  
val = true  
0.upto(25) do |idx|  
t = self.evaluate\_at(idx)  
val &&= t  
end  
if val  
puts “Solution found!”  
puts print(@start\_str, @char\_cnt\_arr)  
exit  
end  
end  
puts “#{TIMES} mark”  
0.upto(25) do |idx|  
puts “At #{idx} current=#{@char\_cnt\_arr[idx]}, actual=#{  
self.count\_char\_at(idx)}”  
end  
puts “-----------------------------------”  
end  
end # do\_pangram

def evaluate\_at(idx)  
current\_cnt = @char\_cnt\_arr[idx]  
actual\_cnt = self.count\_char\_at(idx)  
ret = true  
if current\_cnt != actual\_cnt  
#printf("\*")  
v1 = current\_cnt - ((current\_cnt-actual\_cnt)\*rand).round  
v2 = current\_cnt - ((current\_cnt-actual\_cnt)\*rand).round  
if actual\_cnt \> current\_cnt  
@char\_cnt\_arr[idx] = [v1,v2].max  
else  
@char\_cnt\_arr[idx] = [v1,v2].min  
end  
ret = false

```
end
ret

```

end

# index in char\_cnt\_arr, ‘a’ is 0 ‘z’ is 25

# Gives the current count of the character in the string

def count\_char\_at(i)  
count = @start\_str\_cnt\_arr[i] # assume only orig string for start  
count += 1 # always 1a, 1b etc  
@char\_cnt\_arr.each do |cnt|  
count += (@ref\_array[cnt])[i] #ref\_arr[0] is zero  
end  
count  
end

def print(str, arr)  
my\_str = str  
fmts = "%s %c, "  
fmtp = "%s %c’s, "  
arr.each\_with\_index do |elm, i|  
if elm==1  
my\_str \<\< sprintf(fmts, @cardinals[elm], 97+i)  
else  
my\_str \<\< sprintf(fmtp, @cardinals[elm], 97+i)  
end  
end  
yield my\_str if block\_given?  
my\_str  
end

end #class

p = Pangrams.new  
p.do\_pangram

=begin  
This re-uses quiz #25’s solution by Glenn PArker.  
The algorithm looks simple enough but there is something wrong with this  
implementation that it does not converge, sometimes never.  
Going by the Pangram defintion I am just comparing the current (guessed)  
with actual (counted) and if different replacing the current with a  
random  
number between current and actual (inclusive) with a bias towards  
actual.  
This is what I understood it to be, but there is obviously something  
that I  
am missing as this is terribly inefficient. (Mostly going into orbits)  
You may notice that I have tried both changing current value one at a  
time  
and also accumulating changes in @nchar\_cnt\_arr and changing in one go.  
The  
convergence has been elusive in either case.  
One way for me is to start looking at other solutions (which I will  
certainly do), but it would be a great help if someone points me towards  
a  
flaw in this.  
Also since I am new to Ruby, any general suggestion in Ruby usage will  
be  
greatly appreciated.

On a side note, has anyone tried any other algorithm besides RR?  
Specifically has anyone tried simulated annealing or a variation? I  
tried  
unsuccesfully (again) using SA yesterday.

=end

[Previous page](https://www.ruby-forum.com/t/panagrams-86/97515.md?page=2)
