3c3a3292e0db v0.1.0

Initial commit.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 07 Apr 2012 17:33:03 -0400
parents
children 5cd315b5a314
branches/tags v0.1.0
files .gitignore .hgignore README.markdown docs/footer.markdown docs/index.markdown docs/installation.markdown docs/publish.sh docs/title docs/usage.markdown project.clj src/roul/random.clj test/roul/random_test.clj

Changes

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,10 @@
+/target
+/lib
+/classes
+/checkouts
+pom.xml
+*.jar
+*.class
+.lein-deps-sum
+.lein-failures
+.lein-plugins
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,12 @@
+syntax:glob
+target/
+lib/
+classes/
+checkouts/
+pom.xml
+docs/build/
+*.jar
+*.class
+.lein-deps-sum
+.lein-failures
+.lein-plugins
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.markdown	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,44 @@
+roul
+====
+
+Roul (from "roulette") is a tiny Clojure library for working with random numbers
+more easily.
+
+For example:
+
+    (require '[roul.random :as rr])
+
+    ; Get a random integer between 0 and 10
+    (rand-int 10)    ; Default Clojure
+    (rr/rand-int 10) ; Roul
+
+    ; Get a random integer between 10 and 20
+    (+ 10 (rand-int 10)) ; Default Clojure
+    (rr/rand-int 10 20)  ; Roul
+
+    ; Get a random element from a weighted collection
+
+    ; Returns coffee roughly 80% of the time, tea 15%, and soda 5%.
+    (rr/rand-nth-weighted {:coffee 0.80 :tea 0.15 :soda 0.05})
+
+    ; Returns cats roughly twice as often as boots.
+    (rr/rand-nth-weighted [[:boots 14] [:cats 28]])
+
+Installation
+------------
+
+You need Leiningen 2 to use this.  Sorry.
+
+    [roul "0.1.0"]
+
+Usage
+-----
+
+Read the [documentation](http://sjl.bitbucket.org/roul/).
+
+License
+-------
+
+Copyright © 2012 Steve Losh and Contributors
+
+MIT/X11 Licensed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/footer.markdown	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,18 @@
+Created by [Steve Losh](http://stevelosh.com).
+Docs made with [d](http://sjl.bitbucket.org/d/).
+
+<br/><a id='rochester-made' href='http://rochestermade.com' title='Rochester Made'><img src='http://rochestermade.com/media/images/rochester-made-dark-on-light.png' alt='Rochester Made' title='Rochester Made' /></a>
+
+<script type="text/javascript">
+  var _gauges = _gauges || [];
+  (function() {
+    var t   = document.createElement('script');
+    t.type  = 'text/javascript';
+    t.async = true;
+    t.id    = 'gauges-tracker';
+    t.setAttribute('data-site-id', '4f80ace2f5a1f538860000c2');
+    t.src = '//secure.gaug.es/track.js';
+    var s = document.getElementsByTagName('script')[0];
+    s.parentNode.insertBefore(t, s);
+  })();
+</script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/index.markdown	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,11 @@
+Roul (from "roulette") is a tiny Clojure library that makes working with random
+numbers more convenient.
+
+It's still in the early stages of development, but if you can think of something
+useful that should be in it feel free to open a feature request on the issue
+tracker!
+
+* License: MIT/X11
+* Mercurial: <http://bitbucket.org/sjl/roul/>
+* Git: <http://github.com/sjl/roul/>
+* Issues: <http://github.com/sjl/roul/issues/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/installation.markdown	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,10 @@
+Installation
+============
+
+Roul requires Leiningen 2.  Sorry.
+
+Add the following to your `project.clj`:
+
+    [roul "0.1.0"]
+
+Run `lein deps` and you're all set.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/publish.sh	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+rm -rf ./build
+~/lib/virtualenvs/d/bin/d
+hg -R ~/src/sjl.bitbucket.org pull -u
+rsync --delete -a ./build/ ~/src/sjl.bitbucket.org/roul
+hg -R ~/src/sjl.bitbucket.org commit -Am 'roul: Update site.'
+hg -R ~/src/sjl.bitbucket.org push
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/title	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,1 @@
+Roul
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/usage.markdown	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,79 @@
+Usage
+=====
+
+Roul currently contains a few functions in one namespace.  It'll expand in the
+future, but for now that's all it is.
+
+[TOC]
+
+roul.random
+-----------
+
+The `roul.random` namespace contains wrappers around some of Clojure's built-in
+random functions to make them more user friendly, as well as some uniqe
+functions of its own.
+
+The recommended way is to `require` this namespace into your own instead of
+overwriting Clojure's builtins:
+
+    :::clojure
+    (ns foo.core
+      (:require [roul.random :as rr]))
+
+    ; or
+
+    (require '[roul.random :as rr])
+
+### rand
+
+    :::clojure
+    (rand)           ; return a float in [0, 1)
+    (rand end)       ; return a float in [0, end)
+    (rand start end) ; return a float in [start, end)
+
+A wrapper around the built-in `rand`.  Returns a random floating point number
+between `start` (inclusive) and `end` (exclusive).
+
+If not given, `start` defaults to `0` and `end` defaults to `1`.
+
+### rand-int
+
+    :::clojure
+    (rand-int end)       ; return an int in [0, end)
+    (rand-int start end) ; return an int in [start, end)
+
+A wrapper around the built-in `rand-int`.  Returns a random integer between
+`start` (inclusive) and `end` (exclusive).
+
+If not given, `start` defaults to `0`.
+
+### rand-nth
+
+    :::clojure
+    (rand-nth coll) ; return a random element of coll
+
+A wrapper around the built-in `rand-nth`.  Returns a random element of the given
+collection.
+
+This is a transparent wrapper around the builtin, included only for
+completeness.  Unlike the other wrappers no new functionality has been added
+(yet).
+
+### rand-nth-weighted
+
+    :::clojure
+    (rand-nth-weighted coll) ; return a random element of coll
+
+Returns a random element of a weighted collection.
+
+A weighted collection can be any seq of `[choice, weight]` elements.  The
+weights can be arbitrary numbers -- they do not need to add up to anything
+specific.
+
+    :::clojure
+    ; Returns coffee roughly 80% of the time, tea 15%, and soda 5%.
+    (rr/rand-nth-weighted {:coffee 0.80, :tea 0.15, :soda 0.05})
+
+    ; Returns cats roughly twice as often as boots.
+    (rr/rand-nth-weighted [[:boots 14]
+                           [:cats 28]])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project.clj	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,8 @@
+(defproject roul "0.1.0"
+  :license {:name "MIT/X11"}
+  :dependencies [[org.clojure/clojure "1.3.0"]]
+  :plugins [[sjl/lein2-generative "0.1.4.2"]]
+  :generative-path "test/"
+  :url "http://sjl.bitbicket.org/roul/"
+  :min-lein-version "2.0.0"
+  :description "A library that wraps and extends Clojure's random number generators.")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/roul/random.clj	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,45 @@
+(ns roul.random
+  (:refer-clojure :exclude [rand-int rand rand-nth]))
+
+
+(defn rand
+  "Return a random float between start (inclusive) and end (exclusive).
+
+  start defaults to 0
+  end defaults to 1"
+  ([] (clojure.core/rand))
+  ([end] (clojure.core/rand end))
+  ([start end] (+ start (clojure.core/rand (- end start)))))
+
+(defn rand-int
+  "Return a random int between start (inclusive) and end (exclusive).
+
+  start defaults to 0"
+  ([end] (clojure.core/rand-int end))
+  ([start end] (+ start (clojure.core/rand-int (- end start)))))
+
+(defn rand-nth
+  "Return a random element of the collection.  Delegates to the built-in
+  rand-nth for now."
+  [coll]
+  (clojure.core/rand-nth coll))
+
+(defn rand-nth-weighted
+  "Return a random element from the weighted collection.
+
+  A weighted collection can be any seq of [choice, weight] elements.  The
+  weights can be arbitrary numbers -- they do not need to add up to anything
+  specific.
+
+  Examples:
+
+  (rand-nth-weighted [[:a 0.50] [:b 0.20] [:c 0.30]])
+  (rand-nth-weighted {:a 10 :b 200})"
+  [coll]
+  (let [total (reduce + (map second coll))]
+    (loop [i (rand total)
+           [[choice weight] & remaining] (seq coll)]
+      (if (>= weight i)
+        choice
+        (recur (- i weight) remaining)))))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/roul/random_test.clj	Sat Apr 07 17:33:03 2012 -0400
@@ -0,0 +1,50 @@
+(ns roul.random_test
+  (:use clojure.test)
+  (:require [clojure.test.generative.generators :as gen])
+  (:use [clojure.test.generative :only [defspec]])
+  (:require [roul.random :as rr]))
+
+
+(defn abs [i]
+  (if (< i 0)
+    (- i)
+    i))
+
+
+(defn random-smallish-int []
+  (gen/uniform -2000 2000))
+
+(defspec abs-is-never-negative
+  abs
+  [^{:tag `random-smallish-int} n]
+  (assert (not (neg? %))))
+
+
+(defn all-within [actual expected tolerance]
+  (letfn [(is-bad [[i p]]
+            (<= (abs (- p (expected i)))
+                tolerance))]
+    (empty? (remove identity (map is-bad actual)))))
+
+(defn percentquencies [data]
+  (let [freqs (frequencies data)
+        total (reduce + (map second freqs))]
+    (into {} (map (juxt first #(-> % second (/ total) float))
+                  freqs))))
+
+
+(defn random-data [] (gen/vec gen/int))
+(defspec percentquencies-are-sane
+  percentquencies
+  [^{:tag `random-data} data]
+  (assert (= (set (keys %)) (set data))))
+
+
+(deftest test-rand-nth-weighted
+  (testing "Values should be selected approximately according to their weights."
+    (dotimes [_ 10]
+      (let [data (repeatedly 10000 #(rr/rand-nth-weighted {:a 0.5 :b 0.2 :c 0.3}))]
+        (is (all-within (percentquencies data) {:a 0.5 :b 0.2 :c 0.3} 0.05))))
+    (dotimes [_ 10]
+      (let [data (repeatedly 10000 #(rr/rand-nth-weighted {:a 100 :b 900}))]
+        (is (all-within (percentquencies data) {:a 0.10 :b 0.9} 0.05))))))