<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Duplo</title>
	<atom:link href="http://kill-0.com/duplo/feed/" rel="self" type="application/rss+xml" />
	<link>http://kill-0.com/duplo</link>
	<description>Building Blocks &#038; Learning Experiences</description>
	<pubDate>Wed, 22 Oct 2008 06:01:51 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>MPD -&gt; MP3 Shoutcast Streaming Patches Accepted</title>
		<link>http://kill-0.com/duplo/2008/10/21/mpd-mp3-shoutcast-streaming-patches-accepted/</link>
		<comments>http://kill-0.com/duplo/2008/10/21/mpd-mp3-shoutcast-streaming-patches-accepted/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 06:01:51 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[C]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[mp3]]></category>

		<category><![CDATA[mpd]]></category>

		<category><![CDATA[music]]></category>

		<category><![CDATA[shoutcast]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/?p=20</guid>
		<description><![CDATA[Just a note to those of you that have tried my MP3 streaming patches for MPD; the patches have been accepted and will be included in the next release of MPD (version 0.14.0).  If you want to try out the development version of MPD, that includes these patches, you can now do so by cloning [...]]]></description>
			<content:encoded><![CDATA[<p>Just a note to those of you that have tried my MP3 streaming patches for MPD; the patches have been accepted and will be included in the next release of MPD (version 0.14.0).  If you want to try out the development version of MPD, that includes these patches, you can now do so by cloning the master git branch at <a href="git://git.musicpd.org/master/mpd.git">git://git.musicpd.org/master/mpd.git</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/10/21/mpd-mp3-shoutcast-streaming-patches-accepted/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MPD FLAC md5sum Support</title>
		<link>http://kill-0.com/duplo/2008/09/03/mpd-flac-md5sum-support/</link>
		<comments>http://kill-0.com/duplo/2008/09/03/mpd-flac-md5sum-support/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 04:40:40 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[C]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[mildred]]></category>

		<category><![CDATA[mpd]]></category>

		<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/?p=18</guid>
		<description><![CDATA[Here&#8217;s another little patch for MPD&#8217;s git repos that allows FLAC files to return md5sum as if it were a bit of metadata, like artist, title, or album.  A FLAC file&#8217;s md5sum is about the closest thing you can get to a unique identifier for that file.  The md5sum is generated from the wav file [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s another little patch for <acronym title="Music Player Daemon: http://musicpd.org/">MPD</acronym>&#8217;s git repos that allows <acronym title="Free Lossless Audio Codec: http://xiph.org/">FLAC</acronym> files to return md5sum as if it were a bit of metadata, like artist, title, or album.  A FLAC file&#8217;s md5sum is about the closest thing you can get to a unique identifier for that file.  The md5sum is generated from the wav file that is encoded when the FLAC file is created, so even if you change the filename, or its tags (vorbis comments), the md5sum will remain the same.  This code is how <a href="http://mildred.xmtp.net/">Mildred</a> correlates songs playing in MPD with songs in its database.</p>
<p>You can find the patch here: <a href="http://kill-0.com/patches/0001-Adds-FLAC-md5sum.patch">http://kill-0.com/patches/0001-Adds-FLAC-md5sum.patch</a></p>
<p>After applying the patch, you&#8217;ll want to re-create your MPD database file.  You can use the <tt>&#8211;create-db</tt> flag to do so, or just delete your old database file before restarting MPD.</p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/09/03/mpd-flac-md5sum-support/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MPD MP3 -&gt; Shoutcast streaming (part 2) [UPDATED Sept 15]</title>
		<link>http://kill-0.com/duplo/2008/08/25/mpd-mp3-shoutcast-streaming-part-2/</link>
		<comments>http://kill-0.com/duplo/2008/08/25/mpd-mp3-shoutcast-streaming-part-2/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 00:19:57 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[C]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[mp3]]></category>

		<category><![CDATA[mpd]]></category>

		<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/?p=17</guid>
		<description><![CDATA[Update: due to wide-spread changes in the MPD git repository, this patch no longer applies and builds correctly.  You can still play with the shout MP3 plugin by cloning my shiny-new git repository at: http://git.musicpd.org/encoded/mpd.git See the comments section below for information about configuration changes.  The plugin is currently on the roadmap for the 0.14.0 [...]]]></description>
			<content:encoded><![CDATA[<p><em><strong>Update:</strong> due to wide-spread changes in the MPD git repository, this patch no longer applies and builds correctly.  You can still play with the shout MP3 plugin by cloning my shiny-new git repository at: <a href="http://git.musicpd.org/encoded/mpd.git">http://git.musicpd.org/encoded/mpd.git</a> See the comments section below for information about configuration changes.  The plugin is currently on the roadmap for the 0.14.0 release, so keep your fingers crossed.</em></p>
<p>I&#8217;ve updated my patch so that it can be applied against the current <a href="http://git.musicpd.org/normalperson/mpd.git/">MPD git repository</a>.  Hopefully it will be rolled into <acronym title="Music Player Daemon: http://musicpd.org/">MPD</acronym> for the 0.14.0 release.  The patch has been improved to do better configuration-time checking for the lame library.  I also found a bug where I wasn&#8217;t setting the bit rate properly if constant bit rate was requeted.</p>
<p>I&#8217;m hoping to roll this out to <a href="http://mildred.xmtp.net/">Mildred</a> soon.</p>
<p>Here&#8217;s the link:  <a href="http://kill-0.com/patches/0001-Creation-of-shout_mp3-audio-output-plugin.-Basicall.patch">0001-Creation-of-shout_mp3-audio-output-plugin.-Basicall.patch</a><a href="http://kill-0.com/patches/0001-Adds-FLAC-md5sum.patch"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/08/25/mpd-mp3-shoutcast-streaming-part-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MPD MP3 -&gt; Shoutcast streaming</title>
		<link>http://kill-0.com/duplo/2008/08/23/mpd-mp3-shoutcast-streaming/</link>
		<comments>http://kill-0.com/duplo/2008/08/23/mpd-mp3-shoutcast-streaming/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:21:13 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[C]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[mp3]]></category>

		<category><![CDATA[mpd]]></category>

		<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/2008/08/23/mpd-mp3-shoutcast-streaming/</guid>
		<description><![CDATA[MPD is a great little project that collects, organizes, and plays your music files for you.  You can connect to MPD and listen to your music in a great number of ways.  You can even stream your music out as your own radio station (Mildred makes use of this functionality).
I&#8217;ve always thought it odd that [...]]]></description>
			<content:encoded><![CDATA[<p><acronym title="Music Player Daemon: http://musicpd.org">MPD</acronym> is a great little project that collects, organizes, and plays your music files for you.  You can connect to MPD and listen to your music in <a href="http://www.musicpd.org/clients.shtml">a great number of ways</a>.  You can even <a href="http://mpd.wikia.com/wiki/Configuration#Icecast">stream your music out</a> as your own radio station (<a href="http://mildred.xmtp.net/">Mildred</a> makes use of this functionality).</p>
<p>I&#8217;ve always thought it odd that MPD would stream in <a href="http://www.vorbis.com/">Ogg</a>, but not MP3.  Don&#8217;t get me wrong, I&#8217;m a big fan of open standards and all, but MP3 is just so dominant, that I was surprised MP3 streaming hadn&#8217;t been implemented.  Add to that <a href="http://www.xiph.org/quicktime/faq.html#faq_itunes_stream">the stupid inability of Apple&#8217;s iTunes to stream Ogg</a> and well, it motivated me.  I sat down and hacked together a MPD plugin that allows you to stream MP3 to your shoutcast server from MPD.</p>
<p>Source patches for the plugin are available here:  <a href="http://kill-0.com/patches/shout_mp3.patch">http://kill-0.com/patches/shout_mp3.patch</a></p>
<p>It&#8217;s rough around the edges, but it does work.  You can even play it in iTunes.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/08/23/mpd-mp3-shoutcast-streaming/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Voyeur: Growl Notifications for MPD</title>
		<link>http://kill-0.com/duplo/2008/08/23/voyeur-growl-notifications-for-mpd/</link>
		<comments>http://kill-0.com/duplo/2008/08/23/voyeur-growl-notifications-for-mpd/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:10:24 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[mpd]]></category>

		<category><![CDATA[music]]></category>

		<category><![CDATA[voyeur]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/2008/08/23/voyeur-growl-notifications-for-mpd/</guid>
		<description><![CDATA[Voyeur is a very small bit of ruby code that I&#8217;ve written to display updates to your MPD stream via Growl.
You can find it here:  http://kill-0.com/voyeur/
You start and stop it as you would a daemon, ie $ ./voyeur start and ./voyeur stop.  As an added bonus, you can send it a HUP signal, and [...]]]></description>
			<content:encoded><![CDATA[<p>Voyeur is a very small bit of ruby code that I&#8217;ve written to display updates to your MPD stream via Growl.</p>
<p>You can find it here:  <a href="http://kill-0.com/voyeur/" title="Voyeur">http://kill-0.com/voyeur/</a></p>
<p>You start and stop it as you would a daemon, ie <tt>$ ./voyeur start</tt> and <tt>./voyeur stop</tt>.  As an added bonus, you can send it a HUP signal, and it will immediately display the current track information or status.  Here&#8217;s a screen shot:</p>
<p><a href="http://kill-0.com/duplo/wp-content/uploads/2008/08/voyeur-screenshot.png" title="Voyeur: Screenshot"><img src="http://kill-0.com/duplo/wp-content/uploads/2008/08/voyeur-screenshot.thumbnail.png" alt="Voyeur: Screenshot" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/08/23/voyeur-growl-notifications-for-mpd/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rspec 1.1.4 and Helper spec woes</title>
		<link>http://kill-0.com/duplo/2008/08/06/rspec-114-and-helper-spec-woes/</link>
		<comments>http://kill-0.com/duplo/2008/08/06/rspec-114-and-helper-spec-woes/#comments</comments>
		<pubDate>Thu, 07 Aug 2008 04:11:57 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[mildred]]></category>

		<category><![CDATA[1.1.4]]></category>

		<category><![CDATA[helper]]></category>

		<category><![CDATA[rspec]]></category>

		<category><![CDATA[spec]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/2008/08/06/rspec-114-and-helper-spec-woes/</guid>
		<description><![CDATA[I was having all sorts of problems upgrading Mildred to Rails 2.1.  A lot of the errors I was seeing were like the following:
ArgumentError in 'TracksController downloading a track by admin should not be a redirection'
wrong number of arguments (0 for 1)
/Users/ewollesen/src/mildred/app/models/track.rb:52:in `title'
/Users/ewollesen/src/mildred/app/models/track.rb:52:in `filename'
/Users/ewollesen/src/mildred/app/controllers/tracks_controller.rb:49:in `download'
./spec/controllers/tracks_controller_spec.rb:82:
It took me a good while to figure out what was [...]]]></description>
			<content:encoded><![CDATA[<p>I was having all sorts of problems upgrading Mildred to Rails 2.1.  A lot of the errors I was seeing were like the following:</p>
<pre><code>ArgumentError in 'TracksController downloading a track by admin should not be a redirection'
wrong number of arguments (0 for 1)
/Users/ewollesen/src/mildred/app/models/track.rb:52:in `title'
/Users/ewollesen/src/mildred/app/models/track.rb:52:in `filename'
/Users/ewollesen/src/mildred/app/controllers/tracks_controller.rb:49:in `download'
./spec/controllers/tracks_controller_spec.rb:82:</code></pre>
<p>It took me a good while to figure out what was going on.  The error was strange because as far as I knew, <code>title</code> was a database attribute in the Album model, which was a descendant of ActiveRecord.  There shouldn&#8217;t have been any arguments required.  Indeed, firing up my debugger and running <code>track.album.read_attribute(:title)</code> returned the expected result of &#8220;Test Album 1&#8243;.  I was very puzzled.</p>
<p>I realized that my title method was being overridden, but by what?  I started feeding the title method random arguments in the hopes of learning something new.  It wasn&#8217;t long before I got lucky:</p>
<pre><code>(rdb:1) e track.album.title("x")
NoMethodError Exception: undefined method `content_tag' for #&lt;Album:0x3d5bbfc&gt;</code></pre>
<p>That tipped me off as to what was overriding my title method.  The <code>content_for</code> is part of a pattern I use to set a view&#8217;s title in the layout via a method called <code>title</code> in my <a href="http://www.xmtp.net/websvn/filedetails.php?repname=mildred&amp;path=%2Fmildred_rails%2Fbranches%2Frails-2.1%2Fapp%2Fhelpers%2Fapplication_helper.rb&amp;rev=552&amp;sc=0"><code>ApplicationHelper</code></a>.  This made me think of how in Rspec 1.1.4, a Helper module is no longer included by default.  I popped over to my <a href="http://www.xmtp.net/websvn/filedetails.php?repname=mildred&amp;path=%2Fmildred_rails%2Fbranches%2Frails-2.1%2Fspec%2Fhelpers%2Fapplication_helper_spec.rb&amp;rev=0&amp;sc=0"><code>application_helper_spec.rb</code></a> and found something similar to this:</p>
<pre><code>require File.dirname(__FILE__) + '/../spec_helper'

include ApplicationHelper

describe "ApplicationHelper" do</code></pre>
<p>This needed to be changed to:</p>
<pre><code>require File.dirname(__FILE__) + '/../spec_helper'

describe "ApplicationHelper" do

  include ApplicationHelper</code></pre>
<p>Then all was well.  Whew.  Just to be sure I didn&#8217;t run into this sort of thing again, I went ahead and made sure that all of my other Helper specs followed this paradigm.</p>
<p>This is the second time I&#8217;ve run into an issue where RSpec had overridden some seemingly random method in some seemingly random object.  I guess there&#8217;s a lot of magic in there that I don&#8217;t have my head wrapped around yet.  I just wish it were easier to spot!</p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/08/06/rspec-114-and-helper-spec-woes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>D&#038;D Dice Probabilities</title>
		<link>http://kill-0.com/duplo/2008/06/02/dd-dice-probabilities/</link>
		<comments>http://kill-0.com/duplo/2008/06/02/dd-dice-probabilities/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 04:35:21 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[D&amp;D]]></category>

		<category><![CDATA[dice]]></category>

		<category><![CDATA[probability]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/2008/06/02/dd-dice-probabilities/</guid>
		<description><![CDATA[I&#8217;m going to discuss some basic probabilities about D&#38;D dice rolling.  Yes, I&#8217;m that big of a geek.  At the same time, I am not a statistician, so it&#8217;s entirely possible I&#8217;ve screwed something up.
Rolling a single six-sided die (d6), we know that the probability of rolling any given value is 1 in [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to discuss some basic probabilities about D&amp;D dice rolling.  Yes, I&#8217;m that big of a geek.  At the same time, I am <em>not</em> a statistician, so it&#8217;s entirely possible I&#8217;ve screwed something up.</p>
<p>Rolling a single six-sided die (d6), we know that the probability of rolling any given value is 1 in 6.  This should not a be a surprise.  If it is, you might want to brush up on your <a href="http://mathworld.wolfram.com/Dice.html" target="_blank">dice knowledge</a>.  In the older days of D&amp;D we would typically roll 3 six-sided dice (3d6), and take their sum to use as one of our ability scores (eg strength, intelligence, charisma, etc).  In more recent editions of the game, a new method has emerged, generally known as <q>4d6 drop lowest</q>.  It&#8217;s just what it sounds like, you roll 4d6, remove the lowest of the rolls, and sum the remaining three to use for your ability score.  This can make it a little trickier to figure out what the average and standard deviation are.  Fortunately, it doesn&#8217;t make it so different that a little scripting can&#8217;t find the answers for us.</p>
<p>So how do we calculate these means and standard deviations?  Simple, we create a two dimensional array, and in that array, we place all the possible ways we could roll 4d6.  It basically looks like this:</p>
<pre>[ [ 1, 1, 1, 1 ],
[ 1, 1, 1, 2 ],
[ 1, 1, 1, 3 ],
…
[ 6, 6, 6, 4 ],
[ 6, 6, 6, 5 ],
[ 6, 6, 6, 6 ], ]</pre>
<p>Now, we sum each row, and find the mean of those sums, we&#8217;ll have found the average roll when rolling 4d6.  That&#8217;s close to what we want.  To simulate dropping the lowest, I simply find the lowest die roll in each row, and set its value to 0.  Then I repeat the process above, summing each row, and the average of those sums is now the average for 4d6 drop lowest.  If I take the standard deviation of those rolls, I&#8217;ll have the standard deviation of this method.  All this leads to the following:</p>
<table border="0" summary="Statistics for rolling 4d6 drop lowest">
<tbody>
<tr>
<th>Max</th>
<td>18</td>
</tr>
<tr>
<th>Min</th>
<td>3</td>
</tr>
<tr>
<th>Mean</th>
<td>12.2446</td>
</tr>
<tr>
<th>Std Dev</th>
<td>2.8468</td>
</tr>
</tbody>
</table>
<p>But what does it mean?  Simply put, if you roll 4d6 drop lowest, you are most likely to roll a 12.  Additionally, there is a ? 68% chance that you&#8217;ll roll within one standard deviation of the mean, or [9,15].  The chances that you&#8217;ll get any given roll are in the table below:</p>
<table border="0" summary="Probability of any given result when rolling 4d6 drop lowest.">
<tbody>
<tr>
<th>Roll</th>
<th>Probability</th>
<th>Frequency</th>
<th>? Odds</th>
</tr>
<tr>
<th>3</th>
<td>0.000772</td>
<td>1</td>
<td>1 in 1,295</td>
</tr>
<tr>
<th>4</th>
<td>0.003086</td>
<td>4</td>
<td>1 in 324</td>
</tr>
<tr>
<th>5</th>
<td>0.007716</td>
<td>10</td>
<td>1 in 130</td>
</tr>
<tr>
<th>6</th>
<td>0.016204</td>
<td>21</td>
<td>1 in 62</td>
</tr>
<tr>
<th>7</th>
<td>0.029321</td>
<td>38</td>
<td>1 in 34</td>
</tr>
<tr>
<th>8</th>
<td>0.047840</td>
<td>62</td>
<td>1 in 21</td>
</tr>
<tr>
<th>9</th>
<td>0.070216</td>
<td>91</td>
<td>1 in 14</td>
</tr>
<tr>
<th>10</th>
<td>0.094136</td>
<td>122</td>
<td>1 in 11</td>
</tr>
<tr>
<th>11</th>
<td>0.114198</td>
<td>148</td>
<td>1 in 9</td>
</tr>
<tr>
<th>12</th>
<td>0.128858</td>
<td>167</td>
<td>1 in 8</td>
</tr>
<tr>
<th>13</th>
<td>0.132716</td>
<td>172</td>
<td>1 in 8</td>
</tr>
<tr>
<th>14</th>
<td>0.123457</td>
<td>160</td>
<td>1 in 8</td>
</tr>
<tr>
<th>15</th>
<td>0.101080</td>
<td>131</td>
<td>1 in 10</td>
</tr>
<tr>
<th>16</th>
<td>0.072531</td>
<td>94</td>
<td>1 in 14</td>
</tr>
<tr>
<th>17</th>
<td>0.041667</td>
<td>54</td>
<td>1 in 24</td>
</tr>
<tr>
<th>18</th>
<td>0.016204</td>
<td>21</td>
<td>1 in 62</td>
</tr>
</tbody>
</table>
<p>Here&#8217;s a pretty picture for you:</p>
<p><a title="4d6 drop lowest" href="http://kill-0.com/duplo/wp-content/uploads/2008/06/4d6_drop_lowest.png"><img src="http://kill-0.com/duplo/wp-content/uploads/2008/06/4d6_drop_lowest.thumbnail.png" alt="4d6 drop lowest" /></a></p>
<p>You might notice that the mean is marked below the peak of the distribution.  I&#8217;m not entirely sure why that is, but I suspect it has to do with the facts that we&#8217;re dropping the lowest roll, combined with how the curve gets cut off at 18.  Dropping the lowest roll shifts the mean to a higher number, but because we can&#8217;t possibly go higher than 18, the right-side tail of the distribution gets cut off, causing the mean to be less than the peak of the distribution.</p>
<p>Lastly, here&#8217;s a little python script that can calculate these things for you.  It will also generate two gnuplot data files, one of which was used to generate the pretty picture above.  Yes, this code is quick and dirty, and certainly not production quality, but it gets the job done.</p>
<pre>#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

from numpy import *
import sys
import os
import random
import pprint

outcomes = []

# roll 4d6
for d1 in range(1, 7):
    for d2 in range(1, 7):
        for d3 in range(1, 7):
            for d4 in range(1, 7):
outcome = array([d1, d2, d3, d4])
outcomes.append(outcome)

outcomes = array(outcomes)
hist = {}

# drop the lowest, count the number of times a given sum is found
for x in range(len(outcomes)):
    outcomes[x][outcomes[x].argmin()] = 0
    if outcomes[x].sum() in hist:
        hist[outcomes[x].sum()] += 1
    else:
        hist[outcomes[x].sum()] = 1

rsum = outcomes.sum()
sums = outcomes.sum(axis=1)
mean = sums.mean()
sigma = sums.std()

counts = array(hist.values())
hist2 = hist.copy()

# determine the probability of each sum occurring
for key,value in hist2.items():
    hist2[key] = counts[key-3] / float(counts.sum())

f = open(&#8221;dice.data&#8221;, &#8220;w&#8221;)
for key in hist2.keys():
print &gt;&gt;f, &#8220;%d\t%0.12f&#8221; % (key, hist2[key])
f.close()

f = open(&#8221;dice2.data&#8221;, &#8220;w&#8221;)
for key,value in hist2.items():
    print &gt;&gt;f, &#8220;%d\t%f&#8221; % (key, value)
f.close()

pprint.pprint(hist.values())

args = {
    &#8220;mean&#8221;: mean,
    &#8220;sigma&#8221;: sigma,
    &#8220;-sigma&#8221;: mean - sigma,
    &#8220;+sigma&#8221;: mean + sigma,
    &#8220;++sigma&#8221;: mean + (2 * sigma),
    &#8220;&#8211;sigma&#8221;: mean - (2 * sigma),
    &#8220;+++sigma&#8221;: mean + (3 * sigma),
    &#8220;&#8212;sigma&#8221;: mean - (3 * sigma),
}
labels = {
    &#8220;+sigma_label&#8221;: mean + sigma - 0.1,
    &#8220;-sigma_label&#8221;: mean - sigma + 0.1,
    &#8220;++sigma_label&#8221;: mean + (2*sigma) - 0.1,
    &#8220;&#8211;sigma_label&#8221;: mean - (2*sigma) + 0.1,
    &#8220;+++sigma_label&#8221;: mean + (3*sigma) - 0.1,
    &#8220;&#8212;sigma_label&#8221;: mean - (3*sigma) + 0.1,
    &#8220;mean_label&#8221;: mean - 0.1,
}
args.update(labels)
gnuplot = &#8220;&#8221;"
set terminal png enhanced size 800,600 font &#8216;/Library/Fonts/Arial.ttf&#8217; 8
set output &#8220;dice.png&#8221;
set arrow from %(mean)f,0 to %(mean)f,0.14 nohead lc 1
set label &#8220;? (%(mean)0.2f)&#8221; at %(mean_label)f,0.05 right tc ls 1
set arrow from %(-sigma)f,0 to %(-sigma)f,0.14 nohead lc 2
set label &#8220;?? (%(-sigma)0.2f)&#8221; at %(-sigma_label)f,0.05 tc ls 2
set arrow from %(+sigma)f,0 to %(+sigma)f,0.14 nohead lc 2
set label &#8220;+? (%(+sigma)0.2f)&#8221; at %(+sigma_label)f,0.05 right tc ls 2

set arrow from %(&#8211;sigma)f,0 to %(&#8211;sigma)f,0.14 nohead lc 2
set label &#8220;?2? (%(&#8211;sigma)0.2f)&#8221; at %(&#8211;sigma_label)f,0.05 tc ls 2
set arrow from %(++sigma)f,0 to %(++sigma)f,0.14 nohead lc 2
set label &#8220;+2? (%(++sigma)0.2f)&#8221; at %(++sigma_label)f,0.05 right tc ls 2

set arrow from %(&#8212;sigma)f,0 to %(&#8212;sigma)f,0.14 nohead lc 3
set label &#8220;?3? (%(&#8212;sigma)0.2f)&#8221; at %(&#8212;sigma_label)f,0.05 tc ls 3
set arrow from %(+++sigma)f,0 to %(+++sigma)f,0.14 nohead lc 3
set label &#8220;+3? (%(+++sigma)0.2f)&#8221; at %(+++sigma_label)f,0.05 right tc ls 3

plot &#8216;dice.data&#8217; with lines smooth csplines title &#8216;4d6 drop lowest&#8217;
&#8220;&#8221;" % args

f = open(&#8221;dice.gnuplot&#8221;, &#8220;w&#8221;)
f.write(gnuplot)
f.close()

gnuplot = &#8220;&#8221;"
set terminal png enhanced size 800,600 font &#8216;/Library/Fonts/Arial.ttf&#8217; 8
set output &#8220;dice2.png&#8221;
set boxwidth 0.9 relative
set style data histograms
set style fill solid 1.0 border -1
set style data histogram
plot &#8216;dice2.data&#8217; using 2:xticlabels(1) title &#8216;4d6 drop lowest&#8217;
&#8220;&#8221;"

f = open(&#8221;dice2.gnuplot&#8221;, &#8220;w&#8221;)
f.write(gnuplot)
f.close()

print &#8220;mean: %f&#8221; % mean
print &#8220;sigma: %f&#8221; % sigma
print &#8220;1 sigma: %0.4f - %0.4f&#8221; % (mean - sigma, mean + sigma)
print &#8220;2 sigma: %0.4f - %0.4f&#8221; % (mean - 2*sigma, mean + 2*sigma)
print &#8220;3 sigma: %0.4f - %0.4f&#8221; % (mean - 3*sigma, mean + 3*sigma)

os.system(&#8221;gnuplot &#8216;dice.gnuplot&#8217;&#8221;)
os.system(&#8221;gnuplot &#8216;dice2.gnuplot&#8217;&#8221;)</pre>
<p>Download the <a title="4d6 Drop Lowest Python Script" href="http://kill-0.com/duplo/wp-content/uploads/2008/06/4d6_drop_lowest.py">4d6 Drop Lowest Python Script</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/06/02/dd-dice-probabilities/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JavaScript Conditionals from ERb</title>
		<link>http://kill-0.com/duplo/2008/05/01/javascript-conditionals-from-erb/</link>
		<comments>http://kill-0.com/duplo/2008/05/01/javascript-conditionals-from-erb/#comments</comments>
		<pubDate>Fri, 02 May 2008 04:57:45 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/2008/05/01/javascript-conditionals-from-erb/</guid>
		<description><![CDATA[Rails&#8217;s JavaScript generator provides some great functionality.  But unfortunately, one of the things it can&#8217;t do for you, is generate JavaScript conditionally, based on the page&#8217;s content.  The reason is simply that the page&#8217;s content doesn&#8217;t exist at the time the conditional in your code was executed.  I wanted to do something [...]]]></description>
			<content:encoded><![CDATA[<p>Rails&#8217;s <a href="http://api.rubyonrails.com/classes/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/GeneratorMethods.html">JavaScript generator</a> provides some great functionality.  But unfortunately, one of the things it can&#8217;t do for you, is generate JavaScript conditionally, based on the page&#8217;s content.  The reason is simply that the page&#8217;s content doesn&#8217;t exist at the time the conditional in your code was executed.  I wanted to do something like the following:</p>
<pre><code>if page["album_1_rating"]
  page["album_1_rating"].visual_effect(:highlight)
end</code></pre>
<p>As I said, at the time the <tt>if</tt> statement above is executed, there is no HTML file yet, so the generator can&#8217;t possibly know if the element referenced will exist in the file or not.  In fact, <tt>page["album_1_rating"]</tt> is a <tt>ActionView::Helpers::JavaScriptElementProxy</tt> object, which is not false, so the <tt>if</tt> statement will always execute.  This wasn&#8217;t what I wanted.  So I came up with something that would work. I added the following method to <tt>lib/prototype_helper_hacks.rb</tt>, then required it in <tt>config/environment.rb</tt>.</p>
<pre><code>def if_element(id, &amp;block)
  self &lt;&lt; "if ($(\"#{id}\")) {"
  block.call(self[id])
  self &lt;&lt; &#8220;}&#8221;
end</code></pre>
<p>This lets me do things like this in my views:</p>
<pre><code>page.if_element("album_1_rating") do |element|
  element.visual_effect(:highlight)
end</code></pre>
<p>That made me happy.</p>
<p>In thinking more about the situation, I&#8217;m not sure this is really such a great method.  It works, but I can&#8217;t help but feel there&#8217;s some better way of going about this.  I could simply use the page append method, to do something like:</p>
<pre><code>page &lt;&lt; "if ($(id)) {"
  page["album_1_rating"].visual_effect(:highlight)
page &lt;&lt; &#8220;}&#8221;</code></pre>
<p>But at least if nothing else, my <tt>if_element</tt> method makes this a lot cleaner looking.  So really this is just some syntactic sugar, and I wish at least I could make it more of a general purpose <tt>if</tt> statement, but since I don&#8217;t need that sort of funcationality at this point, <acronym title="You're not going to need it.">YAGNI</acronym> tells me to leave that hurdle for another day.</p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2008/05/01/javascript-conditionals-from-erb/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Another Example of How Append Is Better Than + in Ruby</title>
		<link>http://kill-0.com/duplo/2007/12/20/another-example-of-how-append-is-better-than-in-ruby/</link>
		<comments>http://kill-0.com/duplo/2007/12/20/another-example-of-how-append-is-better-than-in-ruby/#comments</comments>
		<pubDate>Thu, 20 Dec 2007 17:36:24 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/2007/12/20/another-example-of-how-append-is-better-than-in-ruby/</guid>
		<description><![CDATA[The short of it, as you can find with a quick Google search1, is that &#60;&#60; is superior to + (or +=) in Ruby.  This is because &#60;&#60; appends to an existing object, while += creates a new object.  Creating a new object in Ruby is not nearly as fast as appending to [...]]]></description>
			<content:encoded><![CDATA[<p>The short of it, as you can find with a quick Google search<sup>1</sup>, is that <tt>&lt;&lt;</tt> is superior to <tt>+</tt> (or <tt>+=</tt>) in Ruby.  This is because <tt>&lt;&lt;</tt> appends to an existing object, while <tt>+=</tt> creates a new object.  Creating a new object in Ruby is not nearly as fast as appending to an existing object.  This should not be surprising to anyone that has written the two operations in a lower level language like C or C++.  Now, on with the story.</p>
<p>At work, I&#8217;m writing a parser for less-than-well-known file format.  In the lexical analysis stage, I was adding arrays together.  Something along the lines of:</p>
<p><code>@tokens += token</code></p>
<p>Where <tt>@tokens</tt> is an array, and token is an array of the form <tt>[:symbol, character]</tt><sup>2</sup>.   At any rate, when I tried to parse a very large file, it took approximately 180 seconds.  My smaller tests had all been very fast.  Looking at the code, the <tt>+=</tt> was the first thing that came to mind.   I checked it with the benchmarker and found that a particular loop full of <tt>+=</tt>&#8217;s was particularly offensive.  A quick refactor from <tt>+=</tt> to <tt>&lt;&lt;</tt> later, and parsing the same file now took just under 9 seconds.  That&#8217;s down from 180 seconds.  Nice.</p>
<p>So what have I learned here?  Well, I&#8217;m not sorry that I used <tt>+=</tt>.  It worked just fine, and anyone that knows me knows I recite &#8220;premature optimization is the devil&#8221; at least 10 times a day.  Now that I&#8217;m in the final test phases of the parser, I can take the time to optimize things like this.  However this also reinforced the adage of &#8220;everything is fast when <em style="font-family: serif">n</em> is small.&#8221;  A good reminder to test with larger datasets before claiming any algorithm is complete.</p>
<ol class="footnotes"><li id="footnote_0_8" class="footnote">Like <a href="http://google.com/search?q=copy+versus+append">this</a> one.</li><li id="footnote_1_8" class="footnote">If you&#8217;re paying attention you&#8217;ll recognize this format as that used by <a href="http://i.loveruby.net/en/projects/racc/" title="RACC">racc</a>.</li></ol>]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2007/12/20/another-example-of-how-append-is-better-than-in-ruby/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using mysql with Ruby on Rails a No-No?</title>
		<link>http://kill-0.com/duplo/2007/10/20/using-mysql-with-ruby-on-rails-a-no-no/</link>
		<comments>http://kill-0.com/duplo/2007/10/20/using-mysql-with-ruby-on-rails-a-no-no/#comments</comments>
		<pubDate>Sat, 20 Oct 2007 22:38:23 +0000</pubDate>
		<dc:creator>ericw</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://kill-0.com/duplo/2007/10/20/using-mysql-with-ruby-on-rails-a-no-no/</guid>
		<description><![CDATA[No, I&#8217;m not going to say that using MySQL with Ruby on Rails is a bad thing.  It works fine.  But I do think that using the mysql command line tool to modify your Rails databases is a no-no.  The reason is simple, Rails does a lot of work to abstract database [...]]]></description>
			<content:encoded><![CDATA[<p>No, I&#8217;m not going to say that using MySQL with Ruby on Rails is a bad thing.  It works fine.  But I do think that using the <tt>mysql</tt> command line tool to modify your Rails databases is a no-no.  The reason is simple, Rails does a lot of work to abstract database details away, so that programmers don&#8217;t have to know anything about them.  We should respect and embrace that abstraction, not step around it.</p>
<p>So if you&#8217;re not supposed to use <tt>mysql</tt> from the command line, how do you make changes to your models from outside of your application?  The answer is <tt>script/console</tt>.  Using <tt>console</tt> is even better than using <tt>mysql</tt>, because it a) uses Ruby, a language we already know and love, and b) exercises the same bug-free, well tested code that your Rails application does.  Of special use here are ActiveRecord&#8217;s validations, associations, and before_* and after_* callbacks.</p>
<p>As a brief example, let&#8217;s say you&#8217;re writing the ubiquitous blog.  You need to delete a user on the blog, but you haven&#8217;t implemeted the web framework yet.  You open up your trusty <tt>mysql</tt> command line client and do something like this:</p>
<p><code>mysql&gt; DELETE FROM users WHERE username = 'foobar';<br />
Query OK, 1 row affected (0.08 sec)<br />
</code></p>
<p>And you think to yourself, &#8220;Job well done&#8221; as you wipe your hands and pat yourself on the back.  But many of you are probably asking, &#8220;What happened to all of foobar&#8217;s posts?&#8221;  They&#8217;re still there.  I guess you have to delete them too:</p>
<p><code>mysql&gt; DELETE FROM posts WHERE user_id = 666;<br />
Query OK, 1 row affected (0.11 sec)<br />
</code></p>
<p>It&#8217;s a good thing you happened to remember foobar&#8217;s user_id huh?  So that should do it&#8230;  right?  But what about foobar&#8217;s user image?  Now you have to go into the filesystem and delete his user image.</p>
<p><code>$ rm RAILS_ROOT/public/images/users/foobar.jpg<br />
</code></p>
<p>Whew.  There, that&#8217;s all of it.  Finally.   Or is it?  What if your colleague added the concept of &#8220;friendships&#8221; between users, and now you have a bunch of orphaned table rows?  If this doesn&#8217;t seem error prone (and tedious!) already, then you&#8217;re a lot braver than I am.  Especially since if you hadn&#8217;t tried so hard to work around Rails&#8217;s database abstraction, all you would have had to do is:</p>
<p><code>&gt;&gt; User.find_by_username("foobar").destroy<br />
</code></p>
<p>That&#8217;s it.  One simple line.  Your well-designed models will take care of the rest.  In case you&#8217;re new to Rails, and wondering just what this magical User model might look like in Rails, here it is:</p>
<pre>class User &lt; ActiveRecord::Base
  after_destroy :delete_user_image
  has_many :posts, :dependent =&gt; :destroy

  private

  def delete_user_image
    FileUtils.rm(RAILS_ROOT + "/public/images/users/#{username}.jpg")
  end
end</pre>
<p>Yes, if you&#8217;re a true wiz, you could write all of that into your database, but you&#8217;re trying to write a Ruby on Rails application, remember? Besides, what happens when your CTO decides that your application will now use DatabaseX, since it&#8217;s the hottest thing since the sun?  If that frightening occurance isn&#8217;t enough, consider that DHH, the creator of Rails, frowns on <a href="http://web.archive.org/web/20060418215514/http://www.loudthinking.com/arc/000516.html">such database trickery</a>.</p>
<p>I guess the real point of what I&#8217;m trying to say is, Rails uses the database so you don&#8217;t have to.  Try to pretend there is no database, and use <tt>script/console</tt> instead. You&#8217;ll save yourself a lot of grief in the end.</p>
]]></content:encoded>
			<wfw:commentRss>http://kill-0.com/duplo/2007/10/20/using-mysql-with-ruby-on-rails-a-no-no/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
