Skip to content

Instantly share code, notes, and snippets.

@tomlobato
Forked from nevans/gist:9374041
Last active July 7, 2019 06:00
Show Gist options
  • Save tomlobato/71e2815ff210dc24a1717df2afd8048a to your computer and use it in GitHub Desktop.
Save tomlobato/71e2815ff210dc24a1717df2afd8048a to your computer and use it in GitHub Desktop.
simple ruby console histogram generator
require 'pry' # gem install pry
# Pass in an enumeration of data and
# (optionally) a block to extract the grouping aspect of the data.
#
# Optional: sort_by lambda (operates on group key and count)
def puts_hist(data, sort_by:nil, &blk)
data = data.map(&blk) if blk
counts = data.each_with_object(Hash.new(0)) {|k,h| h[k]+=1}
max = counts.values.max
width = Pry::Terminal.size!.last
width0 = counts.keys.map{|k|k.to_s.length}.max
width1 = width - width0 - 30
div = [1, max / width1.to_f].max
puts "max: %d; widths: %d, %d; divisor: %0.3f" % [max, width0, width1, div]
puts "bucket count sum bar"
counts = counts.sort_by(&sort_by) if sort_by
acc = 0
counts.each do |k,c|
acc += c
puts "%#{width0}s (%05s %06s) %-#{width1}s" % [("%.2f" % k), c, acc, "#"*((c/div).round)]
end
counts
end
# sample
class RandomGaussian
def initialize(mean, stddev, rand_helper = lambda { Kernel.rand })
@rand_helper = rand_helper
@mean = mean
@stddev = stddev
@valid = false
@next = 0
end
def rand
if @valid then
@valid = false
return @next
else
@valid = true
x, y = self.class.gaussian(@mean, @stddev, @rand_helper)
@next = y
return x
end
end
private
def self.gaussian(mean, stddev, rand)
theta = 2 * Math::PI * rand.call
rho = Math.sqrt(-2 * Math.log(1 - rand.call))
scale = stddev * rho
x = mean + scale * Math.cos(theta)
y = mean + scale * Math.sin(theta)
return x, y
end
end
r=RandomGaussian.new(3, 2)
pp=Array.new(1e4){r.rand}.map{|d|d if d >= 0}.compact
tt = pp.map{|i|
(i*4).to_i/4.0
}.sort
puts_hist(tt)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment