Skip to content

Instantly share code, notes, and snippets.

@danielpclark
Last active May 13, 2017 18:48
Show Gist options
  • Select an option

  • Save danielpclark/c64122655b062062d1e6a825fa090f90 to your computer and use it in GitHub Desktop.

Select an option

Save danielpclark/c64122655b062062d1e6a825fa090f90 to your computer and use it in GitHub Desktop.
Rock Paper Scissors hash example
module HashExample
class Loser; end; class Winner; end; class Tie; end
class Element
def wins_against?(other)
RANKS[name][other.name] || Tie
end
end
class Rock < Element
def name; :Rock end
end
class Paper < Element
def name; :Paper end
end
class Scissors < Element
def name; :Scissors end
end
RANKS = {
Rock: { Paper: Loser, Scissors: Winner },
Paper: { Rock: Winner, Scissors: Loser },
Scissors: { Paper: Winner, Rock: Loser }
}
end
include HashExample
require "minitest/autorun"
describe "Rock Paper Scissors Game" do
describe "Rock" do
it "Ties against Rock" do
assert_equal Tie, Rock.new.wins_against?(Rock.new)
end
it "Loses against Paper" do
assert_equal Loser, Rock.new.wins_against?(Paper.new)
end
it " Wins against Scissors" do
assert_equal Winner, Rock.new.wins_against?(Scissors.new)
end
end
describe "Paper" do
it "Wins against Rock" do
assert_equal Winner, Paper.new.wins_against?(Rock.new)
end
it "Ties against Paper" do
assert_equal Tie, Paper.new.wins_against?(Paper.new)
end
it "Loses against Scissors" do
assert_equal Loser, Paper.new.wins_against?(Scissors.new)
end
end
describe "Scirssors" do
it "Loses against Rock" do
assert_equal Loser, Scissors.new.wins_against?(Rock.new)
end
it "Wins against Paper" do
assert_equal Winner, Scissors.new.wins_against?(Paper.new)
end
it "Ties against Scissors" do
assert_equal Tie, Scissors.new.wins_against?(Scissors.new)
end
end
end
require "benchmark/ips"
Benchmark.ips do |x|
x.report("HashExample") do
Rock.new.wins_against?(Rock.new)
Rock.new.wins_against?(Paper.new)
Rock.new.wins_against?(Scissors.new)
Paper.new.wins_against?(Rock.new)
Paper.new.wins_against?(Paper.new)
Paper.new.wins_against?(Scissors.new)
Scissors.new.wins_against?(Rock.new)
Scissors.new.wins_against?(Paper.new)
Scissors.new.wins_against?(Scissors.new)
end
end
@danielpclark
Copy link
Author

Results

Warming up --------------------------------------
         HashExample    17.301k i/100ms
Calculating -------------------------------------
         HashExample    197.053k (± 2.8%) i/s -    986.157k in   5.009061s
Run options: --seed 56085

# Running:

.........

Finished in 0.002015s, 4466.5766 runs/s, 4466.5766 assertions/s.

9 runs, 9 assertions, 0 failures, 0 errors, 0 skips

@danielpclark
Copy link
Author

danielpclark commented May 13, 2017

Writing a quick benchmark to see how fast hash lookups are I find that using an Object as a key has the worst possible performance.

A = Object.new

def a
  :result
end

def value_of
  [1]
end

hash_of = {a: [1], "a" => [1], :result => [1], A => [1]}


require "benchmark/ips"
Benchmark.ips do |x|
  x.report("Method Call") do
    value_of()
  end

  x.report("Hash w/ Symbol key") do
    hash_of[:a]
  end

  x.report("Hash w/ String key") do
    hash_of["a"]
  end

  x.report("Hash w/ Method key") do
    hash_of[a]
  end

  x.report("Hash w/ Constant key") do
    hash_of[A]
  end

  x.compare!
end

Results

Warming up --------------------------------------
         Method Call   144.797k i/100ms
  Hash w/ Symbol key   164.880k i/100ms
  Hash w/ String key   156.820k i/100ms
  Hash w/ Method key   141.293k i/100ms
Hash w/ Constant key    92.234k i/100ms
Calculating -------------------------------------
         Method Call      5.511M (± 2.7%) i/s -     27.656M in   5.021800s
  Hash w/ Symbol key      7.581M (± 2.7%) i/s -     37.922M in   5.006266s
  Hash w/ String key      6.620M (± 2.9%) i/s -     33.089M in   5.002952s
  Hash w/ Method key      4.542M (± 5.0%) i/s -     22.748M in   5.022166s
Hash w/ Constant key      1.837M (± 1.0%) i/s -      9.223M in   5.022241s

Comparison:
  Hash w/ Symbol key:  7580536.5 i/s
  Hash w/ String key:  6619759.4 i/s - 1.15x  slower
         Method Call:  5511494.2 i/s - 1.38x  slower
  Hash w/ Method key:  4541697.4 i/s - 1.67x  slower
Hash w/ Constant key:  1836695.9 i/s - 4.13x  slower

@matugm
Copy link

matugm commented May 13, 2017

Could you add a x.compare! to you benchmark so we can see precentages?

@matugm
Copy link

matugm commented May 13, 2017

Also it could be interesting to benchmark case statements.

@danielpclark
Copy link
Author

@matugm I updated it with x.compare!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment