Skip to content

Instantly share code, notes, and snippets.

@parameme
Forked from hackling/scrabble_benchmarking.rb
Last active May 31, 2017 02:03

Revisions

  1. parameme revised this gist May 31, 2017. 1 changed file with 14 additions and 0 deletions.
    14 changes: 14 additions & 0 deletions scrabble_benchmarking.rb
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,10 @@
    "Y" => 4, "Z" => 10
    }

    POINTS_BY_FIXNUM = POINTS.map{ |k, v| [k.bytes.first, v] }.to_h

    ASCII_CAPITALISATION_BITMASK = (255 - 32) # Mask off all but bit 6

    class Scrabble
    def self.hackling(word)
    word ||= ""
    @@ -35,6 +39,11 @@ def self.hybrid2(word)

    word.chars.map {|char| POINTS[char.upcase] }.inject(&:+)
    end

    def self.parameme(word)
    return 0 unless (word && word.is_a?(String) && word.size > 0)
    word.each_byte.reduce(0) { |_, byte| _ + POINTS_BY_FIXNUM.fetch(byte & ASCII_CAPITALISATION_BITMASK) }
    end
    end

    require "fruity"
    @@ -46,6 +55,7 @@ def self.hybrid2(word)
    fuzzmonkey { Scrabble.fuzzmonkey(word) }
    hybrid { Scrabble.hybrid(word) }
    hybrid2 { Scrabble.hybrid2(word) }
    parameme { Scrabble.parameme(word) }
    end

    TIMES = 500_000
    @@ -62,6 +72,7 @@ def self.hybrid2(word)
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid: ") { TIMES.times { Scrabble.hybrid(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    x.report("parameme: ") { TIMES.times { Scrabble.parameme(word) } }
    end

    puts ""
    @@ -73,6 +84,7 @@ def self.hybrid2(word)
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid: ") { TIMES.times { Scrabble.hybrid(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    x.report("parameme: ") { TIMES.times { Scrabble.parameme(word) } }
    end

    puts ""
    @@ -84,6 +96,7 @@ def self.hybrid2(word)
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid: ") { TIMES.times { Scrabble.hybrid(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    x.report("parameme: ") { TIMES.times { Scrabble.parameme(word) } }
    end

    puts ""
    @@ -94,4 +107,5 @@ def self.hybrid2(word)
    x.report(" jma: ") { TIMES.times { Scrabble.jma(word) } }
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    x.report("parameme: ") { TIMES.times { Scrabble.parameme(word) } }
    end
  2. @hackling hackling created this gist May 31, 2017.
    97 changes: 97 additions & 0 deletions scrabble_benchmarking.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    POINTS = {
    "A" => 1, "B" => 3, "C" => 3, "D" => 2,
    "E" => 1, "F" => 4, "G" => 2, "H" => 4,
    "I" => 1, "J" => 8, "K" => 5, "L" => 1,
    "M" => 3, "N" => 1, "O" => 1, "P" => 3,
    "Q" => 10, "R" => 1, "S" => 1, "T" => 1,
    "U" => 1, "V" => 4, "W" => 4, "X" => 8,
    "Y" => 4, "Z" => 10
    }

    class Scrabble
    def self.hackling(word)
    word ||= ""
    return 0 if word == ""

    word.upcase.chars.map {|char| POINTS[char] }.inject(&:+)
    end

    def self.jma(word)
    String(word).upcase.each_char.map { |char| POINTS[char] }.inject(0, :+)
    end

    def self.fuzzmonkey(word)
    word.to_s.chars.map{|c| POINTS[c.upcase].to_i }.inject(:+).to_i
    end

    def self.hybrid(word)
    # I thought upcasing in the block might be faster by saving a pass through the array
    String(word).each_char.map { |char| POINTS[char.upcase] }.inject(0, :+)
    end

    def self.hybrid2(word)
    word ||= ""
    return 0 if word == ""

    word.chars.map {|char| POINTS[char.upcase] }.inject(&:+)
    end
    end

    require "fruity"

    word = "qwertyuiopasdfghjklzxcvbnm"
    compare do
    hackling { Scrabble.hackling(word) }
    jma { Scrabble.jma(word) }
    fuzzmonkey { Scrabble.fuzzmonkey(word) }
    hybrid { Scrabble.hybrid(word) }
    hybrid2 { Scrabble.hybrid2(word) }
    end

    TIMES = 500_000
    require 'benchmark'
    word = "qwertyuiopasdfghjklzxcvbnm"

    puts "Number of Times: #{TIMES}"
    puts ""
    puts "Long Word"
    word = "qwertyuiopasdfghjklzxcvbnm"
    Benchmark.bm(12) do |x|
    x.report("hackling: ") { TIMES.times { Scrabble.hackling(word) } }
    x.report(" jma: ") { TIMES.times { Scrabble.jma(word) } }
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid: ") { TIMES.times { Scrabble.hybrid(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    end

    puts ""
    puts "Short Word"
    word = "qwerty"
    Benchmark.bm(12) do |x|
    x.report("hackling: ") { TIMES.times { Scrabble.hackling(word) } }
    x.report(" jma: ") { TIMES.times { Scrabble.jma(word) } }
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid: ") { TIMES.times { Scrabble.hybrid(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    end

    puts ""
    puts "Nil Word"
    word = nil
    Benchmark.bm(12) do |x|
    x.report("hackling: ") { TIMES.times { Scrabble.hackling(word) } }
    x.report(" jma: ") { TIMES.times { Scrabble.jma(word) } }
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid: ") { TIMES.times { Scrabble.hybrid(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    end

    puts ""
    puts "Empty Word"
    word = ""
    Benchmark.bm(12) do |x|
    x.report("hackling: ") { TIMES.times { Scrabble.hackling(word) } }
    x.report(" jma: ") { TIMES.times { Scrabble.jma(word) } }
    x.report("fuzzmnky: ") { TIMES.times { Scrabble.fuzzmonkey(word) } }
    x.report(" hybrid2: ") { TIMES.times { Scrabble.hybrid2(word) } }
    end