Skip to content

Instantly share code, notes, and snippets.

@boddhisattva
Last active March 25, 2016 10:50
Show Gist options
  • Save boddhisattva/b03d1c3b097051deb9f7 to your computer and use it in GitHub Desktop.
Save boddhisattva/b03d1c3b097051deb9f7 to your computer and use it in GitHub Desktop.
Ruby the usage of to_s within a loop by using old hash syntax wrt the constant
require "benchmark/ips"
Benchmark.ips do |x|
x.report("fast code description") { 38.to_roman_fast}
x.report("slow code description") { 38.to_roman_slow }
x.compare!
end
2.3.0 :220 > class Numeric
2.3.0 :221?>
2.3.0 :222 > ROMAN_NUMERALS = { 'I' => 1,
2.3.0 :223 > 'V' => 5,
2.3.0 :224 > 'X' => 10,
2.3.0 :225 > 'L' => 50,
2.3.0 :226 > 'C' => 100,
2.3.0 :227 > 'D' => 500,
2.3.0 :228 > 'M' => 1000 }
2.3.0 :229?> end
(irb):222: warning: already initialized constant Numeric::ROMAN_NUMERALS
(irb):30: warning: previous definition of ROMAN_NUMERALS was here
=> {"I"=>1, "V"=>5, "X"=>10, "L"=>50, "C"=>100, "D"=>500, "M"=>1000}
2.3.0 :230 > 'M' => 1000 }^C
2.3.0 :230 > class Numeric
2.3.0 :231?>
2.3.0 :232 > ROMAN_NUMERALS = { 'I' => 1,
2.3.0 :233 > 'V' => 5,
2.3.0 :234 > 'X' => 10,
2.3.0 :235 > 'L' => 50,
2.3.0 :236 > 'C' => 100,
2.3.0 :237 > 'D' => 500,
2.3.0 :238 > 'M' => 1000 }
2.3.0 :239?>
2.3.0 :240 >
2.3.0 :241 > ROMAN_NUMERALS_SLOW = { I: 1,
2.3.0 :242 > V: 5,
2.3.0 :243 > X: 10,
2.3.0 :244 > L: 50,
2.3.0 :245 > C: 100,
2.3.0 :246 > D: 500,
2.3.0 :247 > M: 1000 }
2.3.0 :248?>
2.3.0 :249 >
2.3.0 :250 > def to_roman_fast
2.3.0 :251?> num = ''
2.3.0 :252?> number_to_convert = self
2.3.0 :253?>
2.3.0 :254 > ROMAN_NUMERALS.values.reverse.each do |val|
2.3.0 :255 > next if val > number_to_convert
2.3.0 :256?>
2.3.0 :257 > if number_to_convert == 4
2.3.0 :258?> return num << 'IV'
2.3.0 :259?> elsif number_to_convert == 9
2.3.0 :260?> return num << 'IX'
2.3.0 :261?> end
2.3.0 :262?>
2.3.0 :263 > quotient, remainder = number_to_convert.divmod(val)
2.3.0 :264?> num << ROMAN_NUMERALS.key(val) * quotient
2.3.0 :265?> number_to_convert = remainder
2.3.0 :266?> end
2.3.0 :267?>
2.3.0 :268 > num
2.3.0 :269?> end
2.3.0 :270?>
2.3.0 :271 > def to_roman_slow
2.3.0 :272?> num = ''
2.3.0 :273?> number_to_convert = self
2.3.0 :274?>
2.3.0 :275 > ROMAN_NUMERALS_SLOW.values.reverse.each do |val|
2.3.0 :276 > next if val > number_to_convert
2.3.0 :277?>
2.3.0 :278 > if number_to_convert == 4
2.3.0 :279?> return num << 'IV'
2.3.0 :280?> elsif number_to_convert == 9
2.3.0 :281?> return num << 'IX'
2.3.0 :282?> end
2.3.0 :283?>
2.3.0 :284 > quotient, remainder = number_to_convert.divmod(val)
2.3.0 :285?> num << ROMAN_NUMERALS_SLOW.key(val).to_s * quotient
2.3.0 :286?> number_to_convert = remainder
2.3.0 :287?> end
2.3.0 :288?>
2.3.0 :289 > num
2.3.0 :290?> end
2.3.0 :291?> end
(irb):232: warning: already initialized constant Numeric::ROMAN_NUMERALS
(irb):222: warning: previous definition of ROMAN_NUMERALS was here
=> :to_roman_slow
2.3.0 :292 > Benchmark.ips do |x|
2.3.0 :293 > x.report("fast code description")
2.3.0 :294?> {27.to_roman_fast}
2.3.0 :295?> x.report("slow code description") { 27.to_roman_slow }
2.3.0 :296?> x.compare!
2.3.0 :297?> end
SyntaxError: (irb):294: syntax error, unexpected '}', expecting =>
from /Users/mohnishgj/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'
2.3.0 :298 > Benchmark.ips do |x|
2.3.0 :299 > x.report("fast code description") {27.to_roman_fast}
2.3.0 :300?> x.report("slow code description") { 27.to_roman_slow }
2.3.0 :301?> x.compare!
2.3.0 :302?> end
Warming up --------------------------------------
fast code description
21.821k i/100ms
slow code description
19.745k i/100ms
Calculating -------------------------------------
fast code description
315.139k (± 7.1%) i/s - 1.571M
slow code description
282.946k (± 8.2%) i/s - 1.422M
Comparison:
fast code description: 315139.2 i/s
slow code description: 282946.3 i/s - same-ish: difference falls within error
=> #<Benchmark::IPS::Report:0x007ff122927000 @entries=[#<Benchmark::IPS::Report::Entry:0x007ff122b909e0 @label="fast code description", @microseconds=5010793.209075928, @iterations=1571112, @ips=315139.15873283846, @ips_sd=22330, @measurement_cycle=21821, @show_total_time=false>, #<Benchmark::IPS::Report::Entry:0x007ff1229cd680 @label="slow code description", @microseconds=5059605.360031128, @iterations=1421640, @ips=282946.28183858417, @ips_sd=23267, @measurement_cycle=19745, @show_total_time=false>], @data=nil>
2.3.0 :303 > Benchmark.ips do |x|
2.3.0 :304 > x.report("fast code description") {38.to_roman_fast}
2.3.0 :305?> x.report("slow code description") { 38.to_roman_slow }
2.3.0 :306?> x.compare!
2.3.0 :307?> end
Warming up --------------------------------------
fast code description
21.783k i/100ms
slow code description
19.684k i/100ms
Calculating -------------------------------------
fast code description
311.486k (± 8.5%) i/s - 1.547M
slow code description
280.524k (± 6.8%) i/s - 1.398M
Comparison:
fast code description: 311486.4 i/s
slow code description: 280523.7 i/s - same-ish: difference falls within error
=> #<Benchmark::IPS::Report:0x007ff122917bf0 @entries=[#<Benchmark::IPS::Report::Entry:0x007ff122a4c1d8 @label="fast code description", @microseconds=5001697.540283203, @iterations=1546593, @ips=311486.3548602659, @ips_sd=26337, @measurement_cycle=21783, @show_total_time=false>, #<Benchmark::IPS::Report::Entry:0x007ff122b912f0 @label="slow code description", @microseconds=5004760.503768921, @iterations=1397564, @ips=280523.66162181617, @ips_sd=18976, @measurement_cycle=19684, @show_total_time=false>], @data=nil>
2.3.0 :308 >
TL';DR : With the old hash syntax, the keys can be represented as strings. With the new syntax it's only symbols.
How/When does this matter - It does when you need hash heys which are strings say for some operation like concatenation with
some other string. If you use the new syntax, and if the hash is looped over, one would have to apply a `to_s` to each of the keys.
2.2.3 :001 > ROMAN_NUMERALS = { 'I' => 1,
2.2.3 :002 > 'V' => 5,
2.2.3 :003 > 'X' => 10,
2.2.3 :004 > 'L' => 50,
2.2.3 :005 > 'C' => 100,
2.2.3 :006 > 'D' => 500,
2.2.3 :007 > 'M' => 1000 }
=> {"I"=>1, "V"=>5, "X"=>10, "L"=>50, "C"=>100, "D"=>500, "M"=>1000}
2.2.3 :008 > ROMAN_NUMERALS = { "I": 1,
2.2.3 :009 > "V": 5,
2.2.3 :010 > "X": 10,
2.2.3 :011 > "L": 50,
2.2.3 :012 > "C": 100,
2.2.3 :013 > "D": 500,
2.2.3 :014 > "M": 1000 }
(irb):8: warning: already initialized constant ROMAN_NUMERALS
(irb):1: warning: previous definition of ROMAN_NUMERALS was here
=> {:I=>1, :V=>5, :X=>10, :L=>50, :C=>100, :D=>500, :M=>1000}
2.2.3 :015 > ROMAN_NUMERALS = { 'I': 1,
2.2.3 :016 > 'V': 5,
2.2.3 :017 > 'X': 10,
2.2.3 :018 > 'L': 50,
2.2.3 :019 > 'C': 100,
2.2.3 :020 > 'D': 500,
2.2.3 :021 > 'M': 1000 }
(irb):15: warning: already initialized constant ROMAN_NUMERALS
(irb):8: warning: previous definition of ROMAN_NUMERALS was here
=> {:I=>1, :V=>5, :X=>10, :L=>50, :C=>100, :D=>500, :M=>1000}
2.2.3 :022 > ROMAN_NUMERALS = { I: 1,
2.2.3 :023 > V: 5,
2.2.3 :024 > X: 10,
2.2.3 :025 > L: 50,
2.2.3 :026 > C: 100,
2.2.3 :027 > D: 500,
2.2.3 :028 > M: 1000 }
(irb):22: warning: already initialized constant ROMAN_NUMERALS
(irb):15: warning: previous definition of ROMAN_NUMERALS was here
=> {:I=>1, :V=>5, :X=>10, :L=>50, :C=>100, :D=>500, :M=>1000}
class Numeric
ROMAN_NUMERALS = { 'I' => 1,
'V' => 5,
'X' => 10,
'L' => 50,
'C' => 100,
'D' => 500,
'M' => 1000 }
ROMAN_NUMERALS_SLOW = { I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000 }
def to_roman_fast
num = ''
number_to_convert = self
ROMAN_NUMERALS.values.reverse.each do |val|
next if val > number_to_convert
if number_to_convert == 4
return num << 'IV'
elsif number_to_convert == 9
return num << 'IX'
end
quotient, remainder = number_to_convert.divmod(val)
num << ROMAN_NUMERALS.key(val) * quotient
number_to_convert = remainder
end
num
end
def to_roman_slow
num = ''
number_to_convert = self
ROMAN_NUMERALS_SLOW.values.reverse.each do |val|
next if val > number_to_convert
if number_to_convert == 4
return num << 'IV'
elsif number_to_convert == 9
return num << 'IX'
end
quotient, remainder = number_to_convert.divmod(val)
num << ROMAN_NUMERALS_SLOW.key(val).to_s * quotient
number_to_convert = remainder
end
num
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment