<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NelsonWells.net</title>
	<atom:link href="http://nelsonwells.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://nelsonwells.net</link>
	<description>Programming and other distractions</description>
	<lastBuildDate>Mon, 14 May 2012 02:33:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Big Data and how Isaac Asimov will have successfully predicted psychohistory</title>
		<link>http://nelsonwells.net/2012/05/big-data-and-how-isaac-asimov-will-have-successfully-predicted-psycohistory/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=big-data-and-how-isaac-asimov-will-have-successfully-predicted-psycohistory</link>
		<comments>http://nelsonwells.net/2012/05/big-data-and-how-isaac-asimov-will-have-successfully-predicted-psycohistory/#comments</comments>
		<pubDate>Mon, 14 May 2012 02:21:51 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Observation]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=186</guid>
		<description><![CDATA[A couple of weeks ago, I had the opportunity to attend MarkLogic World 2012.  The overall theme of the conference was converting Big Data into Big Ideas.  Big Data is a paradigm shift for many in the IT industry; briefly, &#8230;<p class="read-more"><a href="http://nelsonwells.net/2012/05/big-data-and-how-isaac-asimov-will-have-successfully-predicted-psycohistory/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago, I had the opportunity to attend <a href="http://marklogicworld.com">MarkLogic World 2012</a>.  The overall theme of the conference was converting Big Data into Big Ideas.  Big Data is a paradigm shift for many in the IT industry; briefly, Big Data saves everything, whether it&#8217;s usefulness is obvious or not, in hopes that decisions can be made on that data.  In theory, the traditional data model would be unable to make informed decisions because the data set would not be large enough accurately describe super-complex issues.</p>
<p>Psychohistory, then, as defined by Isaac Asimov in his novel <em>Foundation</em>, goes something like this:</p>
<blockquote><p>Branch of mathematics which deals with the reactions of human conglomerates to fixed social and economic stimuli; implicit in all these definitions is the assumption that<strong> the human conglomerate being dealt with is sufficiently large for valid statistical treatment.</strong></p></blockquote>
<p><span id="more-186"></span></p>
<p>In Asimov&#8217;s novels, psychohistory is used to predict the future on a large scale.  It cannot predict an assassination of a leader or the popularity of a celebrity.  These things are statistical anomalies.  Instead, psychohistory predicts the fate of a society, the social and economic trends of nations, that nation&#8217;s success or failure.</p>
<p>For now, though, predicting the future still falls firmly in the hands of frauds and science fiction authors.  However, given the Big Data paradigm shift, I&#8217;m not convinced it has to stay there.  Asimov has already predicted the miniaturization of consumer electronics, <a href="http://www.pbs.org/moyers/journal/blog/2008/03/bill_moyers_rewind_isaac_asimo_1.html">the modern internet as we know it</a>, and <a href="http://www.youtube.com/watch?v=cFVlzUAZkHY">humanoid robots</a> (which I believe someday will move beyond the <a href="http://en.wikipedia.org/wiki/Uncanny_valley">uncanny valley</a>).  It isn&#8217;t hard to imagine integrating many years worth of behavior and census data with historical data and seeing patterns emerge and from there extrapolating, accurately, what is to come.</p>
<p>Psychohistory may be a pipe dream, but Asimov was a visionary and the future is a very exciting place <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2012/05/big-data-and-how-isaac-asimov-will-have-successfully-predicted-psycohistory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Words With Friends bug</title>
		<link>http://nelsonwells.net/2012/04/words-with-friends-bug/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=words-with-friends-bug</link>
		<comments>http://nelsonwells.net/2012/04/words-with-friends-bug/#comments</comments>
		<pubDate>Mon, 30 Apr 2012 05:01:26 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Distraction]]></category>
		<category><![CDATA[image]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=174</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<div id="attachment_178" class="wp-caption alignnone" style="width: 538px"><a href="http://nelsonwells.net/wp-content/uploads/2012/04/words_with_friends_bug.jpg"><img class="size-full wp-image-178" title="words_with_friends_bug" src="http://nelsonwells.net/wp-content/uploads/2012/04/words_with_friends_bug.jpg" alt="TheDailyWTF would be proud" width="528" height="640" /></a><p class="wp-caption-text">Is an empty string really a misspelled word?</p></div>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2012/04/words-with-friends-bug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convert an integer to a sequence of digits in Xquery</title>
		<link>http://nelsonwells.net/2012/03/convert-an-integer-to-a-sequence-of-digits-in-xquery/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=convert-an-integer-to-a-sequence-of-digits-in-xquery</link>
		<comments>http://nelsonwells.net/2012/03/convert-an-integer-to-a-sequence-of-digits-in-xquery/#comments</comments>
		<pubDate>Sun, 25 Mar 2012 06:57:36 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[MarkLogic]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[functional programming]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=167</guid>
		<description><![CDATA[I am new to the functional programming paradigm and Xquery. As part of a larger exercise, I wanted to sum the digits of an integer.  The first part of that problem is to solve the smaller problem: convert an integer &#8230;<p class="read-more"><a href="http://nelsonwells.net/2012/03/convert-an-integer-to-a-sequence-of-digits-in-xquery/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>I am new to the <a href="http://en.wikipedia.org/wiki/Functional_programming">functional programming</a> paradigm and Xquery. As part of a larger exercise, I wanted to sum the digits of an integer.  The first part of that problem is to solve the smaller problem: convert an integer to a sequence of integers that I can then pass to fn:sum as a parameter.</p>
<pre>(: I've declared the function in the nwnu namespace for testing purposes :&#41;
declare function nwnu:number-to-seq($num as xs:integer)
as xs:integer* {
  if($num gt 9) then
    (
      nwnu:number-to-seq(xs:integer(math:floor($num div 10))),
      xs:integer(math:floor($num mod 10))
    )
  else
    $num
};</pre>
<p><span id="more-167"></span>We&#8217;ll employ a recursive strategy to build our sequence.  First, we&#8217;ll check whether or not the number is greater than 9.  If the number is already a single digit, then we&#8217;ll just return it into the sequence since that is ultimately what we are adding to the sequence anyway.</p>
<p>Otherwise, we&#8217;ll add the the remainder of dividing the number by 10 with the modulus operator; this will isolate the right-most digit in the integer.  We&#8217;ll then recursively call our function with the rounded down result of dividing the input with 10.  So, for the initial input 1250, we will recursively call the function on:</p>
<pre>1250 -&gt; 125 -&gt; 12 -&gt; 1</pre>
<h3>Testing the function</h3>
<p>I am using Xquery with the MarkLogic engine.  If you have a properly configured AppServer, you can test the function with the following script.</p>
<pre>xquery version "1.0-ml";

import module namespace nwnu = "http://nelsonwells.net/xquery/number-utils"
at "/lib/number-utils.xqy";

let $seq := (13857, 1847471, 11183, 44819)
let $out := for $i in $seq
  return
    &lt;item&gt;
      &lt;input&gt;{$i}&lt;/input&gt;
      &lt;output&gt;{nwnu:number-to-seq($i)}&lt;/output&gt;
    &lt;/item&gt;

return &lt;items&gt;{$out}&lt;/items&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2012/03/convert-an-integer-to-a-sequence-of-digits-in-xquery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pair Programming</title>
		<link>http://nelsonwells.net/2012/03/pair-programming/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pair-programming</link>
		<comments>http://nelsonwells.net/2012/03/pair-programming/#comments</comments>
		<pubDate>Tue, 20 Mar 2012 23:27:42 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Distraction]]></category>
		<category><![CDATA[image]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=162</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<div id="attachment_164" class="wp-caption alignnone" style="width: 630px"><a href="http://nelsonwells.net/wp-content/uploads/2012/03/pair_programming.jpg"><img class="size-full wp-image-164" title="pair_programming" src="http://nelsonwells.net/wp-content/uploads/2012/03/pair_programming.jpg" alt="Pair Programming " width="620" height="465" /></a><p class="wp-caption-text">Nothing like cracking the whip</p></div>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2012/03/pair-programming/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JSON.stringify with mapped variables</title>
		<link>http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=json-stringify-with-mapped-variables</link>
		<comments>http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 05:08:08 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Mirth Connect]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=153</guid>
		<description><![CDATA[There are times when I want to create a data structure in Mirth, and output the contents of that data structure while debugging the code.  Luckily, JSON.stringify() is available not only in modern browsers but also in Mirth. var o &#8230;<p class="read-more"><a href="http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>There are times when I want to create a data structure in Mirth, and output the contents of that data structure while debugging the code.  Luckily, JSON.stringify() is available not only in modern browsers but also in Mirth.</p>
<pre>var o = {
  mrn: '8675309',
  labs: [
    'blood bank',
    'microbiology',
    'toxicology'
  ]
};

console.log(JSON.stringify(o, null, '\t'));</pre>
<p>However, there are any types of Mirth mapped variables, the JSON.stringify() method blows up on itself with a message similar to</p>
<pre>DETAILS:    Java class "[B" has no public instance field or method named "toJSON".</pre>
<p>This is how we fix it.</p>
<p><span id="more-153"></span></p>
<p>Consider the following code.  Assume that a variable has been mapped to mrn using Mirth's mapper transformer or a call to channelMap.put().  This code explodes with the aforementioned error.</p>
<pre>var o = {
  mrn: $('mrn'),
  labs: [
    'blood bank',
    'microbiology',
    'toxicology'
  ]
};</pre>
<p>Oddly, if we call logger.error($(&#8216;mrn&#8217;)), the mapped variable shows up correctly.  Our assumption is that $(&#8216;mrn&#8217;) would return a string if the mapped variable was in fact a string (as opposed to a javascript object, for example).  However, if we then call logger.error(typeof $(&#8216;mrn&#8217;)), we get &#8220;object.&#8221;  This should be our first clue that not all is what it seems.</p>
<p>Since I am not a Java programmer, I searched the internet trying to find what &#8220;[B" represents.  I've found that [B is some kind of a byte array in Java, and thus Mirth or maybe even Rhino implements a mapped variable as a byte array.  When JSON.stringify() is called on our data structure, toJSON() is called on each individual element in the structure... since the java byte array [B does not implement toJSON(), an exception is thrown.</p>
<p>So, our goal is to convert the [B object into a javascript string since a javascript string does implement the toJSON() method.  My original instinct was to simply called toString() on the mapped variable, but that failed similarly.</p>
<p>I eventually found that explicitly constructing a javascript string with the new keyword would get the job done.  This is the working code for printing a data structure with a mapped variable.</p>
<pre>var o = {
  mrn: new String($('mrn')),
  labs: [
    'blood bank',
    'microbiology',
    'toxicology'
  ]
};

logger.error(JSON.stringify(o, null, &#8216;\t&#8217;));</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introduction to web scraping with Node.js</title>
		<link>http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introduction-to-web-scraping-with-node-js</link>
		<comments>http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 04:23:02 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=129</guid>
		<description><![CDATA[The internet has a wealth of freely available information in difficult to consume formats.  For example, ClicheSite has lists of cliches, euphemisms, and other phrases that are just perfect for a hangman or Wheel of Fortune game.  Coincidentally, I wanted &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>The internet has a wealth of freely available information in difficult to consume formats.  For example, <a href="http://www.clichesite.com">ClicheSite</a> has lists of cliches, euphemisms, and other phrases that are just <em>perfect</em> for a hangman or Wheel of Fortune game.  Coincidentally, I wanted to write such a game to learn some new technologies, so I wrote a short, simple Node.js script to scrape some pages for those phrases.  In this tutorial, I&#8217;ll discuss how to make an HTTP request and get a page&#8217;s HTML, how to parse the HTML for specific information, and why you would and would not want to do this in the first place.<br />
<span id="more-129"></span></p>
<h3>Identifying Necessary Information</h3>
<p>ClicheSite obviously does not have all of it&#8217;s cliches listed on the home page.  It is technically feasible to begin at the homepage and follow links until we find something useful, but sometimes it makes more sense to take a manual step or two.  In this case, I identified alphabetic listings of phrases; each letter in the alphabet has its own page.  For example, http://clichesite.com/alpha_list.asp?which=lett+1 is a list of all phrases beginning with the letter A and http://clichesite.com/alpha_list.asp?which=lett+26 is a list of all phrases beginning with the letter Z.  So, it is clear that we can open and parse 26 pages to grab our phrases.</p>
<p>Next, we need to look at the pages&#8217; HTML source and identify a way to grab the data we want.  I used Firebug to look at the HTML, but you can also just look at the source directly with your favorite browser.  In Firefox, for example, you can right click anywhere on the page and hit &#8220;View page source.&#8221;  In any case, here is a portion of the HTML we&#8217;re concerned with.</p>
<pre> &lt;tr&gt;
   &lt;td valign="top" bgcolor="#FFFFCC"&gt;&amp;nbsp;&lt;/td&gt;
   &lt;td valign="top" bgcolor="#FFFFCC"&gt;
     &lt;span&gt; &lt;a href="content.asp?which=tip+1332"&gt;Acorn doesn't fall far from the tree, The&lt;/a&gt;&lt;/span&gt;
   &lt;/td&gt;
   &lt;td valign="top" bgcolor="#FFFFCC"&gt;                      
     &lt;span&gt; United States&lt;/span&gt;&lt;/td&gt;
 &lt;/tr&gt;

&lt;tr&gt;
  &lt;td valign="top" bgcolor="#FFFFCC"&gt;&amp;nbsp;&lt;/td&gt;
  &lt;td valign="top" bgcolor="#FFFFEE"&gt;  
    &lt;span&gt; &lt;a href="content.asp?which=tip+65"&gt;Actions speak louder than words&lt;/a&gt;&lt;/span&gt;
  &lt;/td&gt;                         
  &lt;td valign="top" bgcolor="#FFFFEE"&gt;         
  &lt;span&gt; United States&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;</pre>
<p>Let&#8217;s examine what we have here.  The HTML shows us that we have two rows with 3 columns.  We see that the two phrases are in the second column wrapped in a span and anchored (linked).  One possible action we could take is to write an HTML parser or use a 3rd party library to parse the HTML and then drill down to that HTML node.  However, for this particular case, that solution is a shovel when all you really need is a spoon.  Instead, we&#8217;ll use a regular expression to grab the phrases&#8230; but how?</p>
<p>Notice that each phrase is surrounded by an anchor tag, and inside that anchor tag is the word &#8220;tip&#8221;.  That will be the basis for our regular expression.  The content between the anchor tag with &#8220;tip&#8221; in the href attribute will be our phrase.  We&#8217;ll see that regular expression in the next section.</p>
<h3>The Code</h3>
<p>Since the code is so short, I&#8217;ll let you look over it and familiarize yourself with it before I explain it.</p>
<pre>var http = require('http');

var options;
var regex = /&lt;a.*tip.*&gt;(.*)&lt;\/a&gt;/g;

for(var i = 1; i &lt;= 26; i++) {

  options = {
    host: 'clichesite.com',
    path: '/alpha_list.asp?which=lett+' + i
  };

  http.get(options, function(res) {

    // accessible to 'data' and 'end' events
    var data = '';

    res.on('data', function(chunk) {
      data += chunk.toString();
    })
    .on('end', function() {
      while((match = regex.exec(data))) {
        console.log(match[1]);
      }
    });
  });

}</pre>
<p>First, we load the HTTP module.  We&#8217;ll use this to make HTTP requests to ClicheSite.  Then, we&#8217;ll define an options variable.  This is used as a parameter in the HTTP request and identifies the host and path (effectively, the URL) to hit.  Finally, we define a regex literal to identify the phrases.  Let&#8217;s break it apart piecewise.</p>
<pre>&lt;a   - <em>less than followed by the letter a</em>
.*   - <em>followed by any character any number of times</em>
tip  - <em>followed by the letters t, i, p</em>
.*   - <em>followed by any character any number of times</em>
&gt;    - <em>followed by a greater than</em>
(.*) - <em>followed by any character any number of times, and capture it</em>
&lt;    - <em>followed by a less than</em>
\/a  - <em>followed by a forward slash and the letter a</em>
&gt;    - <em>followed, finally, by greater than</em></pre>
<p>We&#8217;ll match it globally.  Later, we&#8217;ll loop through the result of the regular expression and grab the captured phrase.</p>
<p>Now, since we&#8217;ve previously identified that we need to scrape pages where lett+ a number 1 through 26 appears in the URL, we&#8217;ll loop through that range.  We&#8217;ll populate that options variable we created earlier with an object with two properties, host and path.  The host is the domain we wish to hit with our HTTP request, and the path is basically everything past that point in the URL.  Notice that we&#8217;re appending our loop index to the end of the path.  That is how we&#8217;ll hit pages A through Z.</p>
<p>Now, we&#8217;ll make an HTTP request.  All we have to do is call the get method of the HTTP object. We&#8217;ll define a callback function with an HTTP result object as a parameter&#8230; we&#8217;ll register events on this res object to do the actual scraping.  In the .get callback, we define an empty string called data.  This will eventually hold the full HTML content of the page.</p>
<p>Next, we register two events on the res object.  The first event, &#8220;data&#8221;, is fired when data is received.  When that happens, we&#8217;ll just append that data to the data string we defined.  The next event, &#8220;end&#8221; is fired when the HTTP request has finished.  When that happens, we will have the full HTML document.  This is where we do the work.</p>
<p>In the callback to this event, we loop through the results of our regular expression with the following construct:</p>
<pre>while((match = regex.exec(data))) {</pre>
<p>The regular expression exec will eventually evaluate to null, a falsey value, and the loop will end.  In the body of the loop, we can access the phrase with match[1].  Match[0], of course, contains the whole matched expression; we just want the capturing group.  In this example, I simply print the phrase to the screen&#8230; you&#8217;ll likely want to do more to the data than that, though.</p>
<h3>Pitfalls</h3>
<p>One thing you&#8217;ll notice about this solution is that the results are not in alphabetical order even though we iterate alphabetically from A to Z.  This is because of Node.js&#8217; event-driven, asynchronous nature.  In the body of the most broad loop, we make an HTTP request.  However, that request will most likely not finish before the we hit the next iteration of the loop.  Processing seed is much faster than network latency, after all.  In fact, when I was testing the script, I was often making 5-10 HTTP requests before the first one returned!  For this simple example, if you wanted a sorted list you could run the script and pipe to sort</p>
<pre>node index.js | sort</pre>
<p>More likely, you&#8217;ll want to store the results in a data structure and sort it or in a database so it can be sorted later.  This depends on context, of course.</p>
<p>Ironically, you also need to be wary of scraping pages heavy with Javascript.  If the contents of the page are dynamic, you may not have access to the data you actually want to get!</p>
<h3>Final Thoughts</h3>
<p>Why scrape web pages?  If you are feeling black hat, it is relatively simple to scrape for email addresses, phone numbers, and addresses.  In the real world, you may want to scrape your own web applications to ensure data validity and correct formatting of data.</p>
<p>In any case, please be nice!  Don&#8217;t break a website&#8217;s terms of use, and most certainly do not blame it on me! <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Happy coding</p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Swap object keys and values in Javascript</title>
		<link>http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=swap-object-key-and-values-in-javascript</link>
		<comments>http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 01:53:11 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=125</guid>
		<description><![CDATA[There are times when I would like to do work with the values in a Javascript object used as a hash map.  For example, sometimes I&#8217;d like to iterate over the values and perform an action on them, or perhaps &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>There are times when I would like to do work with the values in a Javascript object used as a hash map.  For example, sometimes I&#8217;d like to iterate over the values and perform an action on them, or perhaps check that a value exists in the hash map.  In this post, I&#8217;ll write a function that inverts the keys and values in a hash map, give a couple of examples in regards to how and why you&#8217;d want to do that, and explain the short-comings of the approach.</p>
<p><span id="more-125"></span></p>
<h3>The Invert Function</h3>
<pre>var invert = function (obj) {

  var new_obj = {};

  for (var prop in obj) {
    if(obj.hasOwnProperty(prop)) {
      new_obj[obj[prop]] = prop;
    }
  }

  return new_obj;
};</pre>
<p>The function itself is fairly simple.  We&#8217;ll pass an object as a parameter; this is the object whose keys and values we&#8217;ll invert.  We then create a new empty object; this is the object that we will return with the inverted keys and values.  We do not operate on the object that we pass as a parameter because we do not want to change the original object.</p>
<p>First, we&#8217;ll loop through the properties of obj.  We&#8217;ll use hasOwnProperty to verify that the keys we invert were defined on the object itself and not up the prototype chain.  In the loop, we&#8217;ll create a new key from the value of the key in the original object.  We&#8217;ll assign the value of that key the property we&#8217;re currently looking at in our iteration.  That&#8217;s all there is to inverting the keys and values!</p>
<p>Of course, we&#8217;ll return the newly generated object.</p>
<h3>Use Cases</h3>
<p>Okay, so we can invert k, v pairs.  What can we do with that, though?  How about iterating over them and performing some kind of action on it?</p>
<pre>var obj = {
  firstname : "nelson",
  middlename : "dane",
  lastname: "wells",
};

var name = '';

for(var value in invert(obj)) {
  name += value + ' ';
}

console.log(name.trim());</pre>
<p>Maybe we want to know if a value exists in the hash map?</p>
<pre>var obj = {
  firstname : "nelson",
  middlename : "dane",
  lastname: "wells",
};

if(invert(obj)['dane']) {
  //value exists in the hash
  console.log("Value exists");
} else {
  console.log("Value does not exist");
}

if(invert(obj)['terry']) {
  console.log("Value exists");
} else {
  console.log("Value does not exist");
};</pre>
<p>Of course, there&#8217;s nothing preventing you from inverting the keys, saving the inversion in a var, and doing something with it later.  In fact, you may want to do that&#8230;</p>
<h3>Shortcomings</h3>
<p>There are some obvious shortcomings with this function.  First, every time we call it, we&#8217;re iterating over the object&#8217;s properties.  Of course, we&#8217;re not going to want to do this in a loop because of performance implications.  Instead, we would want to call the function once and assign the result to a variable, and operate on <em>that</em> object.</p>
<p>Another shortcoming is the hash map must have only one to one relationships.  If a value exists for two keys, when the object is inverted, we&#8217;ll lose a key in the process.  It should be trivial to add exception handling to the function or some other mechanism to handle this deficiency gracefully, so if anyone is interested in that and can&#8217;t do it themselves, I&#8217;d be happy to help.</p>
<p>We&#8217;ll also prefer non-nested objects.  An array, another object, or a function may not make a great key <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introduction to memoization with Javascript</title>
		<link>http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introduction-to-memoization-with-javascript</link>
		<comments>http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 21:03:45 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Observation]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=112</guid>
		<description><![CDATA[Memoization is a function optimization technique used to avoid remaking calculations in subsequent function calls.  The classic example, which we&#8217;ll demonstrate here, is the factorial function.  5! = 5 * 4 * 3 * 2 * 1&#8230; factorials are recursive &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Memoization is a function optimization technique used to avoid remaking calculations in subsequent function calls.  The classic example, which we&#8217;ll demonstrate here, is the factorial function.  5! = 5 * 4 * 3 * 2 * 1&#8230; factorials are recursive in nature if we give it some thought.  5! = 5 * 4! and 4! = 4 * 3! and so on.  By recognizing this pattern, we can also recognize that if we calculate 5! and save the results, then we should not have to recalculate it when we do 7!.  Instead of calculating 7! by 7 * 6 * 5 * 4 * 3 * 2 * 1, we&#8217;ll calculate it by 7 * 6 * 5!.</p>
<p>We&#8217;ll first examine the naive approach and then the memoization method.  All in Javascript, and all with code samples&#8230;<br />
<span id="more-112"></span></p>
<h3>The Naive Approach</h3>
<p>The naive approach is very simple.  This is a snip / modification of the larger script, which you can see at the bottom of this post, but you will get the point.</p>
<pre>function naive(n) {
  if(n &lt;= 1) { return 1; }
    return n * naive(n - 1);
  }
}</pre>
<p>In this function, the parameter n is the value of the factorial we wish to calculate.  In this recursive function call, our base case will be when the parameter is 1.  1! = 1, of course, so instead of recursing we&#8217;ll simple return the value.  If n is greater than 1, we&#8217;ll recursively call the function, returning the current value we wish to calculate multiplied by n &#8211; 1.</p>
<p>While this approach works, it is wasteful.  By calling naive(5), we calculate 5 * 4 * 3 * 2 * 1.  Instead of saving the value of naive(5) to be used the next time we call the function, we effectively discard it.  When we call, naive(7), we cannot reuse the value we found for naive(5).</p>
<h3>The Memoization Approach</h3>
<p>The memoization approach is only slightly more complicated.  Again, this code is a section of a larger script, so bear with me.</p>
<pre>var lookup = {};

function memoized(n) {
  if(n &lt;= 1) { return 1; }

  if(lookup[n]) {
    return lookup[n];
  }

  lookup[n] = n * memoized(n - 1);
  return lookup[n];
}</pre>
<p>First, we create an empty object to serve as a lookup table for our factorial function.  This is where we&#8217;ll save the factorials that we&#8217;ve already calculated.  Our function has the same parameter and base case as our naive example.  The difference in the function is the lookup.  If the value of n is a key in our lookup table, then we simply return that value.  If the value isn&#8217;t in the lookup table, we&#8217;ll save it in the lookup table for later.  Now that we&#8217;ve found and saved the value of factorial n, we&#8217;ll return it to the caller.</p>
<p>If we first call memoized(5), we&#8217;ll calculate 5 * 4 * 3 * 2 * 1.  If we then call memoized(7), we&#8217;ll calculate 7 * 6 * 5!, the 5! being saved in the lookup table.  Much faster!</p>
<h3>The Full Script and Observations</h3>
<p>I said previously that the snippets above were part of a larger script.  In the process of writing this post, I wrote the functions as part of a Javascript object I also wrote a function to test the speed increase.  While not absolutely scientific, it should help you grasp the kind of increase you can expect over the succession of function calls.  The script was written and executed in node.js, but should work just as well in Firebug or even Rhino if you remove the #! script declaration.</p>
<p>For what it&#8217;s worth, on my machine node.js executed the test set for the naive method in ~5ms and the memoization method in ~1ms.  Firebug / Firefox 6.0 executed the test set for the naive method in ~14ms and the memoization method in ~1ms.  I think that says something about the speed of the V8 Javascript engine.</p>
<p>Feel free to use / modify this script for your own tests.  I hope that this example helps you speed up your code in the future.</p>
<pre>#!/usr/local/bin/node

var factorial = (function() {
  var lookup = {};

  return {
    //show_lookup is mainly for debugging purposes
    show_lookup : function() { return lookup; },

    run : {

      naive : function(n) {
        if(n &lt;= 1) { return 1; }
        return n * this.naive(n - 1);
      },

      memoized : function(n) {
        if(n &lt;= 1) { return 1; }

        if(lookup[n]) {
          return lookup[n];
        }

        lookup[n] = n * this.memoized(n - 1);
        return lookup[n];
      }

    }
  };
})();

var caller = function(method) {
  var start = (new Date()).getTime();

  for(var i = 0; i &lt;= 150; i++) {
    factorial.run[method](i);
  }

  for(var j = 150; j &gt; 1; j--) {
    factorial.run[method](j);
  }

  return (new Date()).getTime() - start;
};

console.log(caller("naive"));
console.log(caller("memoized"));</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Maintain a running list of your external IP address</title>
		<link>http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=maintain-a-running-list-of-your-external-ip-address</link>
		<comments>http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/#comments</comments>
		<pubDate>Mon, 08 Aug 2011 03:46:57 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=105</guid>
		<description><![CDATA[At home, I have a consumer level cable internet service.  I actually do not know if I have a dynamic IP address or a static IP address because I haven&#8217;t really cared enough to ask my ISP.  I would assume &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>At home, I have a consumer level cable internet service.  I actually do not know if I have a dynamic IP address or a static IP address because I haven&#8217;t really cared enough to ask my ISP.  I would assume that I have a dynamic IP address since most ISPs charge a premium for a static IP address, but since I don&#8217;t know for sure I thought I would find out for myself.</p>
<p>Using http://whatismyip.com &#8216;s &#8220;automation&#8221; page, Perl, and cron, I am going to maintain a list of my external IP addresses.  Not only will this answer the original question, but I can also gather some additional information, such as how often my IP address changes and whether or not I can force my IP address to change by disconnecting my modem <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p><span id="more-105"></span></p>
<h3>The logical steps</h3>
<p>The method I am going to use is relatively simple.  First, I need a script that will fetch a page with my current external IP address.  I&#8217;m going to use Perl, but any scripting language will do.  Once the script has fetched my current IP address, I will append the IP address and the current date, separated by a comma, to a log file.  I want the two fields to be comma separated in case I ever want to run a script over the log it will be easy to grab the information I want.</p>
<p>Once the script is finished, I need a way to automate it.  I would like to do this once a day&#8230; you may want to do this less often or more often depending on your goal.  Luckily, this is simple to do with cron, the Linux utility to run scheduled tasks.</p>
<h3>The code</h3>
<p>First, we need to create the script.  I am going to call my script ip_logger.pl.  We need to declare that the file is a Perl script, give the usual safety directives, and load relevant libraries.</p>
<pre>#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
use LWP::Simple;
use Time::localtime;</pre>
<p>I&#8217;ve loaded File::Slurp to ease reading and writing the the log file.  I&#8217;ve loaded LWP::Simple (libwww-perl) to fetch the page with our external IP.  I use Simple since we just need to make a GET request, we don&#8217;t need any additional features.  I&#8217;ve loaded Time::localtime to make generating a current date string simple and easy to read.</p>
<p>Next, we need to decide where we&#8217;re going to put our log file, and then actually make the request to the website to retrieve our external IP address.</p>
<pre># cron runs the script from your home directory,
# so give an absolute path
my $ip_addresses_filename = '/home/nelson/projects/perl/ip_logger/ip_addresses.txt';

# get current external ip address
my $content = get('http://automation.whatismyip.com/n09230945.asp');
$content = 'Could not pull ip address!' if !$content;</pre>
<p>Let&#8217;s notice that we create a scalar called $content and populate it with the contents at the whatismyip.com &#8216;s automation page.  The page has no HTML, it only contains the IP address, so we don&#8217;t have to parse the IP address or do anything else.  We&#8217;ll just assign the returned string to the scalar.  Also notice that if the page fetch fails, we&#8217;ll put a string indicative of such in the $content scalar.</p>
<p>Next, we need to capture the current date.  I&#8217;m going for the month-day-year format.</p>
<pre># get the current date to also write to our file
my $month = localtime-&gt;mon + 1;
my $day = localtime-&gt;mday;
my $year = localtime-&gt;year + 1900;
my $current_date = "$month-$day-$year";</pre>
<p>The last thing the script needs to do is actually write to the log file.  File::Slurp&#8217;s write_file function is smart enough to create the file if it doesn&#8217;t exist so we don&#8217;t need to guard against that.</p>
<pre># write / append it to the file
write_file($ip_addresses_filename, {append =&gt; 1}, $content . ',' . $current_date . "\n");</pre>
<h3>The cron</h3>
<p>The script by itself will not do a whole lot of good.  Unless you want to manually run the script once a day, we need to schedule it to run automatically.  In shell, we will do crontab -e to open our crontab for editing.  Then, we&#8217;ll insert this line.</p>
<pre>30 6 * * * /home/nelson/projects/perl/ip_logger/ip_logger.pl</pre>
<p>I want to run the script at 6:30 AM every day.  As I said earlier, you may want to adjust the interval to something more appropriate for your situation.</p>
<h3>The result</h3>
<p>After a few days, I&#8217;ll have a log file that looks similar to this.</p>
<pre>104.94.155.241,8-8-2011
104.94.155.241,8-9-2011
104.94.155.241,8-10-2011
104.94.155.241,8-11-2011
104.94.155.241,8-12-2011
104.94.155.241,8-13-2011</pre>
<p>Happy automating!</p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fixing line breaks in HL7 messages in Mirth Connect</title>
		<link>http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fixing-line-breaks-in-hl7-messages-in-mirth-connect</link>
		<comments>http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 04:07:28 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Mirth Connect]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[e4x]]></category>
		<category><![CDATA[hl7]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=95</guid>
		<description><![CDATA[Anyone who has worked in the world of healthcare integration or with HL7 knows that if you have seen one HL7 message, you&#8217;ve seen one HL7 message.  Now, a common problem with some source systems is that a line break &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Anyone who has worked in the world of healthcare integration or with HL7 knows that if you have seen one HL7 message, you&#8217;ve seen <em>one</em> HL7 message.  Now, a common problem with some source systems is that a line break will sneak in the middle of a segment, rendering the whole message invalid.  How many times have you seen this message?</p>
<pre>MSH|^~\&amp;|DDTEK LAB|ELAB-1|DDTEK OE|BLDG14|200502150930||ORU^R01^ORU_R01|CTRL-9876|P|2.4
PID|||010-11-1111||Estherhaus^Eva^E^^^^L|Smith|19720520|F|||256 Sherwood Forest Dr.^^Baton Rouge^LA^70809||(225)334-5232|(225)752-1213||||AC010111111||76-B4335^LA^20070520
OBR|1|948642^DDTEK OE|917363^DDTEK LAB|1554-5^GLUCOSE|||200502150730|||||||||020-22-2222^Levin-Epstein^Anna^^^^MD^^Micro-Managed
Health Associates|||||||||F|||||||030-33-3333&amp;Honeywell&amp;Carson&amp;&amp;&amp;&amp;MD
OBX|1|SN|1554-5^GLUCOSE^^^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^175|mg/dl|70_105|H|||F</pre>
<p>Notice the &#8220;Health Associates&#8221; segment? Obviously, this segment invalidates the message.  When this message is sent through a Mirth channel that expects incoming HL7, the message will error out when Mirth tries to parse it.  Here is how we can fix that.</p>
<p><span id="more-95"></span></p>
<h3>The Solution</h3>
<p>To fix this, we&#8217;re going to use a channel&#8217;s preprocessor script to append seemingly broken segments to the previous segment.  Since the preprocessor script is invoked <em>before</em> Mirth&#8217;s HL7 parser, we don&#8217;t have to worry about Mirth&#8217;s HL7 parser choking on it.</p>
<p>Instead of explaining the logic in a separate paragraph, I have left inline comments to explain what is happening.  I think, though, that it is fairly easy to follow.</p>
<p>Paste the following code into your channel&#8217;s preprocessor script.</p>
<h3>The Code</h3>
<pre>// initialize a first_iteration flag.
// we don't want to add a carriage return
// before the MSH segment
var first_iteration = true;

// initialize the new message as an empty string
var new_message = '';

// loop over each line in the message
// by splitting on the hl7 standard carriage return
for each (var line in message.split(/\r/)) {

  // if it is a valid hl7 segment, we'll
  // append the new line to the new message
  if(line.match(/^[a-zA-Z0-9]{3}\|/)) {
    // see the first comment
    if( ! first_iteration){
      new_message += '\r';
    }
    new_message += line;
  } else {
    // if it isn't a valid hl7 segment,
    // we'll append it to the end of the
    // previous segment instead
    new_message += ' ' + line;
  }

  // it will never be the first_iteration again
  first_iteration = false;
}

//send the fixed message to the channel
message = new_message;

return message;</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

