Skip to content

Instantly share code, notes, and snippets.

@Arcovion
Created July 11, 2014 01:36
Show Gist options
  • Save Arcovion/e346eb1daa037fe32d43 to your computer and use it in GitHub Desktop.
Save Arcovion/e346eb1daa037fe32d43 to your computer and use it in GitHub Desktop.
Ruby code golf: Delimiting a number with commas

61 chars:

$><<('%f'%gets).gsub(/\d(?=\d{3}+\.)/,'\&,').sub(/\.?0+$/,'')

Handles floats, integers, signed numbers and strings. Also strips trailing zeros and avoids scientific notation.

Here's a cleaned up method that lets you choose the delimiter and set the floating point precision:

def delimit number, precision=6, delimiter=?,
  format("%.#{precision}f", number).gsub /(?<=\d)(?=\d{3}+\.)/, delimiter
end

Now some lambdas to replicate rails' helpers:

number_with_delimiter=->n{('%f'%n).gsub(/\d(?=\d{3}+\.)/,'\&,').sub /\.?0+$/,''}
number_with_precision=->(n,p=6,d=?,){("%.#{p}f"%n).gsub /\d(?=\d{3}+\.)/,'\&'+d}

Rails also lets you set a custom seperator, but that's trivial: .tr(?., seperator)

Lets compare the output:

tests = [123, 0, 1.23456789, -1.23456789, 123456789, -123456789, 12345.6789, 0.0000123456789, 1234567890000000.0]

p tests.map{ |n| number_with_delimiter n }
p tests.map{ |n| number_with_precision n, precision: 2, delimiter: ?_ }
puts
p tests.map{ |n| number_with_delimiter.call n }
p tests.map{ |n| number_with_precision.call n, 2, ?_ }
["123", "0", "1.23456789", "-1.23456789", "123,456,789", "-123,456,789", "12,345.6789", "1.23456789e-05", "1.23456789e+15"]
["123.00", "0.00", "1.23", "-1.23", "123_456_789.00", "-123_456_789.00", "12_345.68", "0.00", "1_234_567_890_000_000.00"]

["123", "0", "1.234568", "-1.234568", "123,456,789", "-123,456,789", "12,345.6789", "0.000012", "1,234,567,890,000,000"]
["123.00", "0.00", "1.23", "-1.23", "123_456_789.00", "-123_456_789.00", "12_345.68", "0.00", "1_234_567_890_000_000.00"]

Benchmark via the fruity gem:

compare do
  rails_delim{ tests.map{ |n| number_with_delimiter n } }
  rails_delim_precise{ tests.map{ |n| number_with_precision n, precision: 2, delimiter: ?_ } }

  golf_delim{ tests.map{ |n| number_with_delimiter.call n } }
  golf_delim_precise{ tests.map{ |n| number_with_precision.call n, 2, ?_ } }
  
  delimit{ tests.map{ |n| delimit n } }
end
Running each test 65536 times. Test will take about 22 minutes.
delimit is faster than golf_delim_precise by 19.999999999999996% ± 10.0%
golf_delim_precise is faster than golf_delim by 19.999999999999996% ± 10.0%
golf_delim is faster than rails_delim by 4x ± 0.1
rails_delim is faster than rails_delim_precise by 3x ± 0.1 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment