<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: Tag shuffles</title>
    <link>http://blog.moertel.com/articles/tag/shuffles?tag=shuffles</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>The &amp;quot;perfect shuffles&amp;quot; puzzle (solved in Haskell)</title>
      <description>&lt;p&gt;I ran across a fun programming puzzle (via
&lt;a href="http://weblog.raganwald.com/2006/03/encounter-with-programming-interview.html"&gt;Raganwald&lt;/a&gt;):&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Given a deck of &lt;em&gt;n&lt;/em&gt; unique cards, cut the deck &lt;em&gt;i&lt;/em&gt; cards from top
    and perform a perfect shuffle. A perfect shuffle begins by putting
    down the bottom card from the top portion of the deck followed by
    the bottom card from the bottom portion of the deck followed by
    the next card from the top portion, etc., alternating cards until
    one portion is used up. The remaining cards go on top. The problem
    is to find the number of perfect shuffles required to return the
    deck to its original order. Your function should be declared as:&lt;/p&gt;
    &lt;p&gt;&lt;code&gt;static long shuffles(int nCards,int iCut);&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;Please send the result of shuffles(1002,101) along with your
    program and your resume to &amp;#8216;resume&amp;#8217; at nextag.com.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;It&amp;#8217;s a fun problem, so give it a try before reading on.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Warning: small spoilers ahead&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The first thing I usually do when I encounter a new problem is explore
it until I have a feel for its essence.  For this problem, the
shuffle algorithm seemed like a good starting point:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;shuffle&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;reverse&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;uncurry&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;flip&lt;/span&gt; &lt;span class='varid'&gt;interleave&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;splitAt&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='comment'&gt;-&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;reverse&lt;/span&gt;

&lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;xs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt; &lt;span class='varid'&gt;ys&lt;/span&gt;
&lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;     &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;     &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;
&lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;     &lt;span class='varid'&gt;ys&lt;/span&gt;     &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;ys&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;From within GHCi, I watched a few iterations, using a ten-card deck as
input:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='conid'&gt;Main&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;mapM_&lt;/span&gt; &lt;span class='varid'&gt;print&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;take&lt;/span&gt; &lt;span class='num'&gt;10&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;iterate&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;shuffle&lt;/span&gt; &lt;span class='num'&gt;10&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='keyglyph'&gt;..&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;After a bit of study, a light-bulb appeared over my head, and I
realized something about the fundamental nature of the problem that I
had overlooked earlier.  (I won&amp;#8217;t spoil the fun by saying what it
was.)  From that point, the solution was easy to implement:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;module&lt;/span&gt; &lt;span class='conid'&gt;Main&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;main&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;

&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Control&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Monad&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;liftM&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Array&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Set&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Set&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;empty&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;insert&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;member&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;System&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Environment&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;getArgs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;

&lt;span class='varid'&gt;main&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='keyword'&gt;_&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;liftM&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='varid'&gt;read&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;getArgs&lt;/span&gt;
    &lt;span class='varid'&gt;print&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;shuffles&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;

&lt;span class='varid'&gt;shuffles&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Integer&lt;/span&gt;
&lt;span class='varid'&gt;shuffles&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;foldl&lt;/span&gt; &lt;span class='varid'&gt;lcm&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='varid'&gt;toInteger&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;fst&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;foldl&lt;/span&gt; &lt;span class='varid'&gt;dfs&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;empty&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;deck'&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;deck&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;deck'&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;  &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt; &lt;span class='keyglyph'&gt;..&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='comment'&gt;-&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;shuffle&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varid'&gt;deck&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;perms&lt;/span&gt;          &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;array&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='comment'&gt;-&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;zip&lt;/span&gt; &lt;span class='varid'&gt;deck'&lt;/span&gt; &lt;span class='varid'&gt;deck&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;dfs&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;ls&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;vs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;j&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='varid'&gt;member&lt;/span&gt; &lt;span class='varid'&gt;j&lt;/span&gt; &lt;span class='varid'&gt;vs&lt;/span&gt; &lt;span class='keyword'&gt;then&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;ls&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;vs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyword'&gt;else&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;l&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ls&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;vs'&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
                     &lt;span class='keyword'&gt;where&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;l&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;vs'&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;follow&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt; &lt;span class='varid'&gt;j&lt;/span&gt; &lt;span class='varid'&gt;vs&lt;/span&gt;
    &lt;span class='varid'&gt;follow&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varid'&gt;vs&lt;/span&gt;  &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='varid'&gt;member&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varid'&gt;vs&lt;/span&gt; &lt;span class='keyword'&gt;then&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='varid'&gt;vs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
                     &lt;span class='keyword'&gt;else&lt;/span&gt; &lt;span class='varid'&gt;follow&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;perms&lt;/span&gt;&lt;span class='varop'&gt;!&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;insert&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varid'&gt;vs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;

&lt;span class='varid'&gt;shuffle&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;reverse&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;uncurry&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;flip&lt;/span&gt; &lt;span class='varid'&gt;interleave&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;splitAt&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='comment'&gt;-&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;reverse&lt;/span&gt;

&lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;xs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt; &lt;span class='varid'&gt;ys&lt;/span&gt;
&lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;     &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;     &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;
&lt;span class='varid'&gt;interleave&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;     &lt;span class='varid'&gt;ys&lt;/span&gt;     &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;ys&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The following command compiles the program:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ ghc -O2 -o shuffle --make PerfectShuffle.hs
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The program computes the requested solution in about 4&amp;nbsp;ms on my
1.8-GHz box:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ time ./shuffle 1002 101
5812104600

real    0m0.006s
user    0m0.004s
sys     0m0.004s
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you Google around, you can find other solutions, most of them
implemented in Java.&lt;/p&gt;


	&lt;h3&gt;Solve puzzles!  They&amp;#8217;re good for you.&lt;/h3&gt;


	&lt;p&gt;Solving programming puzzles is a fun way to exercise parts of the
brain that day-to-day coding rarely uses.  If you are looking for
some more puzzles, check out what&amp;#8217;s archived at the &lt;a href="http://community.moertel.com/ss/space/Programming+Fun+Challenge"&gt;Programming
Fun Challenge&lt;/a&gt;
page.  Some are simple but others are downright tricksy.&lt;/p&gt;


&lt;div class="update"&gt;
&lt;strong&gt;Update 2006-03-24:&lt;/strong&gt; Last night I thought of a simple optimization to
my original implementation, and this morning I revised my code.  The
optimization reduces the run time for the (1002, 101) case from about
16&amp;nbsp;ms to about 4&amp;nbsp;ms.  I have replaced the original code from
this article with the new code, which is slightly longer.  For comparison, here is the original implementation:

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;shuffles&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Integer&lt;/span&gt;
&lt;span class='varid'&gt;shuffles&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;foldl&lt;/span&gt; &lt;span class='varid'&gt;lcm&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;fromIntegral&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;cycleLength&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;deck'&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;deck&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;deck'&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='keyglyph'&gt;..&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='comment'&gt;-&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;shuffle&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varid'&gt;deck&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;perms&lt;/span&gt;         &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;array&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='comment'&gt;-&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;zip&lt;/span&gt; &lt;span class='varid'&gt;deck'&lt;/span&gt; &lt;span class='varid'&gt;deck&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;cycleLength&lt;/span&gt; &lt;span class='varid'&gt;j&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;follow&lt;/span&gt; &lt;span class='varid'&gt;j&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;perms&lt;/span&gt;&lt;span class='varop'&gt;!&lt;/span&gt;&lt;span class='varid'&gt;j&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt;
    &lt;span class='varid'&gt;follow&lt;/span&gt; &lt;span class='varid'&gt;i0&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='varid'&gt;i0&lt;/span&gt; &lt;span class='keyword'&gt;then&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='keyword'&gt;else&lt;/span&gt; &lt;span class='varid'&gt;follow&lt;/span&gt; &lt;span class='varid'&gt;i0&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;perms&lt;/span&gt;&lt;span class='varop'&gt;!&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;&lt;strong&gt;Update 2006-03-25:&lt;/strong&gt; I replaced the optimized code with a slightly more idiomatic version.
I did this because I was guilt-tripped by a comment on Reddit saying that Haskell looked &amp;#8220;ugly.&amp;#8221; This code is, in fact, pretty ugly as far as Haskell goes.  (Tip: Don&amp;#8217;t judge a language based on a single sample, especially if it&amp;#8217;s this one. If you want to see more beautiful code, &lt;a href="http://community.moertel.com/~thor/acm-contest-1996/"&gt;my  Haskell solutions&lt;/a&gt; to &lt;a href="http://www.ntnu.edu.tw/acm/ProblemSetArchive/A_FINALS/1996/Finals96html/"&gt;the 1996 &lt;span class="caps"&gt;ACM&lt;/span&gt; International Collegiate Programming Contest&lt;/a&gt; are much less offensive.)&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update 2006-11-04:&lt;/strong&gt; Colorized the Haskell snippets.&lt;/p&gt;


&lt;/div&gt;</description>
      <pubDate>Thu, 23 Mar 2006 16:51:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ce0388053c2b36cae46a6675af744f40</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2006/03/23/the-perfect-shuffles-puzzle-solved-in-haskell</link>
      <category>programming</category>
      <category>haskell</category>
      <category>fun stuff</category>
      <category>haskell</category>
      <category>puzzles</category>
      <category>shuffles</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/60</trackback:ping>
    </item>
  </channel>
</rss>
