{"id":450,"date":"2007-12-09T17:41:27","date_gmt":"2007-12-09T07:41:27","guid":{"rendered":"http:\/\/www.somethinkodd.com\/oddthinking\/2007\/12\/09\/shuffling-and-ownage\/"},"modified":"2007-12-09T17:47:55","modified_gmt":"2007-12-09T07:47:55","slug":"shuffling-and-ownage","status":"publish","type":"post","link":"https:\/\/www.somethinkodd.com\/oddthinking\/2007\/12\/09\/shuffling-and-ownage\/","title":{"rendered":"Shuffling and Ownage"},"content":{"rendered":"<p>Last week, <a href=\"http:\/\/home.comcast.net\/~mike_pope\">Mike Pope<\/a> wrote about <a href=\"http:\/\/www.mikepope.com\/blog\/AddComment.aspx?blogid=1851\">card-shuffling<\/a>.<\/p>\n<p>By his own admission, he didn&#8217;t know the best way, and he described a number of sub-optimal solutions &#8211; generally O(n<sup>2<\/sup>) &#8211; but some had an unbounded worst case, and one displayed biases.<\/p>\n<p>Another commenter pointed to <a href=\"http:\/\/www.secureprogramming.com\/?action=view&#038;feature=recipes&#038;recipeid=23\">John Viega<\/a>&#8216;s solution, which assigned a random number to each card, sorted the result, and then reshuffled if no two random numbers were the same. It was on average about O(n.log n) but it had an unbounded worst case.<\/p>\n<p>So along I came, and ever so helpfully added a comment to the article with an algorithm I stole off a Commodore-64 program and have been using (very occasionally) for over 20 years. It is short, bounded, takes O(n), it has a low-constant time and a small memory footprint<\/p>\n<p>Pope came back to say he&#8217;s tried it, but he was not sure of the randomness. I wasn&#8217;t sure how to respond to that &#8211; it was obvious that it is completely random to me. I made a note to go back to leave another comment, but before I got a chance&#8230;<\/p>\n<p>&#8230; along came <a href=\"http:\/\/www.codinghorror.com\/blog\/\">Jeff Atwood at Coding Horror<\/a>, and <a href=\"http:\/\/www.codinghorror.com\/blog\/archives\/001008.html\">he waded in with a post<\/a>. (Actually, <a href=\"http:\/\/blogs.msdn.com\/ericlippert\/default.aspx\">Eric Lippert<\/a> argued against my algorithm first in a comment on the article, but I saw Jeff Atwood&#8217;s post before Eric Lippert&#8217;s comment.) Atwood brought up an algorithm very similar to the one that I had proposed, and then tried to shoot it down on two grounds.<\/p>\n<p>One, that it was too complicated. I didn&#8217;t feel that it was complicated at all. Then again, I have been using it for a while and it seems natural. Anyway, quicksort is more complicated than bubblesort, but you implement it once, and it&#8217;s done, right?<\/p>\n<p>The other was that its random number generator wasn&#8217;t secure enough. (There&#8217;s a very slight strawman here &#8211; my original didn&#8217;t mention the seeding of the random number generator, but (a) Atwood wasn&#8217;t trying to directly attack my solution, he was trying to attack a naive solution that he himself would have tried, and (b) Atwood&#8217;s solution wasn&#8217;t much different to the one I would have chosen, had I bothered to mention it.)<\/p>\n<p>My response to that was to grumble to myself about security experts who think every single project has security implications, resulting in terrible scope creep. Yes, if you are implementing an online casino, the security of randomisation  is a real problem. However, for a huge majority of implementations, it simply isn&#8217;t an issue. For a single player implementation of <a href=\"http:\/\/www.somethinkodd.com\/oddthinking\/2005\/06\/25\/the-finer-points-of-klondike\/\">Klondike<\/a> it isn&#8217;t important. My main use of card-shuffling is for <a href=\"http:\/\/www.somethinkodd.com\/oddthinking\/2005\/05\/31\/beating-the-clock-solitaire\/\">Monte Carlo simulations<\/a>. The idea that someone could crack the code and start predicting what was going to come next is irrelevant in these situations.<\/p>\n<p>If you have a choice between implementing securely or insecurely for the same price, obviously you should take the secure method &#8211; hey, you never know when your code will be re-used &#8211; but how much does the secure method cost?<\/p>\n<p>Atwood recommends generating a GUID per card, and sorting by that! Oh dear! Not only is it O(n.log n) but it has a huge constant time. My Monte Carlo simulations are going to be dominated by the card-shuffling, especially when testing a game like Blackjack with simplistic play and 416 card decks. I&#8217;ll stick with my algorithm, thanks!<\/p>\n<p>I made a note to go back to leave another comment, but before I got a chance&#8230;<\/p>\n<p>&#8230; Atwood posted another <a href=\"http:\/\/www.codinghorror.com\/blog\/archives\/001015.html\">follow-up<\/a> in which he called the algorithm I used &#8220;na\u00c3\u00afve&#8221;. He then quietly demonstrated that it wasn&#8217;t truly random at all. <\/p>\n<p>You could have knocked me down with a feather. I was completely wrong. Perhaps &#8220;na\u00c3\u00afve&#8221; is the word!<\/p>\n<p>My algorithm had biases &#8211; exactly the sort of biases that you <em>don&#8217;t<\/em> want in a Monte Carlo simulation.<\/p>\n<div class=\"aside\">Atwood points out that a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Knuth_shuffle\" title=\"Wikipedia definition of Knuth_shuffle\" class=\"wikipedia\">slightly different implementation<\/a> fixes the problem, and seems to offer the best of both worlds.<\/div>\n<p>In summary: I&#8217;ve been owned by Jeff Atwood. Eric Lippert owns a part-share of me, too.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In which Jeff Atwood dismisses my experience as &#8220;na\u00c3\u00afve&#8221;&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_s2mail":"","footnotes":""},"categories":[28,25,34],"tags":[189,191,190,90,188],"class_list":["post-450","post","type-post","status-publish","format-standard","hentry","category-doubleplus-geek","category-insufficiently-advanced-technology","category-software-development","tag-cards","tag-coding-horror","tag-randomness","tag-security","tag-shuffling"],"_links":{"self":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts\/450","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/comments?post=450"}],"version-history":[{"count":0,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts\/450\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/media?parent=450"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/categories?post=450"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/tags?post=450"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}