Skip to content

Instantly share code, notes, and snippets.

@orb orb/roll.clj
Created Sep 11, 2018

Embed
What would you like to do?
an instaparse version of the roll parser, just for fun
(ns roll.core
(:require [instaparse.core :as instaparse]
[clojure.string :as str]))
(def roll-parser
(instaparse/parser "
roll = quantity? <'d'> die-type (operator operand)?
<quantity> = number
<die-type> = number
<operand> = number
operator = '+' | '-' | '*'
number = #'-?[0-9]+'
"))
(def roll-transform
{:number #(Integer/parseInt %)
:operator {"+" + "*" * "-" -}
:roll (fn do-roll
([die-type]
(inc (rand-int die-type)))
([quantity die-type]
(reduce + (take quantity (repeatedly #(do-roll die-type)))))
([quantity die-type operator operand]
(operator (do-roll quantity die-type) operand)))})
(defn roll [roll-spec]
(instaparse/transform roll-transform
(roll-parser (name roll-spec))))
(defn histogram [roll-spec n]
(let [max-width 50
freqs (frequencies (take n (repeatedly #(roll roll-spec))))
scale-max (apply max (max (vals freqs)))
scale (fn [n] (Math/ceil (* max-width (/ n scale-max))))
stars (fn [n] (str/join "" (take n (repeatedly (constantly "*")))))]
(doseq [k (sort (keys freqs))]
(println (format "%5d %s"
k
(stars (scale (freqs k))))))))
(comment
;; roll.core> (histogram :3d6 1000)
;; 3 *
;; 4 *****
;; 5 **************
;; 6 ******************
;; 7 *******************************
;; 8 *******************************
;; 9 **********************************************
;; 10 **************************************************
;; 11 **************************************************
;; 12 ***************************************
;; 13 **************************************
;; 14 ****************************
;; 15 ********************
;; 16 **********
;; 17 *****
;; 18 ****
)
¯
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.