<?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: The "perfect shuffles" puzzle (solved in Haskell)</title>
    <link>http://blog.moertel.com/articles/2006/03/23/the-perfect-shuffles-puzzle-solved-in-haskell</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>
    <item>
      <title>"The "perfect shuffles" puzzle (solved in Haskell)" by Tom Moertel</title>
      <description>&lt;p&gt;Dear AnonymousCoward,&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m fairly confident that the answer is not 13898745.  If you want to know why, read on.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;SPOILERS AHEAD&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;The cards at each position in the deck move to another position after
each shuffle.  If you trace the movements, you will see that they form
cycles (and, in fact, &lt;em&gt;must&lt;/em&gt; form cycles).  The various cycles formed
by this particular deck size and shuffling strategy have lengths of
9, 40, 50, 206, 230, 232, and 235. (Note that their sum is 1002.)&lt;/p&gt;


	&lt;p&gt;The cards that move through the 9-length cycle will return to their
original positions in the deck after 9 shuffles.  The cards in the
40-length cycle, however, will require 31 additional shuffles before
they return to their original positions.  But, at that time, the
9-length-cycle cards will again be out of their original positions. You have to shuffle the deck a total of 360 times &amp;#8211; the least common
multiple of 9 and 40 &amp;#8211; before the cards in both cycles return to their
original positions.&lt;/p&gt;


	&lt;p&gt;The same holds for all of the other cycles.  Thus
to return all of the cards in the deck to their original positions,
you must shuffle the deck &lt;em&gt;N&lt;/em&gt; times, where &lt;em&gt;N&lt;/em&gt; is the
least common multiple of all the cycle lengths.  If you compute
&lt;em&gt;N&lt;/em&gt;, it turns out to be 5,812,104,600:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Prelude&amp;gt; foldl1 lcm [9,40,50,206,230,232,235] :: Integer
5812104600
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Note that &lt;em&gt;N&lt;/em&gt; is too large to be represented by a 32-bit integer.
You&amp;#8217;ll need to use some kind of &amp;#8220;BigInt&amp;#8221; type to compute it.&lt;/p&gt;


	&lt;p&gt;For additional explanations, try searching on Google for
&lt;a href="http://www.google.com/search?q=%22perfect+shuffles%22+5812104600"&gt;&amp;#8220;perfect
shuffles&amp;#8221; 5812104600&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Cheers,&lt;br /&gt;
Tom&lt;/p&gt;</description>
      <pubDate>Sun, 25 Feb 2007 11:46:40 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:96513f71-f042-4d3a-9b50-35806822de37</guid>
      <link>http://blog.moertel.com/articles/2006/03/23/the-perfect-shuffles-puzzle-solved-in-haskell#comment-393</link>
    </item>
    <item>
      <title>"The "perfect shuffles" puzzle (solved in Haskell)" by AnonymousCoward</title>
      <description>&lt;p&gt;Are you sure the answer is not 13898745?&lt;/p&gt;</description>
      <pubDate>Sun, 25 Feb 2007 04:13:52 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fe20fe45-394e-4c21-9e29-b85c4b987e6a</guid>
      <link>http://blog.moertel.com/articles/2006/03/23/the-perfect-shuffles-puzzle-solved-in-haskell#comment-392</link>
    </item>
    <item>
      <title>"The "perfect shuffles" puzzle (solved in Haskell)" by Reg Braithwaite</title>
      <description>&lt;p&gt;Nice!&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2006 17:06:42 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://blog.moertel.com/articles/2006/03/23/the-perfect-shuffles-puzzle-solved-in-haskell#comment-122</link>
    </item>
  </channel>
</rss>
