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

Code's slow :(
post's fast ;)

hopefully I find some time to profile and optimise the whole thing.

run.rb is the shell cmdline frontend
torus.rb is the freezer
ascii.rb and ppm.rb are two output plugins.

actually the output of the follwoing is nice already

rubr run.rb -f ascii 80 80 0.5 && \
for i in output/run-80-80.000000*.txt ; do clear; cat $i; sleep 1; done

GQView shows the ppm files nicely too and I guess lot's of other
viewers do but I did not mange to create movies on Linux yet, any
hints would be appreciated.

And before I forget

YET ANOTHER GREAT RUBY QUIZ :))


534/35 > cat run.rb
-------------------------
# vim: sw sts nu twexpandtab:
#
require 'fileutils'
require 'torus'

def usage msg  il
  $stderr.puts msg if msg
  $stderr.puts <<-EOS
  usage:
  #{$0} [options] height width vapor_probability

  options and their defaults
  -s|--start <height>/2@<width>/2      where to put the initial freezer
                                       please use Smalltalk syntax here
  -n|--name   run-<height>-<width>     name of the output file
  -v|--vapor  255/0/255                rgb value for PPM
              O                        use strings for ASCII
  -0|--vacuum 0/0/0                    idem
              <space>
  -i|--ice    255/255/255              idem
              *
  -f|--format ppm                      ppm or ascii are supported
                                       write your own plugins ;)

  have fun
  EOS
  exit -1
end

@start  name  il
@vapor  il
@vacuum  il
@ice     il
@format  ppm"
options   /^-f|^--format/ :format,
            /^-s|^--start/  :start,
            /^-n|^--name/   :name,
            /^-v|^--vapor/  :vapor,
            /^-0|^--vacuum/ :vacuum,
            /^-i|^--ice/    :ice }
loop do
  break if ARGV.empty?
  break if ARGV.first "--"
  break unless /^-/  ARGV.first
  illegal_option  rue
  options.each do
    | opt_reg, opt_sym |
    if opt_reg  ARGV.first then
      usage "Missing argument for option #{ARGV}" if ARGV.length < 2
      instance_variable_set( "@#{opt_sym}", ARGV[1] )
      ARGV.slice!( 0, 2 )
      illegal_option  alse
    end
  end
  usage ARGV.first if illegal_option
end
usage ARGV.join(", ") unless ARGV.size 3

require @format rescue usage

begin
  mkdir( "output" ) unless File.directory?( "output" )
rescue
  $stderr.puts 'Cannot create output directory "output"'
  usage
end

t  orus( *(ARGV << @start) )
t.name  name || "run-#{ARGV[0..1].join("-")}"
t.formatter  ormatter.new( ICE @ice, VAPOR @vapor, VACUUM @vacuum )
t.start_sim
35/36 > cat torus.rb
--------------------------
# vim: sw sts nu twexpandtab nowrap:
#
#

ICE  lass.new
VAPOR  lass.new
VACUUM  lass.new

###############################################################
#
# a small reference to Python ;)
#
###############################################################
def Torus( rows, cols, vapors, start  il )
  Torus_.new( rows.to_i, cols.to_i, vapors.to_f, start )
end

class Torus_

  ###############################################################
  #
  #    Torus_
  #
  ###############################################################
  attr_reader :lines, :columns
  attr_reader :generation
  attr_accessor :formatter, :name
  def initialize rows, cols, vapors, start
    @lines  ows
    @columns  ols
    @vapors  apors
    @generation  
    if start then
      @start  tart.split("@").map{|e| e.to_i}
    else
      @start ||  rows/2, cols /2 ]
    end
    @nhoods  ]  # we will store neighborhoods identified by
    # their upper left corner index, odd is for even generations
    # and even is for odd generations, which might seem odd.
    reset_values
    set_vapors
  end

  def [] line, coll
    return @values[line] unless col
    @values[line][col]
  end # def [](line, coll)
  def [] ine, col, val
    @values[line][col]  al
  end
  def each_cell
    (1..@lines).each do
      | line |
      (1..@columns).each do
        | column |
        yield @values[line-1][column-1], line-1, column-1
      end # (0..@columns).each do
    end # (0..@lines).each do
  end # def each_cell &blk

  def each_line
    @values.each{ |line| yield line }
  end

  def each_nbh
    r    generation % 2
    loop do
      yield @nhoods[ linear_idx( r, c ) ] ||Neighborhood.new( self, r, r.succ % @lines, c, c.succ % @columns )
      c + 
      r +  unless c < @columns
      return unless r < @lines
      c % columns
      r % lines
    end
  end

  def set_from_str str
    @values  ]
    str.strip.split("\n").each do
      | line_str |
      @values << []
      line_str.each_byte do
         | char |
         @values.last << case char.chr
                          when ICE.to_s
                            ICE
                          when VACUUM.to_s
                            VACUUM
                          when VAPOR.to_s
                            VAPOR
                         end

      end
    end
  end

  def start_sim
    until no_more_vapor? do
      tick
      write
    end
  end # def start_sim

  def tick
    puts "Simulation #{@name} generation #{@generation}:"
    @generation + 
    each_nbh do
      | nbh |
      nbh.recalc
    end
  end

  private

  def no_more_vapor?
    ! @values.any?{ |line|
      line.any?{ |v| v VAPOR }
    }
  end

  def reset_values
    @values  rray.new(@lines){
      Array.new(@columns){
        VACUUM
      }
    }
  end
  def set_vapors
    total  lines * @columns
    v   @vapors *  (total-1) ).to_i
    x  *0..total-2]
    at  ]
    v.times do
      at << x.delete_at( rand(x.size) )
    end
    at.each do
      | index |
      l,c  atrix_idx index
      @values[l][c]  APOR
    end
    @values[@lines-1][@columns-1]  values[@start.first][@start.last]
    @values[@start.first][@start.last]  CE
  end # def set_vapors

  def linear_idx r, c
    r * @columns + c
  end
  def matrix_idx l
    return l / @columns, l % @columns
  end

  def write
    @formatter.to_file self, "output/#{@name}.%08d" % @generation
  end # def write

end # class Torus_

###############################################################
#
#    Neighborhood is implementing a 2x2 window to any object
#    that responds to #[]n,m and #[]m,value
#    It implements the operation of rotation.
#
###############################################################
class Neighborhood < Struct.new( :torus, :top, :bottom,  :left, :right )
  include Enumerable

  # Neighborhood gives us the following indexed view to the underlying
  # torus
  #     +---+---+     +-----------+-----------+
  #     | 0 | 1 |     | @top,@lft | @top,@rgt |
  #     +---+---+     +-----------+-----------+
  #     | 3 | 2 |     | @bot,@lft | @bot,@rgt |
  #     +---+---+     +-----------+-----------+
  #
  # The Name and the Indexer implement that mapping

  Names  
      %w{ top left },
      %w{ top right },
      %w{ bottom right },
      %w{ bottom left }
      ]

  def initialize *args
    super *args
  end

  alias_method :__access__, :[] # Needed b/c/o the limited access
  # abilities of Struct

  def [] n
    __access__("torus")[ *resolve_idx( n ) ]
  end
  def [] , val
    __access__("torus")[ *resolve_idx( n ) ]  al
  end

  def each
    4.times do
      | idx |
      yield self[idx]
    end
  end

  def recalc

    if any?{|v| v ICE} then
      4.times do
        | idx |
        self[ idx ]  CE if self[ idx ] VAPOR
      end
    else
      rotate( rand(2) )
    end
  end

  def rotate dir
    x  elf[0]
    3.times do
      | n |
      self[ n + 2*dir*n ]  elf[ n + 1 + dir*2*n.succ ]
    end # 3.times do
    self[ 3 + 2 * dir ]  
  end # def rotate dir

  private
  def resolve_idx n
    [
    __access__( Names[ n % 4 ].first ),
    __access__( Names[ n % 4 ].last)
    ]
  end # def resolv_idx

end # class Neighborhood


538/39 > cat ascii.rb
--------------------------
# vim: sw sts nu twexpandtab nowrap:


class Formatter

  @@default   ICE "*",
                VAPOR "0",
                VACUUM " "
  }
  def initialize chars
    @chars Hash[ *chars.to_a.map{ |(k,v)| [k, v || @@default[k] ] }.flatten ]
  end # def initialize colors

  def to_file( source, file, comment  il )
    File.open( "#{file}.txt", "w" ) do
      | f |
      source.each_line{
        |line|
        line.each do
          | cell |
          f.print @chars[cell]
        end
        f.puts
      }
    end
  end

end

539/40 > cat ppm.rb
--------------------------
# vim: sw sts nu twexpandtab nowrap:


class Formatter

  @@default   ICE "255/255/255",
                VAPOR "255/0/255",
                VACUUM "0/0/0"
  }

  def initialize colors
    @colors  }
    colors.each do
      | element, color |
      color || @default[element]
      @colors[ element ]   " << color.gsub("/", " ") << " "
    end # colors.each do
  end # def initialize colors

  def to_file( source, file, comment  il )
    comment || ile
    File.open( "#{file}.ppm", "w" ) do
      | f |
      f.puts "P3 #{source.columns} #{source.lines} 255"
      f.puts "#"
      f.puts "# #{comment}"
      f.puts "#"
      source.each_line{
        |line|
        count  
        line.each do
          | cell |
          s  colors[cell]
          if count + s.size > 70 then
            f.puts
            count  
          end
          count + .size
          f.print s
        end
        f.puts unless count.zero?
      }
    end
  end

end

------art_20344_4369595.1173621305310
Content-Type: application/x-ruby; name="ascii.rb"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="ascii.rb"
X-Attachment-Id: f_ez5idwji

IyB2aW06IHN3PTIgc3RzPTIgbnUgdHc9MCBleHBhbmR0YWIgbm93cmFwOgoKCmNsYXNzIEZvcm1h
dHRlcgoKICBAQGRlZmF1bHQgPSB7IElDRSA9PiAiKiIsCiAgICAgICAgICAgICAgICBWQVBPUiA9
PiAiMCIsCiAgICAgICAgICAgICAgICBWQUNVVU0gPT4gIiAiIAogIH0KICBkZWYgaW5pdGlhbGl6
ZSBjaGFycz17fQogICAgQGNoYXJzID0gCiAgICAgIEhhc2hbICpjaGFycy50b19hLm1hcHsgfChr
LHYpfCBbaywgdiB8fCBAQGRlZmF1bHRba10gXSB9LmZsYXR0ZW4gXQogIGVuZCAjIGRlZiBpbml0
aWFsaXplIGNvbG9ycz17fQoKICBkZWYgdG9fZmlsZSggc291cmNlLCBmaWxlLCBjb21tZW50ID0g
bmlsICkKICAgIEZpbGUub3BlbiggIiN7ZmlsZX0udHh0IiwgInciICkgZG8KICAgICAgfCBmIHwK
ICAgICAgc291cmNlLmVhY2hfbGluZXsKICAgICAgICB8bGluZXwKICAgICAgICBsaW5lLmVhY2gg
ZG8KICAgICAgICAgIHwgY2VsbCB8CiAgICAgICAgICBmLnByaW50IEBjaGFyc1tjZWxsXQogICAg
ICAgIGVuZAogICAgICAgIGYucHV0cwogICAgICB9CiAgICBlbmQKICBlbmQKICAKZW5kCg------art_20344_4369595.1173621305310
Content-Type: application/x-ruby; name="ppm.rb"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="ppm.rb"
X-Attachment-Id: f_ez5ief6f

IyB2aW06IHN3PTIgc3RzPTIgbnUgdHc9MCBleHBhbmR0YWIgbm93cmFwOgoKCmNsYXNzIEZvcm1h
dHRlcgoKICBAQGRlZmF1bHQgPSB7IElDRSA9PiAiMjU1LzI1NS8yNTUiLAogICAgICAgICAgICAg
ICAgVkFQT1IgPT4gIjI1NS8wLzI1NSIsCiAgICAgICAgICAgICAgICBWQUNVVU0gPT4gIjAvMC8w
IiAKICB9CgogIGRlZiBpbml0aWFsaXplIGNvbG9ycz17fQogICAgQGNvbG9ycyA9IHt9CiAgICBj
b2xvcnMuZWFjaCBkbwogICAgICB8IGVsZW1lbnQsIGNvbG9yIHwKICAgICAgY29sb3IgfHw9IEBA
ZGVmYXVsdFtlbGVtZW50XQogICAgICBAY29sb3JzWyBlbGVtZW50IF0gPSAiICIgPDwgY29sb3Iu
Z3N1YigiLyIsICIgIikgPDwgIiAiCiAgICBlbmQgIyBjb2xvcnMuZWFjaCBkbwogIGVuZCAjIGRl
ZiBpbml0aWFsaXplIGNvbG9ycz17fQoKICBkZWYgdG9fZmlsZSggc291cmNlLCBmaWxlLCBjb21t
ZW50ID0gbmlsICkKICAgIGNvbW1lbnQgfHw9IGZpbGUKICAgIEZpbGUub3BlbiggIiN7ZmlsZX0u
cHBtIiwgInciICkgZG8KICAgICAgfCBmIHwKICAgICAgZi5wdXRzICJQMyAje3NvdXJjZS5jb2x1
bW5zfSAje3NvdXJjZS5saW5lc30gMjU1IgogICAgICBmLnB1dHMgIiMiCiAgICAgIGYucHV0cyAi
IyAje2NvbW1lbnR9IgogICAgICBmLnB1dHMgIiMiCiAgICAgIHNvdXJjZS5lYWNoX2xpbmV7CiAg
ICAgICAgfGxpbmV8CiAgICAgICAgY291bnQgPSAwCiAgICAgICAgbGluZS5lYWNoIGRvCiAgICAg
ICAgICB8IGNlbGwgfAogICAgICAgICAgcyA9IEBjb2xvcnNbY2VsbF0KICAgICAgICAgIGlmIGNv
dW50ICsgcy5zaXplID4gNzAgdGhlbgogICAgICAgICAgICBmLnB1dHMgCiAgICAgICAgICAgIGNv
dW50ID0gMAogICAgICAgICAgZW5kCiAgICAgICAgICBjb3VudCArPSBzLnNpemUKICAgICAgICAg
IGYucHJpbnQgcwogICAgICAgIGVuZAogICAgICAgIGYucHV0cyB1bmxlc3MgY291bnQuemVybz8K
ICAgICAgfQogICAgZW5kCiAgZW5kCiAgCmVuZAo------art_20344_4369595.1173621305310
Content-Type: application/x-ruby; name="run.rb"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="run.rb"
X-Attachment-Id: f_ez5ielfk

IyB2aW06IHN3PTIgc3RzPTIgbnUgdHc9MCBleHBhbmR0YWI6DQojDQpyZXF1aXJlICdmaWxldXRp
bHMnDQpyZXF1aXJlICd0b3J1cycNCg0KZGVmIHVzYWdlIG1zZyA9IG5pbA0KICAkc3RkZXJyLnB1
dHMgbXNnIGlmIG1zZw0KICAkc3RkZXJyLnB1dHMgPDwtRU9TDQogIHVzYWdlOg0KICAjeyQwfSBb
b3B0aW9uc10gaGVpZ2h0IHdpZHRoIHZhcG9yX3Byb2JhYmlsaXR5DQoNCiAgb3B0aW9ucyBhbmQg
dGhlaXIgZGVmYXVsdHMNCiAgLXN8LS1zdGFydCA8aGVpZ2h0Pi8yQDx3aWR0aD4vMiAgICAgIHdo
ZXJlIHRvIHB1dCB0aGUgaW5pdGlhbCBmcmVlemVyDQogICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICBwbGVhc2UgdXNlIFNtYWxsdGFsayBzeW50YXggaGVyZQ0KICAtbnwtLW5h
bWUgICBydW4tPGhlaWdodD4tPHdpZHRoPiAgICAgbmFtZSBvZiB0aGUgb3V0cHV0IGZpbGUNCiAg
LXZ8LS12YXBvciAgMjU1LzAvMjU1ICAgICAgICAgICAgICAgIHJnYiB2YWx1ZSBmb3IgUFBNDQog
ICAgICAgICAgICAgIE8gICAgICAgICAgICAgICAgICAgICAgICB1c2Ugc3RyaW5ncyBmb3IgQVND
SUkNCiAgLTB8LS12YWN1dW0gMC8wLzAgICAgICAgICAgICAgICAgICAgIGlkZW0NCiAgICAgICAg
ICAgICAgPHNwYWNlPg0KICAtaXwtLWljZSAgICAyNTUvMjU1LzI1NSAgICAgICAgICAgICAgaWRl
bQ0KICAgICAgICAgICAgICAqDQogIC1mfC0tZm9ybWF0IHBwbSAgICAgICAgICAgICAgICAgICAg
ICBwcG0gb3IgYXNjaWkgYXJlIHN1cHBvcnRlZA0KICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgd3JpdGUgeW91ciBvd24gcGx1Z2lucyA7KQ0KDQogIGhhdmUgZnVuDQogIEVP
Uw0KICBleGl0IC0xDQplbmQNCg0KQHN0YXJ0ID0gQG5hbWUgPSBuaWwNCkB2YXBvciA9IG5pbA0K
QHZhY3V1bSA9IG5pbA0KQGljZSAgICA9IG5pbA0KQGZvcm1hdCA9ICJwcG0iIA0Kb3B0aW9ucyA9
IHsgL14tZnxeLS1mb3JtYXQvID0+IDpmb3JtYXQsDQogICAgICAgICAgICAvXi1zfF4tLXN0YXJ0
LyAgPT4gOnN0YXJ0LA0KICAgICAgICAgICAgL14tbnxeLS1uYW1lLyAgID0+IDpuYW1lLA0KICAg
ICAgICAgICAgL14tdnxeLS12YXBvci8gID0+IDp2YXBvciwNCiAgICAgICAgICAgIC9eLTB8Xi0t
dmFjdXVtLyA9PiA6dmFjdXVtLA0KICAgICAgICAgICAgL14taXxeLS1pY2UvICAgID0+IDppY2Ug
fQ0KbG9vcCBkbw0KICBicmVhayBpZiBBUkdWLmVtcHR5Pw0KICBicmVhayBpZiBBUkdWLmZpcnN0
ID09ICItLSINCiAgYnJlYWsgdW5sZXNzIC9eLS8gPT09IEFSR1YuZmlyc3QNCiAgaWxsZWdhbF9v
cHRpb24gPSB0cnVlDQogIG9wdGlvbnMuZWFjaCBkbw0KICAgIHwgb3B0X3JlZywgb3B0X3N5bSB8
DQogICAgaWYgb3B0X3JlZyA9PT0gQVJHVi5maXJzdCB0aGVuDQogICAgICB1c2FnZSAiTWlzc2lu
ZyBhcmd1bWVudCBmb3Igb3B0aW9uICN7QVJHVn0iIGlmIEFSR1YubGVuZ3RoIDwgMg0KICAgICAg
aW5zdGFuY2VfdmFyaWFibGVfc2V0KCAiQCN7b3B0X3N5bX0iLCBBUkdWWzFdICkNCiAgICAgIEFS
R1Yuc2xpY2UhKCAwLCAyICkNCiAgICAgIGlsbGVnYWxfb3B0aW9uID0gZmFsc2UNCiAgICBlbmQN
CiAgZW5kDQogIHVzYWdlIEFSR1YuZmlyc3QgaWYgaWxsZWdhbF9vcHRpb24gDQplbmQNCnVzYWdl
IEFSR1Yuam9pbigiLCAiKSB1bmxlc3MgQVJHVi5zaXplID09IDMNCg0KcmVxdWlyZSBAZm9ybWF0
IHJlc2N1ZSB1c2FnZQ0KDQpiZWdpbg0KICBta2RpciggIm91dHB1dCIgKSB1bmxlc3MgRmlsZS5k
aXJlY3Rvcnk/KCAib3V0cHV0IiApIA0KcmVzY3VlIA0KICAkc3RkZXJyLnB1dHMgJ0Nhbm5vdCBj
cmVhdGUgb3V0cHV0IGRpcmVjdG9yeSAib3V0cHV0IicNCiAgdXNhZ2UNCmVuZA0KDQp0ID0gVG9y
dXMoICooQVJHViA8PCBAc3RhcnQpICkNCnQubmFtZSA9IEBuYW1lIHx8ICJydW4tI3tBUkdWWzAu
LjFdLmpvaW4oIi0iKX0iDQp0LmZvcm1hdHRlciA9IEZvcm1hdHRlci5uZXcoIElDRSA9PiBAaWNl
LCBWQVBPUiA9PiBAdmFwb3IsIFZBQ1VVTSA9PiBAdmFjdXVtICkNCnQuc3RhcnRfc2ltDQo------art_20344_4369595.1173621305310
Content-Type: application/x-ruby; name="torus.rb"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="torus.rb"
X-Attachment-Id: f_ez5ieoum

IyB2aW06IHN3PTIgc3RzPTIgbnUgdHc9MCBleHBhbmR0YWIgbm93cmFwOg0KIw0KIw0KDQpJQ0Ug
PSBDbGFzcy5uZXcNClZBUE9SID0gQ2xhc3MubmV3DQpWQUNVVU0gPSBDbGFzcy5uZXcNCg0KDQoj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMNCiMNCiMgYSBzbWFsbCByZWZlcmVuY2UgdG8gUHl0aG9uIDspDQojDQojIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCmRl
ZiBUb3J1cyggcm93cywgY29scywgdmFwb3JzLCBzdGFydCA9IG5pbCApDQogIFRvcnVzXy5uZXco
IHJvd3MudG9faSwgY29scy50b19pLCB2YXBvcnMudG9fZiwgc3RhcnQgKQ0KZW5kDQoNCmNsYXNz
IFRvcnVzXw0KDQogICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIw0KICAjDQogICMgICAgVG9ydXNfDQogICMNCiAgIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQog
IGF0dHJfcmVhZGVyIDpsaW5lcywgOmNvbHVtbnMNCiAgYXR0cl9yZWFkZXIgOmdlbmVyYXRpb24N
CiAgYXR0cl9hY2Nlc3NvciA6Zm9ybWF0dGVyLCA6bmFtZQ0KICBkZWYgaW5pdGlhbGl6ZSByb3dz
LCBjb2xzLCB2YXBvcnMsIHN0YXJ0DQogICAgQGxpbmVzID0gcm93cw0KICAgIEBjb2x1bW5zID0g
Y29scw0KICAgIEB2YXBvcnMgPSB2YXBvcnMNCiAgICBAZ2VuZXJhdGlvbiA9IDANCiAgICBpZiBz
dGFydCB0aGVuDQogICAgICBAc3RhcnQgPSBzdGFydC5zcGxpdCgiQCIpLm1hcHt8ZXwgZS50b19p
fQ0KICAgIGVsc2UNCiAgICAgIEBzdGFydCB8fD0gWyByb3dzLzIsIGNvbHMgLzIgXQ0KICAgIGVu
ZA0KICAgIEBuaG9vZHMgPSBbXSAgIyB3ZSB3aWxsIHN0b3JlIG5laWdoYm9yaG9vZHMgaWRlbnRp
ZmllZCBieQ0KICAgICMgdGhlaXIgdXBwZXIgbGVmdCBjb3JuZXIgaW5kZXgsIG9kZCBpcyBmb3Ig
ZXZlbiBnZW5lcmF0aW9ucw0KICAgICMgYW5kIGV2ZW4gaXMgZm9yIG9kZCBnZW5lcmF0aW9ucywg
d2hpY2ggbWlnaHQgc2VlbSBvZGQuDQogICAgcmVzZXRfdmFsdWVzDQogICAgc2V0X3ZhcG9ycw0K
ICBlbmQNCg0KICBkZWYgW10gbGluZSwgY29sPW5pbA0KICAgIHJldHVybiBAdmFsdWVzW2xpbmVd
IHVubGVzcyBjb2wNCiAgICBAdmFsdWVzW2xpbmVdW2NvbF0NCiAgZW5kICMgZGVmIFtdKGxpbmUs
IGNvbD1uaWwpDQogIGRlZiBbXT0gbGluZSwgY29sLCB2YWwNCiAgICBAdmFsdWVzW2xpbmVdW2Nv
bF0gPSB2YWwNCiAgZW5kDQogIGRlZiBlYWNoX2NlbGwgDQogICAgKDEuLkBsaW5lcykuZWFjaCBk
bw0KICAgICAgfCBsaW5lIHwNCiAgICAgICgxLi5AY29sdW1ucykuZWFjaCBkbw0KICAgICAgICB8
IGNvbHVtbiB8DQogICAgICAgIHlpZWxkIEB2YWx1ZXNbbGluZS0xXVtjb2x1bW4tMV0sIGxpbmUt
MSwgY29sdW1uLTENCiAgICAgIGVuZCAjICgwLi5AY29sdW1ucykuZWFjaCBkbw0KICAgIGVuZCAj
ICgwLi5AbGluZXMpLmVhY2ggZG8NCiAgZW5kICMgZGVmIGVhY2hfY2VsbCAmYmxrDQoNCiAgZGVm
IGVhY2hfbGluZQ0KICAgIEB2YWx1ZXMuZWFjaHsgfGxpbmV8IHlpZWxkIGxpbmUgfQ0KICBlbmQN
Cg0KICBkZWYgZWFjaF9uYmgNCiAgICByID0gYyA9IEBnZW5lcmF0aW9uICUgMg0KICAgIGxvb3Ag
ZG8NCiAgICAgIHlpZWxkIEBuaG9vZHNbIGxpbmVhcl9pZHgoIHIsIGMgKSBdIHx8PSANCiAgICAg
ICAgICBOZWlnaGJvcmhvb2QubmV3KCBzZWxmLCByLCByLnN1Y2MgJSBAbGluZXMsIGMsIGMuc3Vj
YyAlIEBjb2x1bW5zICkNCiAgICAgIGMgKz0gMg0KICAgICAgciArPSAyIHVubGVzcyBjIDwgQGNv
bHVtbnMNCiAgICAgIHJldHVybiB1bmxlc3MgciA8IEBsaW5lcw0KICAgICAgYyAlPSBAY29sdW1u
cw0KICAgICAgciAlPSBAbGluZXMNCiAgICBlbmQNCiAgZW5kDQoNCiAgZGVmIHNldF9mcm9tX3N0
ciBzdHINCiAgICBAdmFsdWVzID0gW10NCiAgICBzdHIuc3RyaXAuc3BsaXQoIlxuIikuZWFjaCBk
bw0KICAgICAgfCBsaW5lX3N0ciB8DQogICAgICBAdmFsdWVzIDw8IFtdDQogICAgICBsaW5lX3N0
ci5lYWNoX2J5dGUgZG8NCiAgICAgICAgIHwgY2hhciB8DQogICAgICAgICBAdmFsdWVzLmxhc3Qg
PDwgY2FzZSBjaGFyLmNocg0KICAgICAgICAgICAgICAgICAgICAgICAgICB3aGVuIElDRS50b19z
DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUNFDQogICAgICAgICAgICAgICAgICAgICAg
ICAgIHdoZW4gVkFDVVVNLnRvX3MNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQUNVVU0N
CiAgICAgICAgICAgICAgICAgICAgICAgICAgd2hlbiBWQVBPUi50b19zDQogICAgICAgICAgICAg
ICAgICAgICAgICAgICAgVkFQT1INCiAgICAgICAgICAgICAgICAgICAgICAgICBlbmQNCg0KICAg
ICAgZW5kDQogICAgZW5kDQogIGVuZA0KDQogIGRlZiBzdGFydF9zaW0NCiAgICB1bnRpbCBub19t
b3JlX3ZhcG9yPyBkbw0KICAgICAgdGljaw0KICAgICAgd3JpdGUNCiAgICBlbmQNCiAgZW5kICMg
ZGVmIHN0YXJ0X3NpbQ0KDQogIGRlZiB0aWNrDQogICAgcHV0cyAiU2ltdWxhdGlvbiAje0BuYW1l
fSBnZW5lcmF0aW9uICN7QGdlbmVyYXRpb259OiINCiAgICBAZ2VuZXJhdGlvbiArPSAxDQogICAg
ZWFjaF9uYmggZG8NCiAgICAgIHwgbmJoIHwNCiAgICAgIG5iaC5yZWNhbGMNCiAgICBlbmQgDQog
IGVuZA0KDQogIHByaXZhdGUNCg0KICBkZWYgbm9fbW9yZV92YXBvcj8NCiAgICAhIEB2YWx1ZXMu
YW55P3sgfGxpbmV8DQogICAgICBsaW5lLmFueT97IHx2fCB2ID09IFZBUE9SIH0NCiAgICB9DQog
IGVuZA0KDQogIGRlZiByZXNldF92YWx1ZXMNCiAgICBAdmFsdWVzID0gQXJyYXkubmV3KEBsaW5l
cyl7DQogICAgICBBcnJheS5uZXcoQGNvbHVtbnMpew0KICAgICAgICBWQUNVVU0NCiAgICAgIH0N
CiAgICB9DQogIGVuZA0KICBkZWYgc2V0X3ZhcG9ycw0KICAgIHRvdGFsID0gQGxpbmVzICogQGNv
bHVtbnMNCiAgICB2ID0gKCBAdmFwb3JzICogICh0b3RhbC0xKSApLnRvX2kNCiAgICB4ID0gWyow
Li50b3RhbC0yXQ0KICAgIGF0ID0gW10NCiAgICB2LnRpbWVzIGRvDQogICAgICBhdCA8PCB4LmRl
bGV0ZV9hdCggcmFuZCh4LnNpemUpICkNCiAgICBlbmQNCiAgICBhdC5lYWNoIGRvDQogICAgICB8
IGluZGV4IHwNCiAgICAgIGwsYyA9IG1hdHJpeF9pZHggaW5kZXgNCiAgICAgIEB2YWx1ZXNbbF1b
Y10gPSBWQVBPUg0KICAgIGVuZA0KICAgIEB2YWx1ZXNbQGxpbmVzLTFdW0Bjb2x1bW5zLTFdID0g
QHZhbHVlc1tAc3RhcnQuZmlyc3RdW0BzdGFydC5sYXN0XQ0KICAgIEB2YWx1ZXNbQHN0YXJ0LmZp
cnN0XVtAc3RhcnQubGFzdF0gPSBJQ0UNCiAgZW5kICMgZGVmIHNldF92YXBvcnMNCg0KICBkZWYg
bGluZWFyX2lkeCByLCBjDQogICAgciAqIEBjb2x1bW5zICsgYw0KICBlbmQNCiAgZGVmIG1hdHJp
eF9pZHggbA0KICAgIHJldHVybiBsIC8gQGNvbHVtbnMsIGwgJSBAY29sdW1ucw0KICBlbmQNCg0K
ICBkZWYgd3JpdGUNCiAgICBAZm9ybWF0dGVyLnRvX2ZpbGUgc2VsZiwgIm91dHB1dC8je0BuYW1l
fS4lMDhkIiAlIEBnZW5lcmF0aW9uDQogIGVuZCAjIGRlZiB3cml0ZQ0KICANCmVuZCAjIGNsYXNz
IFRvcnVzXw0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMNCiMNCiMgICAgTmVpZ2hib3Job29kIGlzIGltcGxlbWVudGluZyBh
IDJ4MiB3aW5kb3cgdG8gYW55IG9iamVjdA0KIyAgICB0aGF0IHJlc3BvbmRzIHRvICNbXW4sbSBh
bmQgI1tdPW4sbSx2YWx1ZQ0KIyAgICBJdCBpbXBsZW1lbnRzIHRoZSBvcGVyYXRpb24gb2Ygcm90
YXRpb24uDQojDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMNCmNsYXNzIE5laWdoYm9yaG9vZCA8IFN0cnVjdC5uZXcoIDp0b3J1
cywgOnRvcCwgOmJvdHRvbSwgIDpsZWZ0LCA6cmlnaHQgKQ0KICBpbmNsdWRlIEVudW1lcmFibGUN
Cg0KICAjIE5laWdoYm9yaG9vZCBnaXZlcyB1cyB0aGUgZm9sbG93aW5nIGluZGV4ZWQgdmlldyB0
byB0aGUgdW5kZXJseWluZw0KICAjIHRvcnVzDQogICMgICAgICstLS0rLS0tKyAgICAgKy0tLS0t
LS0tLS0tKy0tLS0tLS0tLS0tKw0KICAjICAgICB8IDAgfCAxIHwgICAgIHwgQHRvcCxAbGZ0IHwg
QHRvcCxAcmd0IHwNCiAgIyAgICAgKy0tLSstLS0rICAgICArLS0tLS0tLS0tLS0rLS0tLS0tLS0t
LS0rDQogICMgICAgIHwgMyB8IDIgfCAgICAgfCBAYm90LEBsZnQgfCBAYm90LEByZ3QgfA0KICAj
ICAgICArLS0tKy0tLSsgICAgICstLS0tLS0tLS0tLSstLS0tLS0tLS0tLSsNCiAgIw0KICAjIFRo
ZSBOYW1lIGFuZCB0aGUgSW5kZXhlciBpbXBsZW1lbnQgdGhhdCBtYXBwaW5nDQoNCiAgTmFtZXMg
PSBbIA0KICAgICAgJXd7IHRvcCBsZWZ0IH0sDQogICAgICAld3sgdG9wIHJpZ2h0IH0sDQogICAg
ICAld3sgYm90dG9tIHJpZ2h0IH0sDQogICAgICAld3sgYm90dG9tIGxlZnQgfQ0KICAgICAgXQ0K
DQogIGRlZiBpbml0aWFsaXplICphcmdzDQogICAgc3VwZXIgKmFyZ3MNCiAgZW5kDQoNCiAgYWxp
YXNfbWV0aG9kIDpfX2FjY2Vzc19fLCA6W10gIyBOZWVkZWQgYi9jL28gdGhlIGxpbWl0ZWQgYWNj
ZXNzDQogICMgYWJpbGl0aWVzIG9mIFN0cnVjdA0KDQogIGRlZiBbXSBuDQogICAgX19hY2Nlc3Nf
XygidG9ydXMiKVsgKnJlc29sdmVfaWR4KCBuICkgXQ0KICBlbmQNCiAgZGVmIFtdPSBuLCB2YWwN
CiAgICBfX2FjY2Vzc19fKCJ0b3J1cyIpWyAqcmVzb2x2ZV9pZHgoIG4gKSBdID0gdmFsDQogIGVu
ZA0KDQogIGRlZiBlYWNoDQogICAgNC50aW1lcyBkbw0KICAgICAgfCBpZHggfA0KICAgICAgeWll
bGQgc2VsZltpZHhdDQogICAgZW5kDQogIGVuZA0KDQogIGRlZiByZWNhbGMNCiAgICANCiAgICBp
ZiBhbnk/e3x2fCB2ID09IElDRX0gdGhlbg0KICAgICAgNC50aW1lcyBkbw0KICAgICAgICB8IGlk
eCB8DQogICAgICAgIHNlbGZbIGlkeCBdID0gSUNFIGlmIHNlbGZbIGlkeCBdID09IFZBUE9SDQog
ICAgICBlbmQNCiAgICBlbHNlDQogICAgICByb3RhdGUoIHJhbmQoMikgKQ0KICAgIGVuZA0KICBl
bmQNCg0KICBkZWYgcm90YXRlIGRpcg0KICAgIHggPSBzZWxmWzBdDQogICAgMy50aW1lcyBkbw0K
ICAgICAgfCBuIHwNCiAgICAgIHNlbGZbIG4gKyAyKmRpcipuIF0gPSBzZWxmWyBuICsgMSArIGRp
cioyKm4uc3VjYyBdDQogICAgZW5kICMgMy50aW1lcyBkbw0KICAgIHNlbGZbIDMgKyAyICogZGly
IF0gPSB4DQogIGVuZCAjIGRlZiByb3RhdGUgZGlyDQoNCiAgcHJpdmF0ZQ0KICBkZWYgcmVzb2x2
ZV9pZHggbg0KICAgIFsNCiAgICBfX2FjY2Vzc19fKCBOYW1lc1sgbiAlIDQgXS5maXJzdCApLA0K
ICAgIF9fYWNjZXNzX18oIE5hbWVzWyBuICUgNCBdLmxhc3QpDQogICAgXQ0KICBlbmQgIyBkZWYg
cmVzb2x2X2lkeA0KDQplbmQgIyBjbGFzcyBOZWlnaGJvcmhvb2QNCg0K
------art_20344_4369595.1173621305310--