Skip to content

Instantly share code, notes, and snippets.

@ramonrails
Created December 19, 2022 16:02
Show Gist options
  • Save ramonrails/bbb53e21fe446e66c145a3e20c627717 to your computer and use it in GitHub Desktop.
Save ramonrails/bbb53e21fe446e66c145a3e20c627717 to your computer and use it in GitHub Desktop.
ruby range with output based on multiples of 3, 5, 15
# frozen_string_literal: true
require 'benchmark'
# synopsis
#
# rubocop suggested syntax is
# * costlier on execution
# * not really that super easy to read and maintain than case statement
# * adds more number of lines
# * `zero?` is syntactical-sugar but high cost on execution
# case statement
# * is fastest in execution
# * seems most suitable for production
# one-liner
# * is just a show-off :)
# * but it does work too!
# sample output:
#
# 1 2 Ping 4 Pong Ping 7 8 Ping Pong 11 Ping 13 14 PingPong 16 17 Ping 19 Pong
# Ping 22 23 Ping Pong 26 Ping 28 29 PingPong 31 32 Ping 34 Pong Ping 37 38 Ping
# Pong 41 Ping 43 44 PingPong 46 47 Ping 49 Pong Ping 52 53 Ping Pong 56 Ping 58
# 59 PingPong 61 62 Ping 64 Pong Ping 67 68 Ping Pong 71 Ping 73 74 PingPong 76
# 77 Ping 79 Pong Ping 82 83 Ping Pong 86 Ping 88 89 PingPong 91 92 Ping 94 Pong
# Ping 97 98 Ping Pong
#
# Benchmarks
#
# Rehearsal ------------------------------------------------------------
# one liner 0.026752 0.000098 0.026850 ( 0.026848)
# one liner (rubocop) 0.031388 0.000084 0.031472 ( 0.031474)
# case statement 0.026730 0.000095 0.026825 ( 0.026840)
# case statement (rubocop) 0.030073 0.000081 0.030154 ( 0.030189)
# --------------------------------------------------- total: 0.115301sec
#
# user system total real
# one liner 0.027161 0.000050 0.027211 ( 0.027212)
# one liner (rubocop) 0.030034 0.000046 0.030080 ( 0.030083)
# case statement 0.026946 0.000100 0.027046 ( 0.027059)
# case statement (rubocop) 0.031117 0.000055 0.031172 ( 0.031173)
#
# One-liner ruby statement. Complex to maintain. Not ideal.
#
# @param [Range] range -> ruby object
#
# @return [String] concatenated string of final output
#
def ping_pong_one_liner(range = 1..100)
return 'Hey! I am smart :) Give me a range' unless range.is_a?(Range)
range.map {|e| e % 15 == 0 ? 'PingPong' : (e % 5 == 0 ? 'Pong' : (e % 3 == 0 ? 'Ping' : e )) }.join(' ')
end
#
# Using case statement. Easier to maintain than one-liner
#
# @param [Range] range -> ruby object
#
# @return [String] concatenated string of final output
#
def ping_pong_case(range = 1..100)
return 'Hey! I am smart :) Give me a range' unless range.is_a?(Range)
range.map do |e|
case
when e % 15 == 0 then 'PingPong'
when e % 5 == 0 then 'Pong'
when e % 3 == 0 then 'Ping'
else
e
end
end.join(' ')
end
#
# One-liner ruby statement, corrected with rubocop
#
# @param [Range] range -> ruby object
#
# @return [String] concatenated string of final output
#
def ping_pong_one_liner_rubocop(range = 1..100)
return 'Hey! I am smart :) Give me a range' unless range.is_a?(Range)
range.map do |e|
if (e % 15).zero?
'PingPong'
else
(if (e % 5).zero?
'Pong'
else
((e % 3).zero? ? 'Ping' : e)
end)
end
end.join(' ')
end
#
# Using case statement, corrected with rubocop
#
# @param [Range] range -> ruby object
#
# @return [String] concatenated string of final output
#
def ping_pong_case_rubocop(range = 1..100)
return 'Hey! I am smart :) Give me a range' unless range.is_a?(Range)
range.map do |e|
if (e % 15).zero?
'PingPong'
elsif (e % 5).zero?
'Pong'
elsif (e % 3).zero?
'Ping'
else
e
end
end.join(' ')
end
# run
#
puts ping_pong_one_liner(1..100)
puts "\nBenchmarks\n\n"
Benchmark.bmbm do |x|
x.report('one liner') { 1000.times { ping_pong_one_liner(1..100) } }
x.report('one liner (rubocop)') { 1000.times { ping_pong_one_liner_rubocop(1..100) } }
x.report('case statement') { 1000.times { ping_pong_case(1..100) } }
x.report('case statement (rubocop)') { 1000.times { ping_pong_case_rubocop(1..100) } }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment