<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1903519570654910674</id><updated>2011-11-13T23:11:35.299-08:00</updated><category term='operator overloading'/><category term='scala'/><category term='map reduce'/><category term='software engineering'/><category term='type systems'/><category term='functional programming'/><category term='big data'/><category term='hadoop'/><title type='text'>Adam's Tech Thoughts</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-4630358313852375792</id><published>2011-10-13T16:31:00.001-07:00</published><updated>2011-10-13T16:42:51.151-07:00</updated><title type='text'>RIP dmr</title><content type='html'>Dennis Ritchie has passed away, and the world is a lesser place for it.  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(void) {&lt;br /&gt;   printf("Goodbye, dmr, and thanks for everything\n");&lt;br /&gt;   return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-4630358313852375792?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/4630358313852375792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=4630358313852375792' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/4630358313852375792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/4630358313852375792'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2011/10/rip-dmr.html' title='RIP dmr'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-3346115727413440237</id><published>2011-02-14T17:41:00.000-08:00</published><updated>2011-02-14T18:48:35.509-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='map reduce'/><category scheme='http://www.blogger.com/atom/ns#' term='hadoop'/><title type='text'>High-Level Hadoop</title><content type='html'>At a high level, map reduce converts an input record to one or more output records, and then combines those output records into the final output records. The way that it does this can seem like magic, since so much of it is handled by the framework. Hopefully, this will demystify some of what's going on.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You start by configuring the job with a Configuration. The configuration tells Hadoop things like the location of your input, where to put your output, what class implements your mapper and reducer, and how the input and output are formatted. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The input formatter and its record reader take the input file (or files) and split them into records that are passed to the map class.&lt;sup&gt;1&lt;/sup&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For each record that the record reader produces, map gets called once to produce an output record. Those records get stored in memory for awhile, and then written to disk when memory runs low or the map-phase is finished.&lt;sup&gt;2&lt;/sup&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once the mappers are done, their output gets sorted by its key, so that the records group together by key. Then those records are split up by key and sent off to reducers (all of the values for any given key will go to the same reducer, though). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The reducer then gets called with a key and all of the values for that key (as an Iterator). The reducer then does its thing with the values and writes them to its Context, which will send them to the output formatter, which deals with persisting the results.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Footnotes:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;sub&gt;1. The files in HDFS are split into chunks and replicated across the cluster. For performance, Hadoop will try to run the mappers on the same machines that house the blocks of the file. Unless you're writing your own input format, this will be transparent to you.&lt;/sub&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;sub&gt;&lt;br /&gt;&lt;/sub&gt;&lt;/div&gt;&lt;div&gt;&lt;sub&gt;2. You can also add a combiner, which does the same thing as the reducer and, in fact, can be the same class as your reducer. Adding one can potentially improve performance dramatically by drastically reducing the amount of data that has to be sorted and distributed to reducers&lt;/sub&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-3346115727413440237?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/3346115727413440237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=3346115727413440237' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/3346115727413440237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/3346115727413440237'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2011/02/high-level-hadoop.html' title='High-Level Hadoop'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-5338128812776690136</id><published>2011-02-06T08:05:00.000-08:00</published><updated>2011-02-06T13:51:19.240-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='map reduce'/><category scheme='http://www.blogger.com/atom/ns#' term='big data'/><category scheme='http://www.blogger.com/atom/ns#' term='hadoop'/><title type='text'>Know When to Fold 'Em</title><content type='html'>The Map &amp;amp; Reduce approach to dealing with large data sets, as implemented in Hadoop, has its background in functional programming, where both are used to manipulate the elements of a collection. Specifically, map is used to transform one element from the collection to some other type, for example to turn a string representation of an integer into an actual integer. Reduce, on the other hand, is used to combine all of the elements of the collection into a single result (which may, in turn, be another collection).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With just these two “primitives”, you can do a lot of powerful number crunching (or string manipulation, as the case may be), but what if you've got a lot of data coming in constantly &lt;i&gt;and&lt;/i&gt; you need to be able to answer questions quickly? (Hadoop tends to have the throughput of a delivery truck full of hard drives and the latency of a delivery truck full of hard drives)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, let's tackle the delivering-results-quickly part of the problem. Traditional RDBMS' handle this by building indices on the data for the fields that are most frequently searched. Fortunately, there's absolutely nothing that says that we can't do that with Map-Reduce. By building indices with map-reduce, we can then answer questions (that we know about ahead of time) about the data much more quickly. We can also calculate things like sums and averages on the data, so that answering analytics questions is just a simple value lookup.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, on to the constant influx of data problem. In functional programming, reduce has a “sister” function called fold that does the same thing as reduce &lt;i&gt;except&lt;/i&gt; it takes a starting value to reduce (or fold) into. With fold, you can take the results that you calculated &lt;i&gt;earlier&lt;/i&gt; and incorporate them into the new data (or vice versa). So, right now you may be thinking, “Well hello Mr. Fancy Pants. I've got news for you pal, Hadoop doesn't support fold, just reduce!” This is where the relationship between fold and reduce comes in (warning, LISP-like pseudocode follows); &lt;code&gt;(fold startingValue list)&lt;/code&gt; has the same effect as &lt;code&gt;(reduce (cons startingValue list))&lt;/code&gt;. We can take advantage of that equality by having a mapper that generates the previous run's results as input to a reducer, which combines it with the new data's results.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-5338128812776690136?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/5338128812776690136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=5338128812776690136' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/5338128812776690136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/5338128812776690136'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2011/02/know-when-to-fold-em.html' title='Know When to Fold &apos;Em'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-4634814224135890931</id><published>2011-01-26T14:14:00.000-08:00</published><updated>2011-01-26T14:53:43.399-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='operator overloading'/><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='type systems'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Not Your Type</title><content type='html'>Not too long ago, I was asked by a friend why I like Scala's type system and how it helps develop software faster (relative to dynamically typed languages, like Ruby). The short answer is that it doesn't; the slightly longer answer is that that isn't the point. An effective type system is more about making the computer &lt;i&gt;help&lt;/i&gt; you get your code &lt;i&gt;right, &lt;/i&gt;because throwing $125,000,000 down the drain when one person uses metric and the other English units looks bad on the next budget request.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I suspect that most detractors of type systems are doing so from the perspective of weak type systems (like Java's), which really does get in the way as much, if not more, than it helps. A more powerful type system (e.g. Haskell's or Scala's), however, can actually make it a compile error to make some subtle errors. As an example, here's some Scala to make Velocity a type defined by Meters/Seconds:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;br /&gt;class Meters(val dist : Float) {&lt;br /&gt;   def /(time : Seconds) : Velocity = { new Velocity(dist/time.magnitude)}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Seconds(val magnitude : Float)&lt;br /&gt;&lt;br /&gt;class Velocity(val magnitude: Float) {&lt;br /&gt;   override def toString() = magnitude + " m/s"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Feet(val magnitude : Float)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With that definition, you can define something of type Meters, divide it by something of type Seconds and get a Velocity. Ok, so far so good, but that doesn't&lt;i&gt; &lt;/i&gt;seem to be &lt;i&gt;that&lt;/i&gt; helpful... until you find that you can &lt;i&gt;not&lt;/i&gt; multiply the Meters by a typeless unit &lt;i&gt;or&lt;/i&gt; accidentally by Feet! Now, you may be thinking, "Hey, that's still getting in my way! I have a parameter in Feet and I don't want to bother changing it to meters!" That's where the second trick up Scala's sleeve comes in, by providing a way to implicitly convert from Feet to Meters.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By adding this little snippet of code: &lt;/div&gt;&lt;div&gt;&lt;code&gt;implicit def feetToMeters(feet : Feet) = new Meters(feet.dist * 0.3048F)&lt;/code&gt; &lt;/div&gt;&lt;div&gt;we can now divide Feet by Seconds and get Velocity &lt;i&gt;in meters / second!&lt;/i&gt; &lt;/div&gt;&lt;div&gt;So now, these two statements print the same value:&lt;/div&gt;&lt;div&gt;&lt;code&gt;println(new Meters(1000)/new Seconds(60))&lt;br /&gt;println(new Feet(3280.8399F)/new Seconds(60))&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;And helping avoid turning a Mars Orbiter into a Mars Crasher is just one more reason why I &lt;i&gt;really&lt;/i&gt; like Scala.&lt;/code&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-4634814224135890931?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/4634814224135890931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=4634814224135890931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/4634814224135890931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/4634814224135890931'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2011/01/not-your-type.html' title='Not Your Type'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-7682084846037881676</id><published>2011-01-08T19:03:00.000-08:00</published><updated>2011-01-08T19:19:13.427-08:00</updated><title type='text'>QuickBuzz</title><content type='html'>A few of my friends use FizzBuzz to screen candidates, and that's a good thing because it's &lt;i&gt;really&lt;/i&gt; good at weeding out the &lt;i&gt;completely&lt;/i&gt; incompetent. The problem comes when you need someone who's &lt;i&gt;more&lt;/i&gt; than just competent, you need someone who actually knows something. In those cases, I propose using Quick sort as a 2nd level FizzBuzz problem (or even a replacement for FizzBuzz). Quick sort is simple enough that it can be implemented in almost no time and almost no code by anyone who knows their programming language. It also has the benefit of opening the door for follow-on questions, like how do you avoid the algorithm taking n^2 time if the list is in order or what do you do if the list is too big to fit into main memory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-7682084846037881676?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/7682084846037881676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=7682084846037881676' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/7682084846037881676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/7682084846037881676'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2011/01/quickbuzz.html' title='QuickBuzz'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-3592685497194181695</id><published>2011-01-05T17:12:00.000-08:00</published><updated>2011-01-06T19:02:47.277-08:00</updated><title type='text'>The New Alchemy</title><content type='html'>Software development has given rise to entirely new alchemists, with entirely new approaches, including the "Powerful Process" and "Magical Language" schools. The one thing that both of the schools have in common is a belief that there exists some incantation or ritual that will transmute incompetent developers into great developers. They'd be better served trying to turn hydrogen into gold, since that's at least physically possible (if horrifically impractical). Let's look at these schools a little closer and we'll see why ITIL and CMMI (and a lot of "agile" processes!) are incompatible with Agile, and why Paul Graham was right &lt;span style="font-style:italic;"&gt;and &lt;/span&gt;wrong about LISP being a secret weapon in software development.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Arcane Rituals: The Powerful Process School&lt;/div&gt;&lt;div&gt;Acolytes of this school believe that if they can just find the one true process and follow it with sufficient rigor that it will guarantee that they will be guaranteed success in all of their software development endeavors. The holy grail of this school would be to find the process that lets them say, with a high degree of certainty, that it will take &lt;i&gt;x&lt;/i&gt; person weeks to build a particular system, &lt;i&gt;regardless&lt;/i&gt; of who comprises their development team. In effect, magically turning even incompetent developers into highly productive developers. It's this fixation on process over people that makes them ideologically incompatible with Agile. Sadly, even many proponents of Agile fall prey to these beliefs. You can tell if an "Agilist" has joined this school by observing their response to failed projects. If the response is to defend the process by saying, "You did it wrong! You didn't do thing x as prescribed by the process!", then you know you've met an agile alchemist. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Occasionally, processes are put into place that &lt;i&gt;do&lt;/i&gt; succeed in making the composition of a team a minor factor in how long it takes to develop software. Unfortunately, this isn't accomplished by improving the worst developers, but by dragging everyone down to their level. There is some good news, though! The best developers aren't held down at severely depressed productivity for long; they leave and make predicting the outcome of future efforts easier by leaving them with no chance of success.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Words of Power: The Magical Language School&lt;/div&gt;&lt;div&gt;Developers are often counted amongst the acolytes of this school, constantly searching for the programming language, IDE or new technology that'll make hard problems easy to solve and easier to implement. That's certainly understandable, since a lot of things in software development are &lt;i&gt;really &lt;/i&gt;hard and many developers love tinkering with new things. Certain commercial entities exacerbate the problem to profit from the sales of books, tools, and software by hyping every new thing that comes along. Unfortunately for developers (and fortunately for snake-oil salesmen), some problems &lt;i&gt;are just hard!&lt;/i&gt; No tool or language will ever make the intrinsically hard problems easy, at best they can stay out of the way and let the easy parts of the problems be easy. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Earlier, I mentioned that Paul Graham was right &lt;i&gt;and&lt;/i&gt; wrong about LISP being a secret weapon, and you may be wondering just how that could be. To be sure, LISP is a &lt;i&gt;very&lt;/i&gt; powerful language, very well suited to extending with powerful DSLs and someone comfortable with it could be extremely productive. That said, LISP alone isn't enough to make one team an order of magnitude more productive than another. What &lt;i&gt;does&lt;/i&gt; let LISP make teams significantly more productive is that it's a &lt;i&gt;great&lt;/i&gt; filter. Requiring LISP automatically rules out everyone other than really good developers. Since LISP is not a language that's a sure-fire path to a job, only people who actually care about software development know anything about it. Adding to that, LISP has a fairly high barrier to entry, by requiring an understanding of functional programming and recursion. Basically, any team that's using LISP is most likely a 10x team, and &lt;i&gt;that&lt;/i&gt; is the secret weapon.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, if neither languages or processes can work the magic, what _can_ we use to improve our odds of success at software development? The answer is simple; hire really good developers who work well together. Then tell them what you need them to do, and work with them to clarify any issues that come up and to make sure that they know when needs are changing as soon as possible.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-3592685497194181695?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/3592685497194181695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=3592685497194181695' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/3592685497194181695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/3592685497194181695'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2011/01/new-alchemy.html' title='The New Alchemy'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-8330423629831929206</id><published>2010-10-23T07:16:00.000-07:00</published><updated>2010-10-23T08:23:49.558-07:00</updated><title type='text'>Infinite sequences in Java</title><content type='html'>One of the interesting features in a lot of functional languages is lazily evaluated infinite sequences. Java lacks any explicit syntax for creating sequences, however the Iterator interface combined with generics lets us implement just such a feature, though it's obviously not as clean or succinct as in some languages.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As an example, here's an implementation of an "infinite" sequence of 64-bit integers.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;package blog;&lt;br /&gt;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.List;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;&lt;br /&gt;public class Sequence &lt;br /&gt;   implements Iterable&amp;lt;long&amp;gt; {&lt;br /&gt;&lt;br /&gt;  private long value;&lt;br /&gt;&lt;br /&gt;  public Sequence(long start) {&lt;br /&gt;      value=start;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Sequence() {&lt;br /&gt;      this(0L);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Iterator&amp;lt;long&amp;gt; iterator() {&lt;br /&gt;      return new LazyIterator();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public List&amp;lt;long&amp;gt; take(int toTake) {&lt;br /&gt;      ArrayList&amp;lt;long&amp;gt; retVal = &lt;br /&gt;         new ArrayList&amp;lt;long&amp;gt;(toTake);&lt;br /&gt;      for(int i = 0; i &amp;lt; toTake; ++i) {&lt;br /&gt;&lt;br /&gt;      public boolean hasNext() {&lt;br /&gt;          /* Always return true, because this &lt;br /&gt;             sequence is "infinite" */&lt;br /&gt;          return true;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      public Long next() {&lt;br /&gt;          // store where we are&lt;br /&gt;          long retVal = value; &lt;br /&gt;          // Move on to the next value&lt;br /&gt;          ++value; &lt;br /&gt;          // auto-boxing will turn it into a Long&lt;br /&gt;          return retVal; &lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      public void remove() {&lt;br /&gt;          throw new UnsupportedOperationException();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;This technique is also useful for parsing documents or in other situations where generating the entire list would either take too long or too much memory.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-8330423629831929206?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/8330423629831929206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=8330423629831929206' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/8330423629831929206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/8330423629831929206'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2010/10/infinite-sequences-in-java.html' title='Infinite sequences in Java'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-9127968981121548400</id><published>2010-10-22T17:42:00.000-07:00</published><updated>2010-10-22T18:15:51.879-07:00</updated><title type='text'>The Fizz-Buzz Challenge!</title><content type='html'>One of my friends asks all interviewees to implement Fizz Buzz as part of a programming interview and, sadly, many people trying to pass themselves off as programmers can't implement it. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The basic idea is to print out the integers from 1-100, if the number is evenly divisible by 3 also print "Fizz", if it's evenly divisible by 5, also print "Buzz" and if it's evenly divisible by 15, print "FizzBuzz". &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are a ton of possible implementations, most of them painfully obvious and straightforward, so here's the challenge. 1) What's the shortest program that you can write to solve the problem and 2) what's the "fastest" (in terms of fewest number of operations, no sane solution should take more than a few milliseconds to execute and very nearly all of that is I/O).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My shortest in terms of lines of code was 5 lines of code (not counting curly-brace only lines), with 300 conditionals, 100 increments and 200 modulus operations. Fewest instructions had 6 conditionals (could have been none, but that would've cost an extra 75 lines of code) and 100 increments (no other operations), but at a cost of 27 lines of code.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-9127968981121548400?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/9127968981121548400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=9127968981121548400' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/9127968981121548400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/9127968981121548400'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2010/10/fizz-buzz-challenge.html' title='The Fizz-Buzz Challenge!'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-510312323186242840</id><published>2010-10-19T18:03:00.000-07:00</published><updated>2010-10-19T18:18:25.477-07:00</updated><title type='text'>More algorithms and surprises</title><content type='html'>Testing the intersection problem using a HashMap turned up some more interesting numbers. In spite of that being an O(m+n) algorithm (m to build the hash map, n to check for intersection) like the linear probing, it was still significantly faster than the linear probing, even with the time to sort the two arrays removed. The HashMap based intersection did have the disadvantage of taking about an extra 3% memory.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another surprise came from the fact that sorting the two arrays was just a very minor part of the runtime for the linear intersection, even though it should be m*log(m) + n*log(n), as opposed to the intersection's m+n time. I &lt;i&gt;suspect&lt;/i&gt;, though I'm not certain, that that is due to locality and caching, since the sort operates on one array at a time, so the processor is better able to pre-fetch the needed data. Either that or Josh Bloch, Neil Gafter &amp;amp; John Rose have magical programming powers, which I'm also not ready to rule out quite yet.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-510312323186242840?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/510312323186242840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=510312323186242840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/510312323186242840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/510312323186242840'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2010/10/more-algorithms-and-surprises.html' title='More algorithms and surprises'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-5144740658950667046</id><published>2010-10-18T12:59:00.000-07:00</published><updated>2010-10-18T13:29:07.166-07:00</updated><title type='text'>Algorithms and surprises</title><content type='html'>The other day, there was a question on StackOverflow that basically boiled down to, "Why is my O(n*n) algorithm running so slow?" What the individual was trying to do was find all of the elements in one array that exist in another array. It didn't take long for someone to post that the person should sort the lists and iterate over them once, but that got me thinking. Would it be faster to do a linear traversal, or would doing a binary search back and forth between the two lists be faster? It seems like it should be, since it's O(log(n)) to find the next term, instead of a potential O(n), but I wanted to make sure. The answer was surprising, to say the least. The O(n*n) algorithm was by far the slowest, but the fastest turned out to be the linear traversal.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cumulative times (in ms) for 100 iterations of each of the approaches were (for input arrays of size 1,000, 2,000, 4,000, 8,000, 16,000, 32,000 &amp;amp; 64,000 elements respectively):&lt;/div&gt;&lt;div&gt;O(n*n):             [52, 174, 727, 2698, 10648, 42516, 171441]&lt;/div&gt;&lt;div&gt;Linear:             [43, 36, 74, 161, 332, 718, 1484]&lt;/div&gt;&lt;div&gt;Binary Search: [28, 41, 87, 182, 385, 825, 1727]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Actually looking at the data (all arrays populated by a call to Random.nextInt) revealed the answer. None of the binary searches were allowing the index for either array to jump by more than 2 or 3 entries at a time, meanwhile the linear approach wasn't examining more than 2 or 3 entries before finding the value (or a higher value to force a switch to the other list). The element being sought being so near the lower-end of the array made the binary search evaluate many more elements than the linear search. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The take-home from this test is that it's important to test your assumptions when it comes to performance. Intuitively, an algorithm with an expected runtime log(n)*log(n) &lt;i&gt;should&lt;/i&gt; be much faster than one with an expected runtime of 2n, but actual data distribution may make it not so.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-5144740658950667046?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/5144740658950667046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=5144740658950667046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/5144740658950667046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/5144740658950667046'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2010/10/algorithms-and-surprises.html' title='Algorithms and surprises'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-1348235957516273686</id><published>2010-08-28T17:21:00.000-07:00</published><updated>2010-08-28T18:19:15.800-07:00</updated><title type='text'>More on The Myth of SLOC</title><content type='html'>Wow, this has been a LONG time coming, but between finishing up my MS in CS and work I've been a bit busy. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SLOC and other metrics, like coupling and complexity metrics are just proxies for the only "metric" that really matters. The best name that I've got for this metric is "clarity of intent". It's nothing Earth-shattering or particularly easy to measure, but it's what really matters. It all boils down to how clearly does the code that you've written express what you want the code to do?  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Clarity of intent is why we name our variables things like "numOrders" instead of "doggie". A lot of languages fall short in this regard, in different ways.  Java, for example, makes you repeat yourself a lot like in the declaration for an ArrayList; ArrayList&lt;thingy&gt; al = new ArrayList&lt;thingy&gt;()&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Other languages (in particular, dynamically and "loosely" typed languages) tend to fail in the other direction, leaving you with declarations like&lt;/div&gt;&lt;div&gt;something = doSomething(someThingy);&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my opinion, this is one of the biggest failings of a lot of the dynamic languages like Javascript and (at least the last time I checked) Ruby. Functions and procedures take one or more "thingies" and there's no easy way to say, in code, "This thingy must have bark() and playDead() methods". Sure, you can say in comments, "Hey, if this thing can't bark and playDead, I don't want it", but there's no way to have the compiler check that for you.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A lot of languages, like Java, go too far in the other direction, though, and say "This thingy must extend/implement Doggie" when what you &lt;i&gt;really&lt;/i&gt; want to say is "This thingy needs to have behavor similar to a Doggie, but if you happen to have a Rubber Duckie that behaves like a Doggie, that's cool too".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A good language will let you say very clearly what the prerequisites are for a method and makes it clear what you intend to do (with features like list comprehensions or map/filters instead of dealing with iterators for everything).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-1348235957516273686?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/1348235957516273686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=1348235957516273686' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/1348235957516273686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/1348235957516273686'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2010/08/more-on-myth-of-sloc.html' title='More on The Myth of SLOC'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-2387122409361317409</id><published>2010-08-28T16:58:00.000-07:00</published><updated>2010-08-28T17:18:23.622-07:00</updated><title type='text'>Two approaches to products</title><content type='html'>There are, or at least seem to be, two distinct approaches to developing products. The first is to develop products that people need, whether they know it or not. These products may not be pretty or particularly fun, but they are the things that you absolutely need, whether you know it or not. People almost never love the products produced by companies who follow this path, but they'd be lost without them. This is what Google does, and it's why some of their products change everything and others flop completely.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other approach is to build beautiful products. The kind of things that people love and feel they absolutely HAVE to have. These products may be "game changers", but they rarely make any really major impact on the world (not counting the obvious commercial impact). Apple falls firmly into this category. They can produce a product that's laughably inferior, but it's so blasted pretty that people will rush and line up to spend massive amounts of money to buy it. It's as rare for products in this category to not be huge commercial successes as it is for the products to meaningfully change the world or anyone's life.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-2387122409361317409?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/2387122409361317409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=2387122409361317409' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/2387122409361317409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/2387122409361317409'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2010/08/two-approaches-to-products.html' title='Two approaches to products'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-1889552370515980785</id><published>2008-05-15T16:46:00.000-07:00</published><updated>2008-05-15T18:06:05.457-07:00</updated><title type='text'>The Myth of SLOC</title><content type='html'>Ah, that old favorite metric, Lines of Code, all the ubiquity of a spork and slightly less useful. Since we all (hopefully) know that SLOC is a useless metric, the obvious question is why would anyone use it? The simple answer is that it's so easy that a drunk chimp can calculate the metric!&lt;br /&gt;&lt;br /&gt;As an example of why SLOC is useless, imagine two programmers at different companies implementing a paging functionality. Specifically, both programmers need to determine whether a next button and a previous button should be displayed. Programmer A produces the following code:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;   String n,p;  &lt;br /&gt;   if(x&amp;&amp;y) {&lt;br /&gt;      n="enabled";&lt;br /&gt;      p="enabled";&lt;br /&gt;   } else if(x&amp;&amp;!y) {&lt;br /&gt;      n="enabled";&lt;br /&gt;      p="disabled";&lt;br /&gt;   } else if(!x &amp;&amp; y) {&lt;br /&gt;      n="disabled";&lt;br /&gt;      p="enabled"; &lt;br /&gt;   } else if(!x &amp;&amp; !y) {&lt;br /&gt;      n="disabled";&lt;br /&gt;      p="disabled";&lt;br /&gt;   } else {&lt;br /&gt;      n="disabled";&lt;br /&gt;      p="disabled";&lt;br /&gt;   }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Wow, 16 lines of code! Programmer A's been pretty productive. Programmer B, on the other hand, came up with:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;   String next = hasNext ? "enabled" : "disabled";&lt;br /&gt;   String prev = hasPrev ? "enabled" : "disabled";&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Wha? Only two lines of code? What a slacker!  Oh, wait... both ultimately have the same effect! In fact, on closer examination, we find that Programmer A's code actually &lt;strong&gt;reduces&lt;/strong&gt; the value of the code base! In case you're wondering how adding functionality could reduce value, consider the cost of maintenance. Those 16 lines, including a logically impossible else clause, will have to be read and understood by some poor soul if that file ever needs to be changed. Since none of the variables have meaningful names and the boolean clauses are more complicated than necessary, understanding Programmer A's code will take significantly longer. &lt;br /&gt;&lt;br /&gt;So, if more lines of code aren't better, doesn't that mean that expressing the same thing in fewer lines of code is better? Turns out that the answer is a resounding... not necessarily. I'll expand on that a bit more in the next post, including touching on the myth that fewer lines of code implies fewer bugs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-1889552370515980785?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/1889552370515980785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=1889552370515980785' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/1889552370515980785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/1889552370515980785'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2008/05/myth-of-sloc.html' title='The Myth of SLOC'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-8762970721919990309</id><published>2008-05-14T18:36:00.001-07:00</published><updated>2008-05-14T18:46:46.037-07:00</updated><title type='text'>Dev102.com Programming Challenge 3</title><content type='html'>&lt;a href="http://www.dev102.com/2008/05/12/a-programming-job-interview-challenge-3"&gt;Programming Challenge 3 at Dev102.com&lt;/a&gt; is to find an element in a m&lt;span style="font-style: italic;"&gt;x&lt;/span&gt;n matrix whose rows and columns are sorted in ascending order. A quick and easy way to do this is to perform a binary search in the first column to find the row with the highest value that is less than or equal to the value for which you're searching. Then, perform a binary search in that row to find the element.&lt;br /&gt;&lt;br /&gt;If that didn't find the element, then do the same thing except perform the binary search on the first row and then the column. You can actually use information from the first run to limit the size of the size of the column, but the performance improvement will (in general) be relatively small.&lt;br /&gt;&lt;br /&gt;The runtime for this is &lt;span style="font-style: italic;"&gt;O&lt;/span&gt;(log m + log n)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-8762970721919990309?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/8762970721919990309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=8762970721919990309' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/8762970721919990309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/8762970721919990309'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2008/05/dev102com-programming-challenge-3.html' title='Dev102.com Programming Challenge 3'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-2678342766648839649</id><published>2008-05-06T18:37:00.000-07:00</published><updated>2008-05-07T12:48:22.644-07:00</updated><title type='text'>Dev102 Programming Challenge 2</title><content type='html'>&lt;a href="http://www.dev102.com/2008/05/05/a-programming-job-interview-challenge-2/"&gt;Programming Challenge #2 at Dev102.com&lt;/a&gt; is to find an efficient way to reverse the bits in a 1000x1000 byte image. Assuming you can afford 256 bytes for a cache, one really fast general-purpose way to implement this is to create an array with an entry for each possible value of a byte, storing the reversed bits of the byte. For each byte in the image, you can then look the reversed bits nearly instantly. The runtime of the algorithm is &lt;span style="font-style: italic;"&gt;O&lt;/span&gt;(n) with a trivial constant multiplier.&lt;br /&gt;&lt;br /&gt;This algorithm, by the way, is insanely easy to make run in multiple threads and should run extremely fast on a multi-core SIMD processor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-2678342766648839649?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/2678342766648839649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=2678342766648839649' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/2678342766648839649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/2678342766648839649'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2008/05/dev102-programming-challenge-2.html' title='Dev102 Programming Challenge 2'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1903519570654910674.post-908803458812273340</id><published>2008-05-06T17:38:00.000-07:00</published><updated>2008-05-06T18:30:41.626-07:00</updated><title type='text'>The Only Process You'll Ever Need</title><content type='html'>Scrum, CMM-I, ITIL and countless others. It seems that for every developer, there are half a dozen software development methodologies and processes. Some are lightweight, some are heavyweight and some are stupid-weight, producing orders of magnitude more documentation than code.&lt;br /&gt;&lt;br /&gt;So, you may be wondering, why are there so many different processes? The answer is that everyone's looking for that one, magical process that'll make software development predictable and repeatable. Unfortunately, I don't have that magical process to give you, in fact, I seriously doubt that it even exists. What I &lt;span style="font-style: italic;"&gt;do&lt;/span&gt; have for you however is a process without which your development efforts are &lt;span style="font-style: italic;"&gt;guaranteed&lt;/span&gt; to fail. The process that I have for you is a &lt;span style="font-style: italic;"&gt;very&lt;/span&gt; strict process, far more strict, in fact, than most heavyweight processes, but it requires no more documentation than your handwritten notes to yourself.&lt;br /&gt;&lt;br /&gt;I won't keep you in suspense anymore. This super-process is none other than &lt;span style="font-style: italic;"&gt;the scientific method.&lt;/span&gt; In case you're not familiar with the scientific method, here are the highlights.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Consider the problem&lt;/li&gt;&lt;li&gt;Gather data&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Formulate a hypothesis (an educated guess about how to solve the problem)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Test your hypothesis&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;Use the information from testing your hypothesis to accept, reject, or refine the hypothesis&lt;/li&gt;&lt;/ol&gt;The scientific method is useful at all stages of software development, but it is particularly useful when debugging, which is frequently the most difficult part of development. Before fixing a bug, &lt;span style="font-style: italic;"&gt;any&lt;/span&gt; bug, take some time to apply the scientific method. Think about the bug and what the implications of it are. Don't jump straight into the fix, spend some time to make sure your fix will really fix the problem and not just mask the symptoms. Figure out how you'll test that your fix actually works without breaking anything else, and then test the fix. If it works, commit the fix and do the dance of joy!&lt;br /&gt;&lt;br /&gt;Good luck and enjoy your coding!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1903519570654910674-908803458812273340?l=programmersthoughts.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programmersthoughts.blogspot.com/feeds/908803458812273340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1903519570654910674&amp;postID=908803458812273340' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/908803458812273340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1903519570654910674/posts/default/908803458812273340'/><link rel='alternate' type='text/html' href='http://programmersthoughts.blogspot.com/2008/05/only-process-youll-ever-need.html' title='The Only Process You&apos;ll Ever Need'/><author><name>Adam Browning</name><uri>http://www.blogger.com/profile/03376806966616596553</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
