<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>I'm Putting On My Top Hat, Tying Up My White Tie, Brushing Out My Tails -- In That Order</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx</link><description>I thought I might blog briefly on an interesting algorithm which can be implemented very elegantly in JScript, but a lot of scripters don't know about.
 
 
 
 Most scripters know about the sort method on the Array prototype -- you give it an array</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>re: I'm Putting On My Top Hat, Tying Up My White Tie, Brushing Out My Tails -- In That Order</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#10098285</link><pubDate>Tue, 30 Nov 2010 12:17:03 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10098285</guid><dc:creator>Matthew Rodatus</dc:creator><description>&lt;p&gt;Under step four, the call to visit, you have this:&lt;/p&gt;
&lt;p&gt;visit(dependencies, dependencies[dependency][child], list, dead);&lt;/p&gt;
&lt;p&gt;Should the second argument be simply child, instead of dependencies[dependency][child]? The latter doesn&amp;#39;t make any sense to me, and the former seems to work.&lt;/p&gt;
&lt;p&gt;Matthew&lt;/p&gt;
&lt;div class="yellowbox"&gt;
&lt;p&gt;The former does &lt;strong&gt;not&lt;/strong&gt; work; did you actually &lt;em&gt;try&lt;/em&gt; it?&amp;nbsp; It gives the output &amp;quot;tophat, 0, bowtie, socks, pocketwatch, vest, shirt, 1, shoes, cufflinks, gloves, tailcoat, underpants, trousers&amp;quot;, which first, has you putting on your vest before your shirt, and second, has mysteriously gained items &amp;quot;0&amp;quot; and &amp;quot;1&amp;quot; for some strange reason. That is completely and utterly broken.&lt;/p&gt;
&lt;p&gt;What you have forgotten is that the &amp;quot;for-in&amp;quot; loop does not give you the &lt;strong&gt;members&lt;/strong&gt; of a collection (as the foreach loop does in C#). It gives you the &lt;strong&gt;indicies&lt;/strong&gt; of the members of the collection. &amp;quot;child&amp;quot; is an index into an array; zero or one, in this case. &lt;/p&gt;
&lt;p&gt;- Eric&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10098285" width="1" height="1"&gt;</description></item><item><title>  Optimal Dressing, or A challenge to Eric Lippert  | MikeSchinkel.com</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#8599464</link><pubDate>Sun, 15 Jun 2008 08:14:26 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8599464</guid><dc:creator>  Optimal Dressing, or A challenge to Eric Lippert  | MikeSchinkel.com</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://mikeschinkel.com/blog/optimaldressingorachallengetoericlippert/"&gt;http://mikeschinkel.com/blog/optimaldressingorachallengetoericlippert/&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8599464" width="1" height="1"&gt;</description></item><item><title>How Not To Teach Recursion</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#5403543</link><pubDate>Thu, 11 Oct 2007 21:39:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5403543</guid><dc:creator>Fabulous Adventures In Coding</dc:creator><description>&lt;p&gt;A Joel On Software reader asked the other day for examples of recursive functions other than old chestnuts&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5403543" width="1" height="1"&gt;</description></item><item><title>Recursion, Part Zero</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#4796122</link><pubDate>Fri, 07 Sep 2007 01:59:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4796122</guid><dc:creator>Fabulous Adventures In Coding</dc:creator><description>&lt;p&gt;I’ve mentioned recursive programming techniques several times over the years in this blog ( Topological&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4796122" width="1" height="1"&gt;</description></item><item><title>re: I'm Putting On My Top Hat, Tying Up My White Tie, Brushing Out My Tails -- In That Order</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#92522</link><pubDate>Fri, 19 Mar 2004 06:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:92522</guid><dc:creator>Mike Schinkel</dc:creator><description>&lt;a target="_new" href="http://blogs.xtras.net/mikes/PermaLink,guid,57000f55-832e-47e7-9895-2658d4e65d52.aspx"&gt;http://blogs.xtras.net/mikes/PermaLink,guid,57000f55-832e-47e7-9895-2658d4e65d52.aspx&lt;/a&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=92522" width="1" height="1"&gt;</description></item><item><title>re: I'm Putting On My Top Hat, Tying Up My White Tie, Brushing Out My Tails -- In That Order</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#91988</link><pubDate>Thu, 18 Mar 2004 16:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:91988</guid><dc:creator>Brian Butler</dc:creator><description>Thanks for another great article, Eric.  I had to solve a similar problem last year using XSL and thought the solution was particularly elegant.  Given a list of documents, some of which should be read before others:&lt;br&gt;&lt;br&gt;&amp;lt;page id=&amp;quot;A&amp;quot; name=&amp;quot;Page 1&amp;quot;/&amp;gt;  &lt;br&gt;&amp;lt;page id=&amp;quot;B&amp;quot; name=&amp;quot;Page 2&amp;quot;&amp;gt;&lt;br&gt;    &amp;lt;prereq id=&amp;quot;A&amp;quot;/&amp;gt;&lt;br&gt;&amp;lt;/page&amp;gt;&lt;br&gt;&lt;br&gt;This transform outputs a valid reading order.  In my case I needed to detect circular references and also be able to deal with references to documents not on the list.&lt;br&gt;&lt;br&gt;&amp;lt;xsl:template name=&amp;quot;prereq_sort&amp;quot;&amp;gt;&lt;br&gt;  &amp;lt;xsl:param name=&amp;quot;unsorted&amp;quot;/&amp;gt;&lt;br&gt;  &amp;lt;xsl:variable name=&amp;quot;invalid&amp;quot; select=&amp;quot;$unsorted[prereq/@id=$unsorted/@id]&amp;quot; /&amp;gt;&lt;br&gt;  &amp;lt;xsl:variable name=&amp;quot;valid&amp;quot; select=&amp;quot;$unsorted[count(.|$invalid)!=count($invalid)]&amp;quot; /&amp;gt;&lt;br&gt;  &amp;lt;xsl:if test=&amp;quot;count($valid)=0&amp;quot;&amp;gt;No valid pages - possible circular reference!&amp;lt;/xsl:if&amp;gt;&lt;br&gt;&lt;br&gt;  &amp;lt;!-- Output pages without dependencies --&amp;gt;&lt;br&gt;  &amp;lt;xsl:for-each select=&amp;quot;$valid&amp;quot;&amp;gt;&lt;br&gt;    &amp;lt;xsl:value-of select=&amp;quot;@name&amp;quot; /&amp;gt;&lt;br&gt;  &amp;lt;/xsl:for-each&amp;gt;&lt;br&gt;&lt;br&gt;  &amp;lt;!-- If there are still pages with dependencies, sort again --&amp;gt;&lt;br&gt;  &amp;lt;xsl:if test=&amp;quot;count($valid)&amp;gt;0 and count($invalid)&amp;gt;0&amp;quot;&amp;gt;&lt;br&gt;    &amp;lt;xsl:call-template name=&amp;quot;prereq_sort&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xsl:with-param name=&amp;quot;unsorted&amp;quot; select=&amp;quot;$invalid&amp;quot;/&amp;gt;&lt;br&gt;    &amp;lt;/xsl:call-template&amp;gt;&lt;br&gt;  &amp;lt;/xsl:if&amp;gt;&lt;br&gt;&amp;lt;/xsl:template&amp;gt;&lt;br&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=91988" width="1" height="1"&gt;</description></item><item><title>re: I'm Putting On My Top Hat, Tying Up My White Tie, Brushing Out My Tails -- In That Order</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#91882</link><pubDate>Thu, 18 Mar 2004 13:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:91882</guid><dc:creator>Dan Shappir</dc:creator><description>Indeed, a nice sample. Although your implementation obviously works, the dead variable should be initialized to {}, not to []. This is because it's used as a set, not as an array. Also, in real life (as opposed to an online sample) I would define the visit() function inside topSort() so that it does not pollute the global scope. Done this way, you also avoid the need to pass list and dead as parameters because they are in the closure - less typing and also slightly better performance I believe.&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=91882" width="1" height="1"&gt;</description></item><item><title>Other examples</title><link>http://blogs.msdn.com/b/ericlippert/archive/2004/03/16/i-m-putting-on-my-top-hat-tying-up-my-white-tie-brushing-out-my-tails-in-that-order.aspx#91158</link><pubDate>Wed, 17 Mar 2004 13:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:91158</guid><dc:creator>Robert Hahn</dc:creator><description>Hi, Eric.&lt;br&gt;&lt;br&gt;I understand the code you're setting up well enough, and I agree that it's a quite elegant solution.&lt;br&gt;&lt;br&gt;But (and there always seems to be one) I think the example makes me think that 80% of the hard work has to be done by the programmer in creating the dependency graph.  Because of the example chosen, all it looks like on first inspection is that you are merely serializing a data structure.  And you know what? Maybe that's the point - but it seems to me that a trick that requires 80% effort to set up isn't a real productivity enhancer.&lt;br&gt;&lt;br&gt;So while typing this, I realized that there was another example that people may relate to that may show the value of this useful function.&lt;br&gt;&lt;br&gt;Consider a software application that is extensible with plug-ins.  If some of the plug-ins are dependent on others, then a partial sort is required to determine the order in which they are loaded so that errors can be prevented.  Further, since this application has an active plugin developer community, the list of plug-ins is always growing.&lt;br&gt;&lt;br&gt;The advantages of using a partial sort algorithm as described becomes clear: the dependency graph is much easier to maintain over time than a compiled list -- especially once the number of plugins reaches a large number (50-100). Finally, if someone only wanted to install a subset of plug-ins, they could query the dependency graph with that subset to realize the ordering of their subset.&lt;br&gt;&lt;br&gt;This example also highlights why you need to be careful of cycles, so I'm looking forward to seeing what you'll say about cycle detection.  All I know is that it's a hard problem (if it wasn't, then Go would be a lot easier to write AI opponents for).&lt;br&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=91158" width="1" height="1"&gt;</description></item></channel></rss>