From: Albert Ng Date: 2007-03-12T09:36:00+09:00 Subject: Re: [QUIZ] SimFrost (#117) ------=_Part_24090_5257072.1173659755826 Content-Type: multipart/alternative; boundary="----=_Part_24091_6790476.1173659755826" ------=_Part_24091_6790476.1173659755826 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline Right, here's the graphical version, using RMagick (thanks for the idea, Chris). Much improved from the last try, with bits and pieces stolen from many ppl. BTW, ImageMagic does not like 200x200 grids written bit by bit, just fyi... #!/usr/bin/env ruby -w class SimFrost require 'RMagick' VACUUM=" " #Chris Shea reminded me of constants... VAPOR="+" ICE="*" ICECOLOR='blue' VAPORCOLOR='grey' VACUUMCOLOR='white' attr_reader :grid, :vapor def initialize (width=30,height=24, vapor_percent=30, showvapor=true) @x_size=width/2*2 #this should take care of those odd numbers @y_size=height/2*2 @vapor_percent=vapor_percent @offset=1 @image = Magick::ImageList.new @showvapor=showvapor create_grid end def create_grid @grid=Array.new(@x_size){Array.new(@y_size)} @bitmap = Array.new(@x_size){Array.new(@y_size,0)} @grid.each_with_index do |row, x| row.each_with_index do |square, y| if rand(100) < @vapor_percent @grid[x][y]= VAPOR @bitmap[x][y]=1 if @showvapor else @grid[x][y]= VACUUM end end end @grid[@x_size/2][@y_size/2]=ICE @bitmap[@x_size/2][@y_size/2]=1 end def check_neighborhoods #interesting bits shamelessly stolen from Dave Burt @offset ^= 1 (@offset...@x_size).step(2) do |x0| (@offset...@y_size).step(2) do |y0| x1=(x0+1) % @x_size y1=(y0+1) % @y_size neighborhood=[@grid[x0][y0], @grid[x0][y1], @grid[x1][y0], @grid[x1][y1]] if neighborhood.include?(VAPOR) if neighborhood.include?(ICE) #there's got to be a rubyer way of doing this... if @grid[x0][y0] == VAPOR #top left corner @grid[x0][y0] = ICE @bitmap[x0][y0] = 1 end if @grid[x0][y1] == VAPOR #one right @grid[x0][y1] = ICE @bitmap[x0][y1] end if @grid[x1][y0] == VAPOR #one down @grid[x1][y0] = ICE @bitmap[x1][y0] end if @grid[x1][y1] == VAPOR #right and down @grid[x1][y1] = ICE @bitmap[x1][y1] = 1 end elsif rand(2)==1 @grid[x0][y0], @grid[x0][y1], @grid[x1][y0], @grid[x1][y1] = @grid[x1][y0], @grid[x0][y0], @grid[x1][y1], @grid[x0][y1] if @showvapor @bitmap[x0][y0], @bitmap[x0][y1], @bitmap[x1][y0], @bitmap[x1][y1] = 1, 1, 1, 1 end else #It's the correct sequence, maybe... I think... @grid[x0][y0], @grid[x0][y1], @grid[x1][y0], @grid[x1][y1] = @grid[x0][y1], @grid[x1][y1], @grid[x0][y0], @grid[x1][y0] if @showvapor @bitmap[x0][y0], @bitmap[x0][y1], @bitmap[x1][y0], @bitmap[x1][y1] = 1, 1, 1, 1 end end end end end end def to_s @grid.transpose.collect{|row| row.join}.join("\n") end def generate_gif something = false if @image.empty? @image.new_image(@x_size, @y_size) else @image << @image.last.copy end frame = Magick::Draw.new @grid.each_with_index do | row, x | row.each_with_index do |square, y| if @bitmap[x][y] == 1 if square == ICE frame.fill(ICECOLOR).point(x,y) something = true elsif square == VAPOR frame.fill(VAPORCOLOR).point(x,y) something = true elsif square == VACUUM frame.fill(VACUUMCOLOR).point(x,y) something = true end @bitmap[x][y] =0 end end end frame.draw(@image) if something puts "On to next frame" end def create_animation @image.write("frost_#{Time.now.strftime("%H%M")}.gif") end end s=SimFrost.new(200,200,40) step = 0 puts "Sit back, this may take a while" while s.grid.flatten.include?(SimFrost::VAPOR) #flatten inspired by James Edward Gray puts "Step #{step}: creating frame" s.generate_gif s.check_neighborhoods step += 1 end s.create_animation puts "Done" ------=_Part_24091_6790476.1173659755826 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline Right, here's the graphical version, using RMagick (thanks for the idea, Chris).
Much improved from the last try, with bits and pieces stolen from many ppl.
BTW, ImageMagic does not like 200x200 grids written bit by bit, just fyi...

#!/usr/bin/env ruby -w

class SimFrost
 
  require 'RMagick'
  VACUUM=" "    #Chris Shea reminded me of constants...
  VAPOR="+"
  ICE="*"
  ICECOLOR='blue'
  VAPORCOLOR='grey'
  VACUUMCOLOR='white'
  attr_reader :grid, :vapor
 
  def initialize (width=30,height=24, vapor_percent=30, showvapor=true)
    @x_size=width/2*2    #this should take care of those odd numbers
    @y_size=height/2*2
    @vapor_percent=vapor_percent
    @offset=1
    @image = Magick::ImageList.new
    @showvapor=showvapor
    create_grid
  end
 
  def create_grid
    @grid=Array.new(@x_size){Array.new(@y_size)}
    @bitmap = Array.new(@x_size){Array.new(@y_size,0)}
    @grid.each_with_index do |row, x|
      row.each_with_index do |square, y|
        if rand(100) < @vapor_percent
          @grid[x][y]= VAPOR
          @bitmap[x][y]=1 if @showvapor
        else
          @grid[x][y]= VACUUM
        end
      end
    end
    @grid[@x_size/2][@y_size/2]=ICE
    @bitmap[@x_size/2][@y_size/2]=1
  end
 
  def check_neighborhoods    #interesting bits shamelessly stolen from Dave Burt
    @offset ^= 1
    (@offset...@x_size).step(2) do |x0|
      (@offset...@y_size).step(2) do |y0|
        x1=(x0+1) % @x_size
        y1=(y0+1) % @y_size
        neighborhood=[@grid[x0][y0], @grid[x0][y1], @grid[x1][y0], @grid[x1][y1]]
        if neighborhood.include?(VAPOR)
          if neighborhood.include?(ICE)                              #there's got to be a rubyer way of doing this...
            if @grid[x0][y0] == VAPOR      #top left corner
              @grid[x0][y0] = ICE
              @bitmap[x0][y0] = 1
            end
            if @grid[x0][y1] == VAPOR     #one right
              @grid[x0][y1] = ICE
              @bitmap[x0][y1]
            end
            if @grid[x1][y0] == VAPOR     #one down
              @grid[x1][y0] = ICE
              @bitmap[x1][y0]
            end
            if @grid[x1][y1] == VAPOR     #right and down
              @grid[x1][y1] = ICE
              @bitmap[x1][y1] = 1
            end
          elsif rand(2)==1
            @grid[x0][y0], @grid[x0][y1], @grid[x1][y0], @grid[x1][y1] = @grid[x1][y0], @grid[x0][y0], @grid[x1][y1], @grid[x0][y1]
            if @showvapor
              @bitmap[x0][y0], @bitmap[x0][y1], @bitmap[x1][y0], @bitmap[x1][y1] = 1, 1, 1, 1
            end
          else        #It's the correct sequence, maybe...  I think...
            @grid[x0][y0], @grid[x0][y1], @grid[x1][y0], @grid[x1][y1] = @grid[x0][y1], @grid[x1][y1], @grid[x0][y0], @grid[x1][y0]
            if @showvapor
              @bitmap[x0][y0], @bitmap[x0][y1], @bitmap[x1][y0], @bitmap[x1][y1] = 1, 1, 1, 1
            end
          end
        end
      end
    end
  end
 
  def to_s
    @grid.transpose.collect{|row| row.join}.join("\n")
  end
 
  def generate_gif
    something = false
    if @image.empty?
      @image.new_image(@x_size, @y_size)
    else
      @image << @image.last.copy
    end
    frame = Magick::Draw.new
    @grid.each_with_index do | row, x |
      row.each_with_index do |square, y|
        if @bitmap[x][y] == 1
          if square == ICE
            frame.fill(ICECOLOR).point(x,y)
            something = true
          elsif square == VAPOR
            frame.fill(VAPORCOLOR).point(x,y)
            something = true
          elsif square == VACUUM
            frame.fill(VACUUMCOLOR).point(x,y)
            something = true
          end
          @bitmap[x][y] =0
        end
      end
    end
    frame.draw(@image) if something
    puts "On to next frame"
  end
 
  def create_animation
    @image.write("frost_#{Time.now.strftime("%H%M")}.gif")
  end 
end

s=SimFrost.new(200,200,40)
step = 0
puts "Sit back, this may take a while"
while s.grid.flatten.include?(SimFrost::VAPOR)  #flatten inspired by James Edward Gray
  puts "Step #{step}: creating frame"
  s.generate_gif
  s.check_neighborhoods
  step += 1
end
  s.create_animation
  puts "Done"
------=_Part_24091_6790476.1173659755826-- ------=_Part_24090_5257072.1173659755826 Content-Type: text/x-ruby-script; name=SimFrost2.rb; charset=ANSI_X3.4-1968 Content-Transfer-Encoding: base64 X-Attachment-Id: f_ez671n1c Content-Disposition: attachment; filename="SimFrost2.rb" IyEvdXNyL2Jpbi9lbnYgcnVieSAtdw0KDQpjbGFzcyBTaW1Gcm9zdA0KICANCiAgcmVxdWlyZSAn Uk1hZ2ljaycNCiAgVkFDVVVNPSIgIiAgICAjQ2hyaXMgU2hlYSByZW1pbmRlZCBtZSBvZiBjb25z dGFudHMuLi4NCiAgVkFQT1I9IisiDQogIElDRT0iKiINCiAgSUNFQ09MT1I9J2JsdWUnDQogIFZB UE9SQ09MT1I9J2dyZXknDQogIFZBQ1VVTUNPTE9SPSd3aGl0ZScNCiAgYXR0cl9yZWFkZXIgOmdy aWQsIDp2YXBvcg0KICANCiAgZGVmIGluaXRpYWxpemUgKHdpZHRoPTMwLGhlaWdodD0yNCwgdmFw b3JfcGVyY2VudD0zMCwgc2hvd3ZhcG9yPXRydWUpDQogICAgQHhfc2l6ZT13aWR0aC8yKjIgICAg I3RoaXMgc2hvdWxkIHRha2UgY2FyZSBvZiB0aG9zZSBvZGQgbnVtYmVycw0KICAgIEB5X3NpemU9 aGVpZ2h0LzIqMg0KICAgIEB2YXBvcl9wZXJjZW50PXZhcG9yX3BlcmNlbnQNCiAgICBAb2Zmc2V0 PTENCiAgICBAaW1hZ2UgPSBNYWdpY2s6OkltYWdlTGlzdC5uZXcNCiAgICBAc2hvd3ZhcG9yPXNo b3d2YXBvcg0KICAgIGNyZWF0ZV9ncmlkDQogIGVuZA0KICANCiAgZGVmIGNyZWF0ZV9ncmlkDQog ICAgQGdyaWQ9QXJyYXkubmV3KEB4X3NpemUpe0FycmF5Lm5ldyhAeV9zaXplKX0NCiAgICBAYml0 bWFwID0gQXJyYXkubmV3KEB4X3NpemUpe0FycmF5Lm5ldyhAeV9zaXplLDApfQ0KICAgIEBncmlk LmVhY2hfd2l0aF9pbmRleCBkbyB8cm93LCB4fA0KICAgICAgcm93LmVhY2hfd2l0aF9pbmRleCBk byB8c3F1YXJlLCB5fA0KICAgICAgICBpZiByYW5kKDEwMCkgPCBAdmFwb3JfcGVyY2VudCANCiAg ICAgICAgICBAZ3JpZFt4XVt5XT0gVkFQT1INCiAgICAgICAgICBAYml0bWFwW3hdW3ldPTEgaWYg QHNob3d2YXBvcg0KICAgICAgICBlbHNlIA0KICAgICAgICAgIEBncmlkW3hdW3ldPSBWQUNVVU0N CiAgICAgICAgZW5kDQogICAgICBlbmQNCiAgICBlbmQNCiAgICBAZ3JpZFtAeF9zaXplLzJdW0B5 X3NpemUvMl09SUNFDQogICAgQGJpdG1hcFtAeF9zaXplLzJdW0B5X3NpemUvMl09MQ0KICBlbmQN CiAgDQogIGRlZiBjaGVja19uZWlnaGJvcmhvb2RzICAgICNpbnRlcmVzdGluZyBiaXRzIHNoYW1l bGVzc2x5IHN0b2xlbiBmcm9tIERhdmUgQnVydA0KICAgIEBvZmZzZXQgXj0gMQ0KICAgIChAb2Zm c2V0Li4uQHhfc2l6ZSkuc3RlcCgyKSBkbyB8eDB8DQogICAgICAoQG9mZnNldC4uLkB5X3NpemUp LnN0ZXAoMikgZG8gfHkwfA0KICAgICAgICB4MT0oeDArMSkgJSBAeF9zaXplDQogICAgICAgIHkx PSh5MCsxKSAlIEB5X3NpemUNCiAgICAgICAgbmVpZ2hib3Job29kPVtAZ3JpZFt4MF1beTBdLCBA Z3JpZFt4MF1beTFdLCBAZ3JpZFt4MV1beTBdLCBAZ3JpZFt4MV1beTFdXQ0KICAgICAgICBpZiBu ZWlnaGJvcmhvb2QuaW5jbHVkZT8oVkFQT1IpDQogICAgICAgICAgaWYgbmVpZ2hib3Job29kLmlu Y2x1ZGU/KElDRSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjdGhlcmUncyBnb3QgdG8g YmUgYSBydWJ5ZXIgd2F5IG9mIGRvaW5nIHRoaXMuLi4NCiAgICAgICAgICAgIGlmIEBncmlkW3gw XVt5MF0gPT0gVkFQT1IgICAgICAjdG9wIGxlZnQgY29ybmVyDQogICAgICAgICAgICAgIEBncmlk W3gwXVt5MF0gPSBJQ0UNCiAgICAgICAgICAgICAgQGJpdG1hcFt4MF1beTBdID0gMQ0KICAgICAg ICAgICAgZW5kDQogICAgICAgICAgICBpZiBAZ3JpZFt4MF1beTFdID09IFZBUE9SICAgICAjb25l IHJpZ2h0DQogICAgICAgICAgICAgIEBncmlkW3gwXVt5MV0gPSBJQ0UNCiAgICAgICAgICAgICAg QGJpdG1hcFt4MF1beTFdDQogICAgICAgICAgICBlbmQNCiAgICAgICAgICAgIGlmIEBncmlkW3gx XVt5MF0gPT0gVkFQT1IgICAgICNvbmUgZG93bg0KICAgICAgICAgICAgICBAZ3JpZFt4MV1beTBd ID0gSUNFDQogICAgICAgICAgICAgIEBiaXRtYXBbeDFdW3kwXQ0KICAgICAgICAgICAgZW5kDQog ICAgICAgICAgICBpZiBAZ3JpZFt4MV1beTFdID09IFZBUE9SICAgICAjcmlnaHQgYW5kIGRvd24N CiAgICAgICAgICAgICAgQGdyaWRbeDFdW3kxXSA9IElDRSANCiAgICAgICAgICAgICAgQGJpdG1h cFt4MV1beTFdID0gMQ0KICAgICAgICAgICAgZW5kDQogICAgICAgICAgZWxzaWYgcmFuZCgyKT09 MQ0KICAgICAgICAgICAgQGdyaWRbeDBdW3kwXSwgQGdyaWRbeDBdW3kxXSwgQGdyaWRbeDFdW3kw XSwgQGdyaWRbeDFdW3kxXSA9IEBncmlkW3gxXVt5MF0sIEBncmlkW3gwXVt5MF0sIEBncmlkW3gx XVt5MV0sIEBncmlkW3gwXVt5MV0NCiAgICAgICAgICAgIGlmIEBzaG93dmFwb3INCiAgICAgICAg ICAgICAgQGJpdG1hcFt4MF1beTBdLCBAYml0bWFwW3gwXVt5MV0sIEBiaXRtYXBbeDFdW3kwXSwg QGJpdG1hcFt4MV1beTFdID0gMSwgMSwgMSwgMQ0KICAgICAgICAgICAgZW5kDQogICAgICAgICAg ZWxzZSAgICAgICAgI0l0J3MgdGhlIGNvcnJlY3Qgc2VxdWVuY2UsIG1heWJlLi4uICBJIHRoaW5r Li4uDQogICAgICAgICAgICBAZ3JpZFt4MF1beTBdLCBAZ3JpZFt4MF1beTFdLCBAZ3JpZFt4MV1b eTBdLCBAZ3JpZFt4MV1beTFdID0gQGdyaWRbeDBdW3kxXSwgQGdyaWRbeDFdW3kxXSwgQGdyaWRb eDBdW3kwXSwgQGdyaWRbeDFdW3kwXQ0KICAgICAgICAgICAgaWYgQHNob3d2YXBvcg0KICAgICAg ICAgICAgICBAYml0bWFwW3gwXVt5MF0sIEBiaXRtYXBbeDBdW3kxXSwgQGJpdG1hcFt4MV1beTBd LCBAYml0bWFwW3gxXVt5MV0gPSAxLCAxLCAxLCAxDQogICAgICAgICAgICBlbmQNCiAgICAgICAg ICBlbmQNCiAgICAgICAgZW5kDQogICAgICBlbmQNCiAgICBlbmQNCiAgZW5kDQogIA0KICBkZWYg dG9fcw0KICAgIEBncmlkLnRyYW5zcG9zZS5jb2xsZWN0e3xyb3d8IHJvdy5qb2lufS5qb2luKCJc biIpDQogIGVuZA0KICANCiAgZGVmIGdlbmVyYXRlX2dpZg0KICAgIHNvbWV0aGluZyA9IGZhbHNl DQogICAgaWYgQGltYWdlLmVtcHR5Pw0KICAgICAgQGltYWdlLm5ld19pbWFnZShAeF9zaXplLCBA eV9zaXplKQ0KICAgIGVsc2UNCiAgICAgIEBpbWFnZSA8PCBAaW1hZ2UubGFzdC5jb3B5DQogICAg ZW5kDQogICAgZnJhbWUgPSBNYWdpY2s6OkRyYXcubmV3DQogICAgQGdyaWQuZWFjaF93aXRoX2lu ZGV4IGRvIHwgcm93LCB4IHwNCiAgICAgIHJvdy5lYWNoX3dpdGhfaW5kZXggZG8gfHNxdWFyZSwg eXwNCiAgICAgICAgaWYgQGJpdG1hcFt4XVt5XSA9PSAxDQogICAgICAgICAgaWYgc3F1YXJlID09 IElDRQ0KICAgICAgICAgICAgZnJhbWUuZmlsbChJQ0VDT0xPUikucG9pbnQoeCx5KQ0KICAgICAg ICAgICAgc29tZXRoaW5nID0gdHJ1ZQ0KICAgICAgICAgIGVsc2lmIHNxdWFyZSA9PSBWQVBPUg0K ICAgICAgICAgICAgZnJhbWUuZmlsbChWQVBPUkNPTE9SKS5wb2ludCh4LHkpDQogICAgICAgICAg ICBzb21ldGhpbmcgPSB0cnVlDQogICAgICAgICAgZWxzaWYgc3F1YXJlID09IFZBQ1VVTQ0KICAg ICAgICAgICAgZnJhbWUuZmlsbChWQUNVVU1DT0xPUikucG9pbnQoeCx5KQ0KICAgICAgICAgICAg c29tZXRoaW5nID0gdHJ1ZQ0KICAgICAgICAgIGVuZA0KICAgICAgICAgIEBiaXRtYXBbeF1beV0g PTANCiAgICAgICAgZW5kDQogICAgICBlbmQNCiAgICBlbmQNCiAgICBmcmFtZS5kcmF3KEBpbWFn ZSkgaWYgc29tZXRoaW5nDQogICAgcHV0cyAiT24gdG8gbmV4dCBmcmFtZSINCiAgZW5kDQogIA0K ICBkZWYgY3JlYXRlX2FuaW1hdGlvbg0KICAgIEBpbWFnZS53cml0ZSgiZnJvc3RfI3tUaW1lLm5v dy5zdHJmdGltZSgiJUglTSIpfS5naWYiKQ0KICBlbmQgIA0KZW5kDQoNCnM9U2ltRnJvc3QubmV3 KDIwMCwyMDAsNDApDQpzdGVwID0gMA0KcHV0cyAiU2l0IGJhY2ssIHRoaXMgbWF5IHRha2UgYSB3 aGlsZSINCndoaWxlIHMuZ3JpZC5mbGF0dGVuLmluY2x1ZGU/KFNpbUZyb3N0OjpWQVBPUikgICNm bGF0dGVuIGluc3BpcmVkIGJ5IEphbWVzIEVkd2FyZCBHcmF5DQogIHB1dHMgIlN0ZXAgI3tzdGVw fTogY3JlYXRpbmcgZnJhbWUiDQogIHMuZ2VuZXJhdGVfZ2lmDQogIHMuY2hlY2tfbmVpZ2hib3Jo b29kcw0KICBzdGVwICs9IDENCmVuZA0KICBzLmNyZWF0ZV9hbmltYXRpb24NCiAgcHV0cyAiRG9u ZSI= ------=_Part_24090_5257072.1173659755826--