Skip to content

Instantly share code, notes, and snippets.

@bradleybuda
Created August 2, 2010 21:10
Show Gist options
  • Save bradleybuda/505316 to your computer and use it in GitHub Desktop.
Save bradleybuda/505316 to your computer and use it in GitHub Desktop.
Friendlier histogram.rb with automatic width and height
require 'histogram'
class AutoHistogram
def initialize
@values = []
end
def push(values)
if values.kind_of? Numeric
@values << values
elsif values.respond_to? :each
values.each { |value| push(value) }
else
raise "don't know how to push a #{values.class}"
end
end
# Height and width are given in characters
def report(height = nil, width = nil)
terminal_height, terminal_width = *terminal_size
height ||= terminal_height * 0.9 - 4
width ||= terminal_width * 0.9
max = @values.max
min = @values.min
# Expand bucket size so it feels 'natural' - meaning, it starts
# with a 1, 2, or 5 and the rest is zeros
min_bucket_size = (max - min) / height.to_f
bucket_size = if min_bucket_size < 1
1
else
min_bucket_size_s = min_bucket_size.to_i.to_s
places = min_bucket_size_s.size - 1
first_digit = min_bucket_size_s.chars.first
prefix = case first_digit
when '1' then '2'
when '2', '3', '4' then '5'
when '5', '6', '7', '8', '9' then '10'
end
(prefix + '0' * places).to_i
end
histogram = Histogram.new(min, max, bucket_size)
@values.each { |v| histogram.push(v) }
initial_width = histogram.to_s.split("\n").map(&:size).max
width_scale = initial_width / width
histogram.report(width_scale)
end
private
def terminal_size
%x{stty size}.split.collect { |x| x.to_i }
end
end
if __FILE__ == $0
# Example - requires histogram.rb from http://www.math.kobe-u.ac.jp/~kodama/tips-ruby-histogram.html
h = AutoHistogram.new
20000.times { h.push rand(100) + rand(100) + rand(100) }
h.report
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment