Create a gist now

Instantly share code, notes, and snippets.

Simple Discrete Distribution

Big Idea

The BIG IDEA here is just that I can create a list of things I want to work on with my spare time and generate a random list of things to practice each day. The idea that it's randomized gives it a little more excitement for me and (I think) makes it easier for me to challenge myself to learn and grow.

class Distribution < Struct.new(:hash)
def proportional_keys
@proportional_keys ||= hash.reduce([]) do |list, (key, proportion)|
list += Array.new(proportion, key)
end
end
def sample(n=1)
n.times.map do
proportional_keys.sample
end
end
end
BayesDistribution = Distribution.new({
"Apply Bayes' theory to wide range of models" => 2,
"Grok PyMC3" => 2,
"Perform own derivations" => 1,
"Blog on Bayes" => 2})
DeepLearningDistribution = Distribution.new({
"Grok the current deep learning literature" => 2,
"Apply deep learning to own data" => 3,
"Blog on deep learning" => 2})
VisualizationDistribution = Distribution.new({
"Apply creativity and focus to own data" => 4,
"Deliver complete projects" => 6,
"Coordinate and organize underlying visualization data" => 3,
"Master Pandas" => 2,
"Blog on visualization" => 4,
"Grok D3" => 3})
NodeDistribution = Distribution.new({
"Grok and deliver Express" => 2,
"Deliver Rethink" => 1,
"Blog on Node.js" => 2})
TDCSDistribution = Distribution.new({
"Conduct tDCS Experiments" => 3})
class ServiceObject
def self.execute(*args)
new(*args).execute
end
end
class CombineDistributions < ServiceObject
attr_reader :distributions
def initialize(distributions)
@distributions = Array(distributions)
end
def combined
@combined ||= distributions.reduce({}) do |hash, distribution|
hash.merge(distribution.hash)
end
end
def distribution
@distribution = Distribution.new(combined)
end
def execute
return distribution
end
end
Combined = CombineDistributions.execute([
BayesDistribution,
DeepLearningDistribution,
VisualizationDistribution,
NodeDistribution,
TDCSDistribution])
class Summarize < Struct.new(:sample)
def count(round=false)
value = Array(sample).reduce(Hash.new(0)) do |hash, e|
hash[e] += 1
hash
end
round ? simplify_hash(value) : value
end
def simplify(frequency, factor=nil)
factor ||= order_of_magnitude(frequency) * -1
frequency.round(factor)
end
def sum_hash(hash)
hash.reduce(0) {|s, (_k, v)| s + v}
end
def order_of_magnitude(frequency)
Math.log10(frequency).floor
end
def simplify_hash(hash)
total = sum_hash(hash)
factor = [order_of_magnitude(total) - 1, 0].max * -1
hash.reduce({}) do |h, (k, v)|
h[k] = simplify(v, factor)
h
end
end
end
require 'active_support/all'
class Calendar < ServiceObject
attr_reader :distribution, :opts
def initialize(distribution, opts={})
@distribution = distribution
@opts = opts.with_indifferent_access
end
def period
@period ||= opts.fetch(:period, 2.days)
end
def n
@n ||= opts.fetch(:n, 45)
end
def start_on
@start_on ||= opts.fetch(:start_on, Time.now.to_date)
end
def end_on
@end_on ||= start_on + ((period / 1.day) * n)
end
def date_from(epoch)
Time.at(epoch).to_date
end
def epoch_from(date)
date.to_time.to_i
end
def iteration_range
@iteration_range ||= (epoch_from(start_on)..epoch_from(end_on))
end
def tasks
@tasks ||= iteration_range.step(period).reduce({}) do |hash, epoch|
hash[date_from(epoch)] = distribution.sample[0]
hash
end
end
def execute
tasks
end
end
def get_assignment
Combined.sample.first
end
def events
@events ||= Calendar.execute(Combined).map do |start_date, title|
[title, start_date.to_datetime.strftime("%D")]
end
end
require 'csv'
def write_events!(filename="/tmp/events.csv")
CSV.open(filename, 'wb') do |csv|
csv << ["title", "start_on"]
events.each do |event|
csv << event
end
end
true
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment