Bike Bingo in Clojure

So I’m admittedly a total newb in Clojure, but in the spirit of expanding my repertoire, I like to tackle problems in it now and again. So here’s what I want from you rare folks who somehow find these posts: enlighten me. Here’s my attempt at solving a trivial problem in what is surely not idiomatic Clojure. So why not shine a little light my way and tell me how you’d do it.

The Challenge

I’m in a biking-for-beer competition and the side game this month is bike bingo. All bikers know the potential tiles (which come in such flavors as “Bike at least 30 miles in one day” or “Pass someone on a tall bike”), but we don’t know the board layout. We spend the month completing as many of the tiles as possible, and the person with the most bingos at the end of the month wins beer. And sweet, sweet, arrogant pride.

So now we need a board. I figure we only need one board, because we’ll all have earned different tiles (opposite of standard bingo where everyone plays with the same numbers but different boards). The board should be somewhat random, but we’d also like to reward those who completed the hardest tiles.

The Solution

Here’s my solution. Tear it apart.

(ns bike-bingo
  (:require
   ;; We'll use cl-format to draw the board.
   [clojure.contrib.pprint :as pp]))

;; Here's our 5x5 bingo board. We're counting horizontal, vertical,
;; diagonal, four corners, and blackout.  The numbers in each square
;; represent how many bingos that square is involved in (excluding
;; blackout).
;;
;; It's been predetermined that the middle square, [2 2], will be "Ride
;; more than 1 mile", so I'm leaving it out.
;;
;;    | 0 | 1 | 2 | 3 | 4 |
;; ---+---+---+---+---+---|
;;  0 | 4 | 2 | 2 | 2 | 4 |
;; ---+---+---+---+---+---|
;;  1 | 2 | 3 | 2 | 3 | 2 |
;; ---+---+---+---+---+---|
;;  2 | 2 | 2 | x | 2 | 2 |
;; ---+---+---+---+---+---|
;;  3 | 2 | 3 | 2 | 3 | 2 |
;; ---+---+---+---+---+---|
;;  4 | 4 | 2 | 2 | 2 | 4 |
;;    +---+---+---+---+---|
;;
;; Given the illustration above, we're going to fill the most valuable
;; slots first using the most difficult tiles. Here's our board
;; filling order:

(def *board-priority*
	 [[0 0] [0 4] [4 0] [4 4]
	  [1 1] [1 3] [3 1] [3 3]
	  [0 1] [0 2] [0 3] [1 0]
	  [1 2] [1 4] [2 0] [2 1]
	  [2 3] [2 4] [3 0] [3 2]
	  [3 4] [4 1] [4 2] [4 3]])

;; To determine which tiles are the hardest, we'll take a look at how
;; many people earned them. Not perfect, but it'll do. Here's a map of
;; tiles to times completed.

(def *freq-map*
	 {"Ride more than 10 miles"                                7
	  "Ride more than 20 miles"                                3
	  "Ride more than 30 miles"                                3
	  "Ride more than 40 miles"                                2
	  "Ride more than 50 miles"                                4
	  "Ride more than 100 miles"                               1
	  "Ride between 12:00AM and 5:00AM"                        2
	  "Ride in inclement weather"                              5
	  "Get yelled at by a stranger"                            5
	  "Hit 30mph (downhill OK)"                                8
	  "Ride to work every day one week"                        5
	  "Go mountain biking"                                     2
	  "Bike home from the bar"                                 5
	  "Bike up Summit (Ramsey) hill"                           1
	  "Bike on the Greenway"                                   5
	  "Ride the Minneapolis Grand Rounds"                      2
	  "Ride from DT Minneapolis to DT St. Paul or vice versa"  1
	  "Ride outside the 494-694 loop"                          5
	  "Follow all traffic laws (yes, even stop signs)"         8
	  "Get a flat tire"                                        5
	  "Change a flat tire"                                     3
	  "Get honked at by a stranger"                            5
	  "Bike in a group of 5 or more people"                    4
	  "Pass someone on a Segway"                               2
	  "Pass someone on a tall bike"                            2
	  "Participate in a public bike event"                     4
	  "Watch a public bike event"                              1
	  "Track stand for 30 seconds"                             2})

;; Here's a simple HTML board template with some `cl-format'
;; directives in it. `~{' and `~}' start and end loops, `~a' is
;; replaced with some value. (Todo: It might be interesting to use
;; Enlive for this instead (http://github.com/cgrand/enlive).)

(def *template*
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
  <head>
	<style type=\"text/css\" media=\"screen\">
		td {
			border: 2px solid black;
			padding: 10px;
			width: 150px;
			height: 150px;
			text-align: center;
			font-weight: bold;
		}
	</style>
  </head>
  <body>
	<table>
		~{<tr>
			~{<td>~a</td>
			~}
		</tr>
		~}
	</table>
  </body>
</html>
")

;; Each tile will be selected at random, but I'd really like to give
;; the hardest tiles a good chance to hit the most valuable
;; squares. This function will transform their weight into the number
;; of entries they'll be getting in the hat.
;;
;; If someone has a more mathematically clever solution for this
;; transformation, I'm all ears.

(defn weight-transform [x]
  (* x x x))

;; Weight is inversely proportional to frequency from our freq-map, so
;; we subtract the times seen from 1 + most frequent to determine
;; it.
;;
;; Though, would it make more sense to make this an inverse of the
;; actually frequency divided by the number of people in the
;; contest (greatest possible frequency)?

(defn freq-to-weight [freq-map]
  (let [biggest (inc (apply max (vals freq-map)))]
	(apply hash-map (flatten
					 (for [pair freq-map] (list (pair 0) (- biggest (pair 1))))))))

;; Given the weight map and our transforming function, fill the hat
;; with an appropriate number of entries for each tile.

(defn fill-hat [weight-map weight-transform]
  (flatten (for [pair weight-map] (repeat (weight-transform (pair 1)) (pair 0)))))

;; Now we build up our board in order of priority.

(defn build-board [hat priority]
  (loop [board {} hat hat priority priority]
	;; Once we've filled all our tiles from the priority list, we'll
	;; place "Bike more than 1 mile" at the center.
	(if (= (count priority) 0)
	  (assoc board [2 2] "Bike more than 1 mile")
	  ;; Pull a random item from the hat. More heavily rated items
	  ;; have more entries in the hat and are more likely to be drawn.
	  (let [value (nth hat (rand-int (count hat)))]
		(recur
		 ;; Place the tile on the board.
		 (assoc board (first priority) value)
		 ;; Remove all entries for that tile from the hat. (Good thing
		 ;; this isn't a real hat.)
		 (remove #(= % value) hat)
		 ;; Continue with the remaining priority list.
		 (rest priority))))))

;; `cl-format' will really like our board if it's nested vectors. Hash
;; table, not so much.

(defn board-to-nested-vector [board]
  (vec (for [row (range 5)]
		 (vec (for [col (range 5)]
				(board [row col]))))))

;; A simple bit of business

(defn print-board [board template]
  (pp/cl-format true template (board-to-nested-vector board)))

;; And finally, we do the work.

(-> *freq-map*
	(freq-to-weight)
	(fill-hat weight-transform)
	(build-board *board-priority*)
	(print-board *template*))

Here’s the result.

Posted in Clojure, Programming | Tagged , , , | Leave a comment

anything-project-files.el

;; As promised `anything-project-files'. This smattering of code
;; allows you to define and load projects. Projects, once loaded, will
;; be indexed for all interesting files, which will let you make an
;; `anything' command to rule them all.
;; 
;; Note: This is not intended to be a robust Emacs package, just an
;; example. Aw-right?  Good. Let's start.
anything-project-files

anything-project-files

;; The Common Lisp library for Emacs Lisp gives us keyword arguments
;; for defun*
(require 'cl)

(defvar projects (list) "This keeps track of all available projects.")
(defvar project (list) "And here's our current project.")
(defvar project-index (list) "This will store the project index of files.")
(defvar project-default-filetypes
  '("*.el" "*.rb" "*.py" "*.rb" "*.clj" "*.php" "*.js" "*.html")
  "Files for indexing.")

;; Before we can build `anything-project-files', we need to have an
;; idea of what a project is.  For the purposes of this post, a
;; project will have a name, a root directory, and a list of filetypes
;; we want to index. Change this default file list to suit your own
;; needs.
;;  
;; By the way, `&key' gives us keyword arguments, you can use a symbol
;; or a list of the form `(keyname default-value)' to designate a
;; keyword.
;;  
;; Anything candidates can be a list of `(DISPLAY . REAL)' pairs, so
;; we throw the name up front to serve as the `DISPLAY' component."

(defun* project-create (name &key root (indexed-files project-default-filetypes))
  "Add a project to the list or projects."
  (add-to-list 'projects
			   (cons name
					 `((:name . ,name)
					   (:root . ,root)
					   (:indexed-files . ,indexed-files)))))

;; The handy, dandy function below makes it real easy to get a project
;; component in the form of `(project :root)' or `(project :name)'.
;; (Elisp is a Lisp-2, so function can have the same name as
;; variables.)

(defun project (key)
  (cdr (assoc key project)))

;; Here's the code that indexes our project.

(defun project-reindex ()
  "Update your projects index of files."
  (interactive)
  ;; Travel to the project root
  (cd (project :root))
  ;; Using our `indexed-files', create a string that we can toss into a
  ;; find command.  It'll look like "'*.el' -or -name '*.rb'...".
  ;;
  ;; For a big project, we don't want to be stuck waiting while it
  ;; indexes, so we have to do a little jig-hoolery to make this work
  ;; async. Firstly, that means keeping track of the current buffer,
  ;; and switching to a temporary one in which to do our work.
  (let* ((b (current-buffer))
		 (file-types (mapconcat #'identity (project :indexed-files) " -or -name ")))
	;; And here's our temp buffer.
	(switch-to-buffer "*project-index*")
	;; I'll use `tramp-handle-shell-command' as it returns a process
	(let ((process (tramp-handle-shell-command
					"find . -type f -name '*.el' &" (current-buffer))))
	  ;; And that lets me set a sentinel (callback) for when the
	  ;; process is complete
	  (set-process-sentinel process 'project-load-index))
	(message "Indexing...")
	;; The work has been started, so we switch back to where we were
	;; when we called the command.
	(switch-to-buffer b)))

;; Here's my callback function. `p' is the process and `s' is a
;; message string, which I'll ignore here.
(defun project-load-index (p s)
  ;; Now we'll just split-string on newline for our process buffer.
  (setq project-index
		(split-string
		 (with-current-buffer (process-buffer p)
		   (buffer-string))))
  ;; Goodbye
  (kill-buffer (process-buffer p))
  (message "Indexing complete."))

;; We load the project by selecting from a list an anything
;; buffer. Nice.
(defun project-load ()
  (interactive)
  (setq project
		(anything
		 '((name . "Load Project")
		   (candidates . projects)
		   ;; `anything' usually wants to do something with our selected candidate,
		   ;; but here I'm just going to return it.
		   (action . (("Return" . identity))))))
  ;; The project is set, let's index it.
  (project-reindex))


;; And finally, the payload.
(defun anything-project-files ()
  (interactive)
  (anything
   '((name . "Project Find File")
	 (candidates . project-index)
	 ;; `display-to-real' will take the filename selection and add our
	 ;; project root before any action is performed on it.
	 (display-to-real . (lambda (c) (concat (project :root) "/" c)))
	 (type . file))))


;; Now we'll set up our `emacs-config' project, accepting defaults for `:indexed-files',
;; though we could certainly use `'("*.el")' if we wanted to.
(project-create "emacs-config"
				:root "~/.emacs.d")


;; And there you have it. Load your `emacs-config' project, give it
;; the old `M-x anything-project-files', and you're off to the races.
;;
;; Next steps:
;;
;; Once you've got project context, you can let your imagination run
;; wild coming up with project-related tasks Emacs could be doing for
;; you.
;;
;; Also `project-load' could do more, like tagging the project. Hell,
;; you could create an `anything-project-tags' command, which would
;; rock out pretty hard.
;;
;; Indexing (and tagging) might take a long time on large projects and
;; may not be necessary on every project load. One could consider
;; saving a project index file and loading from that until you
;; explicitly reindex. It'd be pretty simple, but I'll leave that up
;; to you.
;;
;; Until next time, buenos dias! Buenos Aires!
Posted in Emacs, Programming, Uncategorized | Tagged , , , | Leave a comment

So long old friend

As I was biking home, a wicked storm struck up.

And here’s me, pitched half sideways as the wind works to pull me down. My eyes shut tight against the rain.

A shadow, I barely saw, and the next thing I knew I was prone on the street. Struck by some branch pulled from its tree. It hit me in the side of the head.

My helmet, thank heavens. I might be dead.

I’ve felt different since. Calm, oddly. Something knocked loose.

It’s been several days, and I’ve hit the source. My anxiety, struck clear out my brain. It’s a terrible thing, to loose something you’ve held onto so tightly and for so long.

I’m not sure how all this will play out. I’d like to fear for the worst, but it just won’t come.

Posted in Uncategorized | Leave a comment

Anything.else

Last time I blabbed about why anything.el is rad, but left you hanging with just a few out-of-the-box implications or that rad-ness. This time, let’s use anything.el to make our own anything.

The simplest anything.el customization is making your own anything command. You’ll find an example of this in anything-config.el.

(defun my-anything ()
       (interactive)
       (anything-other-buffer
        '(anything-c-source-buffers
          anything-c-source-file-name-history
          anything-c-source-info-pages
          anything-c-source-info-elisp
          anything-c-source-man-pages
          anything-c-source-locate
          anything-c-source-emacs-commands)
        "*my-anything*"))

anything-other-buffer is a simplified version of anything that takes a list of sources for its first argument and a buffer name as its second. So M-x my-anything now gives you an anything selection buffer for all them sources there. You’ll find a wealth of pre-baked sources to choose from in anything-config.el.

The next level of awesomeness comes when you create your own source, which is cheese easy. Do a C-h v on anything-sources. Here you’ll get a lengthy description of how to set one of these buggers up. I’ve made the world’s simplest, most contrived, and most stupidly named source below.

(setf my-pretend-files-source
      '((name . "Name for My Source")
		(candidates . ("a" "list" "of" "files"))
		(type . file)))

There are three mandatory keys: name, candidates, and either action or type. Here I’m pretending to be looking at a list of files, so my type is file. Types provide common actions for things you’ll commonly be working with. They’re a shortcut to actually writing your own actions.

Now that we’ve got a source, let’s make an anything command that uses it.

(defun anything-for-pretend-files ()
  (interactive)
  (anything-other-buffer '(my-pretend-files-source)
                         "*anything-select-buffer-name*"))
anything-for-pretend-files

anything-for-pretend-files

Try out this custom command and hit tab on one of the items to see what you can get with the file type. You can find a list of types with a C-h v of anything-type-attributes.

The "file" type

Options for the file type

If you’re not using a type, you’re using an action. The action key takes a list of alists, each of which maps one name string to one function. Something like this:

(action . (("Action name" . (lambda (selection)
                              (do-some-crazy-shit-to selection)))))

Of course, that lambda could be a function name. Let’s make a real action. A real stupid action!

(setf things-to-say-source
      '((name . "Things To Say")
        (candidates . ("Llama" "Guano" "Mochaccino" "Colostomy"))
        (action . (("Say it!" .
                    (lambda (selection)
                      (message selection)))
                   ("Spray it!" .
                    (lambda (selection)
                      (message (concat selection "thpppt"))))))))

(defun anything-things-to-say ()
  (interactive)
  (anything-other-buffer '(things-to-say-source)
                         "*anything things to say*"))
anything-things-to-say

anything-things-to-say

“Say it!” is the default action, it’s what happens when we hit return. “Spray it!” is an alternate action, which we can select by hitting tab on an item. Remember that this action selection screen is another anything screen, so you can arrow and C-n, C-p through it, but you can also just start typing what you want.

Spray it!

Spray it!

colostomy

Yes!

Next steps

Now these examples are collosally stewpid. What’s more, they use only a tiny fraction of the shite tonne of source options anything‘ll take. If your curiosity is tingling, C-h v anything-sources and prepare to have your amazement blown.

And if you’re really and truly rapt, tune in next time, when we’ll make a for real anything-project-files source that lets you fly around the files of your gigantic, deeply nested project like an airbus on an eightball. It’ll be fun.

Posted in Emacs, Programming | Tagged , , , , | Leave a comment

What can I get for 10 dolla? Anything.el.

Actually it’s not even $10. It’s free, both as in speech and as in nachos. So in the spirit of fanning both sides of the fire, here’s a quick look at anything.el for (gasp) Emacs.

Anything.el is most certainly one of Emacs’s killer features. It’s like ido-mode on steroids, but without the rage or shrinking testicles.

It’s been described as Quicksilver for Emacs, which I guess is kinda true, but that’s not the way I use it.

The documentation for the anything function says it all:

Select anything. In Lisp program, some optional arguments can be used.

Tomas has a poet’s soul, and what he means when he says “some optional arguments can be used” is that you can go bat-shit crazy with what goes in, what gets displayed, what comes out, what happens then, where am I, why am I naked?

But before we get there, let’s cover the basics, shall we?

Installation

M-x auto-install-batch is one option. auto-install.el is here and it’s super handy. Ask for the “anything” package, and you’ll get anything.el, anything-config.el, and anything-match-plugin.el. You’ll want all three. Of course you can just follow the links and install the files yourself if that’s your thing.

Once you’ve got these boys somewhere handy, just

(add-to-list 'load-path "/path/to/anything/folder")
(require 'anything-match-plugin)
(require 'anything-config)

Eval all that, and you’re ready to go.

Usage

M-x anything

Now we’re in the *anything* buffer, and you can have a merry time typing away at any part of the filename or filepath you’re after. Behold as anything.el starts chipping away at the options. C-n and C-p behave as expected. Left and right arrow keys move you to different groups of things.

Because you’ve got the match plugin installed, you get some bonus features. Say you start typing your filename, and you’ve still got 50 matches. Add a space and you’re in a whole new pattern group. So now you start typing something unique in the path, and viola, you’re looking at a full-on double rainbow.

Once you’ve found your victim, hit enter to do the default thing, which is usually the thing you want. If you’ve got eccentric taste, hit tab instead for a list of other things you can do with the thing you’ve selected. Thing.

More Youthage

Things get real crazy when you crack open anything-config.el. Go ahead and anything-imenu up in there and type in “anything”. Here’s a list of custom anything.el commands you get for free. Who needs nachos? You’ll have a riotous time mapping keys to the bazillion-ish anything.el commands the anything-config.el crew have put together for you.

For my part, C-x b is anything-mini, which serves up a combination of buffers and recent files. C-x C-i is anything-imenu, which is awesome wearing a hat. C-x f is anything for recent files, and C-x C-f is ido-find-file, which still trumps anything.el for navigating about file systems.

But wait, there’s more!

You remember that part about going guano building your own who-knows-whats on top of anything.el? It’s anything.el‘s finest suit, but alas, a subject for another post.

Posted in Emacs, Programming | Tagged , , , , | 4 Comments

Visdom, briefly.

Wanna evaluate a line of code in your .vimrc without having to so: the whole damn file?

noremap  <C-x><C-e> :exe getline(".")<CR>

I stole the binding from Emacs (suckers). Put yer cursor on the line of vim script you want to evaluate and control-x, control-e.

Great for testing mappings and commands and all whatnot.

You do have your caps lock remapped to control, right? Don’t make me check your pinky.

Posted in Programming, Vim | Tagged , , , , | Leave a comment

Change Little Word, Change

I’m back (to blogging) and aroused from my meat coma with some vim wisdom to share (vi-sdom?). Here a handy mapping to make your day better.

Of course you know that cw (mnemonically “change word”) replaces from the cursor to the end of a word. But changing a part of something in snake_case or CamelCase is a slightly bigger pain in the carpal-T. So may I present clw, mnemonically “change little word”.

noremap clw c/[_A-Z]

Simplicity itself, no?

mnemonic, not pneumonic

coma, not comma

Posted in Programming, Vim | Tagged , , , , | Leave a comment

Black-Listed

My Flash logger happend upon some output from an ad scanner at huffingtonpost.com. Without further ado, here’s the black list:

whore, slut, lapdance, porno, porn, weed, kill, attack, rape, cock, dick, homo, gay, fraud, gambling, slavery, holocaust, racial, murder, killing, cemetery, suicide, noose, hanging, mortuaries, funeral homes, embarrassing, dirty-sanchez, humiliating, abuse, degrading, dickhead, asshole, shit, fuck, gang, bleed, torture, physical pain, physical harm, violence, gotti, mob, mafia, organized crime, sex, intercourse, pornography, sexual activities, adult themes, knife, rifle, sawed-off, shotgun, gun, glock, bullets, firearms, smokes, blunts, chewing tobacco, pipes, cigars, cigarettes, tobacco

I find this sort of thing facinating, both for what’s included and for what’s omitted.

Posted in Fun, Troof | Leave a comment

Breakfast Suicides

Remember suicide at the soda fountain? A similar technique can be used when you’re almost out of all your cereal. The results are unexpected and sometimes a bit confusing in texture and flavor. But really, not bad.

Cereal Suicide - Cheerios, Fiber One Flakes, and Frosted Mini Wheats

Posted in Food | Tagged , , | 1 Comment

Richard Stallman speaks at the U of MN

Richard Stallman looking like a criminal, but no, really, he's a saint.

Saw Stallman tonight. Whatever else, one must appreciate the man’s dedication. He certainly takes a more hard-line approach to his free software diet than most of us would find convenient, but you must understand that convenience is absolutely not at the top of his priority list.

To him, it’s not just software. Software is his life, and in his life, freedom—freedom to share, freedom to know what you’re putting on your computer (on which may also reside a good chunk of your life), freedom to fix that which is broken, and so on—is non-negotiable. Hypocrite that I am, I’m writing this on a Mac running OS X and in TextMate, a most proprietary text editor, but I’m not oblivious to his concerns. At times his rants feel shallow. But he speaks convincingly about the evils of software patents and those pesky little unadvertised features that find their way into products in which we place our blind trust.

Continue reading

Posted in Programming | Tagged , | Leave a comment