Last active
March 25, 2016 10:50
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 > |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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