The Computer Language
Benchmarks Game

chameneos-redux Ruby JRuby program

source code

# The Computer Language Benchmarks Game
# http://benchmarksgame.alioth.debian.org/

#   contributed by Michael Barker
#   based on a Java contribution by Luzius Meisser
#   converted to C by dualamd
#   converted to Ruby by Eugene Pimenov

require 'thread'

COLORS     = [:blue, :red, :yellow, :invalid].freeze
COMPLIMENT = {
  :blue => {:blue => :blue, :red => :yellow, :yellow => :red}.freeze,
  :red => {:blue => :yellow, :red => :red, :yellow => :blue}.freeze,
  :yellow => {:blue => :red, :red => :blue, :yellow => :yellow}.freeze
}.freeze

$creature_id = 0

NUMBERS = %w{zero one two three four five six seven eight nine}.freeze

# convert integer to number string: 1234 -> "one two three four"
def format_number(num)
  out = []
  begin
    out << NUMBERS[num%10]
    num /= 10
  end while num > 0
  out.reverse.join(" ")
end

class MeetingPlace
  attr_reader :mutex
  attr_accessor :meetings_left, :first_creature

  def initialize(meetings)
    @mutex = Mutex.new
    @meetings_left = meetings
  end
end

class Creature
  attr_accessor :place, :thread, :count, :same_count, :color, :id, :two_met, :sameid

  def initialize(place, color)
    @place = place
    @count = @same_count = 0

    @id = ($creature_id += 1)
    @color = color
    @two_met = FALSE

    @thread = Thread.new do
      loop do
        if meet
          Thread.pass while @two_met == false

          @same_count += 1 if @sameid
          @count += 1
        else
          break
        end
      end
    end
  end

  def meet
    @place.mutex.lock

    if @place.meetings_left > 0
      if @place.first_creature
        first = @place.first_creature
        new_color = COMPLIMENT[@color][first.color]

        @sameid  = first.sameid  = @id == first.id
        @color   = first.color   = new_color
        @two_met = first.two_met = true

        @place.first_creature = nil
        @place.meetings_left -= 1
      else
        @two_met = false
        @place.first_creature = self
      end
      true
    else
      false
    end
  ensure
    @place.mutex.unlock
  end

  def result
    '' << @count.to_s << ' ' << format_number(@same_count)
  end
end

def run_game(n_meeting, colors)
  place = MeetingPlace.new(n_meeting)

  creatures = []
  colors.each do |color|
    print color, " "
    creatures << Creature.new(place, color)
  end
  puts

  # wait for them to meet
  creatures.each { |c| c.thread.join}

  total = 0
  # print meeting times of each creature
  creatures.each do |c|
    puts c.result
    total += c.count
  end

  # print total meeting times, should be equal n_meeting
  print ' ', format_number(total), "\n\n"
end

def print_colors_table
  [:blue, :red, :yellow].each do |c1|
    [:blue, :red, :yellow].each do |c2|
      puts "#{c1} + #{c2} -> #{COMPLIMENT[c1][c2]}"
    end
  end
end

n = (ARGV[0] || 600).to_i


print_colors_table
puts

run_game n, [:blue, :red, :yellow]
run_game n, [:blue, :red, :yellow, :red, :yellow, :blue, :red, :yellow, :red, :blue]
    

notes, command-line, and program output

NOTES:
32-bit Ubuntu one core
jruby 9.1.0.0 (2.3.0) 2016-05-02 a633c63 Java HotSpot(TM) Server VM 25.92-b14 on 1.8.0_92-b14 +jit [linux-i386]



Wed, 04 May 2016 01:01:01 GMT

MAKE:
mv chameneosredux.jruby chameneosredux.rb
0.06s to complete and log all make actions

COMMAND LINE:
/usr/local/src/jruby-9.1.0.0/bin/jruby -Xcompile.fastest=true -Xcompile.invokedynamic=true -J-server -J-Xmn512m -J-Xms2048m -J-Xmx2048m chameneosredux.rb 6000000

PROGRAM OUTPUT:
blue + blue -> blue
blue + red -> yellow
blue + yellow -> red
red + blue -> yellow
red + red -> red
red + yellow -> blue
yellow + blue -> red
yellow + red -> blue
yellow + yellow -> yellow

blue red yellow 
4048956 zero
4038180 zero
3912864 zero
 one two zero zero zero zero zero zero

blue red yellow red yellow blue red yellow red blue 
1199079 zero
1204814 zero
1183078 zero
1190614 zero
1210090 zero
1214983 zero
1210068 zero
1204307 zero
1196854 zero
1186113 zero
 one two zero zero zero zero zero zero