When I try to map out pi in colors with ChunkyPNG, I get many unexpected results

180 views Asked by At

I am trying to calculate pi and put it into a picture in ruby. It works up until lines 36 (where it doesn't write pi [without a decimal place] to file) and 63 (where it only writes the off white color to pi.png). As a side note, the program doesn't seem to be making the right number of digits of pi ($looptimes)

Here is my ruby file:

pi.rb

#get width and height of picture
p 'width of pi'
$w = gets.chomp.to_i

p 'height of pi'
$h = gets.chomp.to_i

$looptimes = $w*$h

#calculate pi
def pi

  q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
  dot = nil
  $looptimes.times do
    if 4*q+r-t < n*t
      yield n
      nr = 10*(r-n*t)
      n = ((10*(3*q+r)) / t) - 10*n
      q *= 10
      r = nr
    else
      nr = (2*q+r) * l
      nn = (q*(7*k+2)+r*l) / (t*l)
      q *= k
      t *= l
      l += 2
      k += 1
      n = nn
      r = nr
    end
  end
end

#create and write to file
File.new("pi.txt", 'w')
File.open("pi.txt", 'w') { |pitxt|
    pitxt.write(pi {|digit| print digit; $stdout.flush})}

def read_file(file_name)
    file = File.open(file_name, "r")
    data = file.read
    file.close
    return data
end

pinumber = read_file("./pi.txt")

    pinumber.to_s


require 'chunky_png'

#make picture
image = ChunkyPNG::Image.new($w,$h)
image.save('pi.png')
image = ChunkyPNG::Image.from_file('pi.png')

#draw pixels
for $pointw in 0...$w do
    for $pointh in 0...$h do
        for j in 0...$looptimes do
            if pinumber[j] = '0' 
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(244,244,244) 
                image.save('pi.png')
            elsif pinumber[j] = '1'
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(231,47,39) 
                image.save('pi.png')
            elsif pinumber[j] = '2'
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(241,176,102) 
                image.save('pi.png')
            elsif pinumber[j] = '3' 
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(255,228,15) 
                image.save('pi.png')
            elsif pinumber[j] = '4' 
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(18,154,47) 
                image.save('pi.png')
            elsif pinumber[j] = '5' 
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(126,188,209) 
                image.save('pi.png')
            elsif pinumber[j] = '6' 
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(3,86,155) 
                image.save('pi.png')
            elsif pinumber[j] = '7'
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(46,20,141) 
                image.save('pi.png')
            elsif pinumber[j] = '8' 
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(152,152,152) 
                image.save('pi.png')
            elsif pinumber[j] = '9'     
                image[$pointw,$pointh] = ChunkyPNG::Color.rgb(10,10,10) 
                image.save('pi.png')
            end
        end
    end
end

Please let me know if you have any ideas.

Also, are there any more efficient ways to do this? Thank you all for your help!

1

There are 1 answers

1
Neil Slater On BEST ANSWER

The write command, as you used it, would write the return value of pi to the file. The returned value from pi is not a string of digits, but the last value calculated inside the routine (which happens to always be the last assignment to r)

The closest fix (i.e. the least amount you need to change to get it to work) is to output the yielded digits to the file, which you are already doing with printing to stdout:

File.open("pi.txt", 'w') do |pitxt|
  pi do |digit| 
    print digit
    $stdout.flush
    pitxt.write digit
  end
end

This should at least get you the digits you need into the text file.

You have several more mistakes in your script. I suggest you take things more slowly (in fact I recommend you remove the image-writing code as it is, and have another go!) Feel free to ask more questions on SO as you progress. For your next question, instead of presenting the entire script and asking "what's wrong with this", try to write a simple isolated example that demonstrates what you are trying to do, and has a single thing that you cannot get to work. For example, now you already have the digits of pi correct, there is no need to ask about that code - the image-writing part should be able to cope with any string of digits. You may even find that putting examples together allows you to answer your own question.