Skip to content

Instantly share code, notes, and snippets.

@boddhisattva
Created March 31, 2016 01:56
Show Gist options
  • Save boddhisattva/71048f3c27131abc95d30367fa82db7f to your computer and use it in GitHub Desktop.
Save boddhisattva/71048f3c27131abc95d30367fa82db7f to your computer and use it in GitHub Desktop.
Roman numerals - comparing two implementations
2.3.0 :001 > require "benchmark/ips"
=> true
2.3.0 :002 > class Fixnum
2.3.0 :003?> VERSION = 1
ROMAN_NUMERALS = { 'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1 }.freeze
def to_roman_fast
return "" if zero?
letter, num = ROMAN_NUMERALS.detect { |roman_numeral, number| number <= self }
rest = self - num
"#{letter}#{rest.to_roman_fast}"
end
def to_roman_slow
number_to_convert = self
ROMAN_NUMERALS.each_with_object("") do |(roman_numeral, numeric_equivalent), roman_equivalent|
next if numeric_equivalent > number_to_convert
quotient, remainder = number_to_convert.divmod(numeric_equivalent)
number_to_convert = remainder
roman_equivalent << roman_numeral * quotien2.3.0 :004?>
2.3.0 :005 > ROMAN_NUMERALS = { 'M' => 1000,
2.3.0 :006 > 'CM' => 900,
2.3.0 :007 > 'D' => 500,
2.3.0 :008 > 'CD' => 400,
2.3.0 :009 > 'C' => 100,
2.3.0 :010 > 'XC' => 90,
2.3.0 :011 > 'L' => 50,
2.3.0 :012 > 'XL' => 40,
2.3.0 :013 > 'X' => 10,
2.3.0 :014 > 'IX' => 9,
2.3.0 :015 > 'V' => 5,
2.3.0 :016 > 'IV' => 4,
2.3.0 :017 > 'I' => 1 }.freeze
2.3.0 :018?>
2.3.0 :019 > def to_roman_fast
2.3.0 :020?> return "" if zero?
2.3.0 :021?> letter, num = ROMAN_NUMERALS.detect { |roman_numeral, number| number <= self }
2.3.0 :022?> rest = self - num
2.3.0 :023?> "#{letter}#{rest.to_roman_fast}"
2.3.0 :024?> end
2.3.0 :025?>
2.3.0 :026 > def to_roman_slow
2.3.0 :027?> number_to_convert = self
2.3.0 :028?>
2.3.0 :029 > ROMAN_NUMERALS.each_with_object("") do |(roman_numeral, numeric_equivalent), roman_equivalent|
2.3.0 :030 > next if numeric_equivalent > number_to_convert
2.3.0 :031?>
2.3.0 :032 > quotient, remainder = number_to_convert.divmod(numeric_equivalent)
2.3.0 :033?> number_to_convert = remainder
2.3.0 :034?> roman_equivalent << roman_numeral * quotient
2.3.0 :035?> end
2.3.0 :036?> end
2.3.0 :037?>
2.3.0 :038 > end
=> :to_roman_slow
2.3.0 :039 > Benchmark.ips do |x|
2.3.0 :040 > x.report("fast code description") { 23.to_roman_fast }
2.3.0 :041?> x.report("slow code description") { 23.to_roman_slow }
2.3.0 :042?> x.compare!
2.3.0 :043?> end
Warming up --------------------------------------
fast code description
8.186k i/100ms
slow code description
22.396k i/100ms
Calculating -------------------------------------
fast code description
86.120k (± 7.1%) i/s - 433.858k
slow code description
296.277k (± 6.8%) i/s - 1.478M
Comparison:
slow code description: 296276.6 i/s
fast code description: 86120.3 i/s - 3.44x slower
=> #<Benchmark::IPS::Report:0x007fbd1493f818 @entries=[#<Benchmark::IPS::Report::Entry:0x007fbd13858e78 @label="fast code description", @microseconds=5063694.477081299, @iterations=433858, @ips=86120.27317565453, @ips_sd=6130, @measurement_cycle=8186, @show_total_time=false>, #<Benchmark::IPS::Report::Entry:0x007fbd138b32d8 @label="slow code description", @microseconds=5013072.0138549805, @iterations=1478136, @ips=296276.63372336526, @ips_sd=20182, @measurement_cycle=22396, @show_total_time=false>], @data=nil>
2.3.0 :044 >
Impl 1 - http://exercism.io/submissions/61ad4a5a70ab4194aaf09875997da322
Impl 2 - (my implementation took quite a bit of insipration from - http://exercism.io/submissions/525704159fcfeabc2200023a)
class Fixnum
VERSION = 1
ROMAN_NUMERALS = { 'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1 }.freeze
def to_roman_fast
return "" if zero?
letter, num = ROMAN_NUMERALS.detect { |roman_numeral, number| number <= self }
rest = self - num
"#{letter}#{rest.to_roman_fast}"
end
def to_roman_slow
number_to_convert = self
ROMAN_NUMERALS.each_with_object("") do |(roman_numeral, numeric_equivalent), roman_equivalent|
next if numeric_equivalent > number_to_convert
quotient, remainder = number_to_convert.divmod(numeric_equivalent)
number_to_convert = remainder
roman_equivalent << roman_numeral * quotient
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment