{"id":502,"date":"2011-06-27T09:16:05","date_gmt":"2011-06-27T17:16:05","guid":{"rendered":"http:\/\/www.madpickles.org\/rokjoo\/?p=502"},"modified":"2012-08-24T16:59:57","modified_gmt":"2012-08-25T00:59:57","slug":"big-double-cheddar-mac-beef-down","status":"publish","type":"post","link":"https:\/\/www.madpickles.org\/rokjoo\/2011\/06\/27\/big-double-cheddar-mac-beef-down\/","title":{"rendered":"Big Double Cheddar Mac Beef Down"},"content":{"rendered":"<p>Every now and then it&#8217;s useful to challenge oneself, to grow, to stretch. A couple of months ago, a friend of mine noticed a McDonalds, Kentucky Fried Chicken and Arby&#8217;s within spitting distance of each other, a trifecta of sorts. Then came the eureka moment, where he envisioned combining a Big Mac, Double Down and Beef &#8216;n Cheddar into the greatest fast food sandwich imaginable.<\/p>\n<p><a title=\"Supplies by madpickles, on Flickr\" href=\"http:\/\/www.flickr.com\/photos\/madpickles\/5866439651\/\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/farm7.static.flickr.com\/6036\/5866439651_1dfef9d001.jpg\" alt=\"Supplies\" width=\"339\" height=\"500\" \/><\/a><\/p>\n<p>The supplies (we put some fries into the sandwich for good measure).<\/p>\n<p><a title=\"Three Main Ingredients by madpickles, on Flickr\" href=\"http:\/\/www.flickr.com\/photos\/madpickles\/5866439693\/\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/farm6.static.flickr.com\/5240\/5866439693_2c16bae588.jpg\" alt=\"Three Main Ingredients\" width=\"500\" height=\"208\" \/><\/a><\/p>\n<p>The main ingredients, from left to right, Big Mac, Double Down, Beef &#8216;n Cheddar.<br \/>\n<!--more--><br \/>\n<a title=\"Big Double Cheddar Mac Beef Down by madpickles, on Flickr\" href=\"http:\/\/www.flickr.com\/photos\/madpickles\/5866439735\/\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/farm4.static.flickr.com\/3076\/5866439735_4249d2b27f.jpg\" alt=\"Big Double Cheddar Mac Beef Down\" width=\"233\" height=\"500\" \/><\/a><\/p>\n<p>Assembly complete.<\/p>\n<p>At this point, you might be wondering what nutritional value this behemoth contains, so I&#8217;ve compiled it below using the official <a rel=\"nofollow\" href=\"http:\/\/www.arbys.com\/menu\/roast-beef\/regular-beef-ncheddar.html\" target=\"_blank\">Arby&#8217;s Menu<\/a>, <a rel=\"nofollow\" href=\"http:\/\/nutrition.mcdonalds.com\/nutritionexchange\/nutritionfacts.pdf\" target=\"_blank\">McDonalds Nutrition Facts<\/a> and <a rel=\"nofollow\" href=\"http:\/\/www.kfc.com\/nutrition\/pdf\/kfc_nutrition.pdf\" target=\"_blank\">KFC Nutrition Information<\/a>. The % daily values are based off of the <a href=\"http:\/\/www.fda.gov\/Food\/GuidanceComplianceRegulatoryInformation\/GuidanceDocuments\/FoodLabelingNutrition\/FoodLabelingGuide\/ucm064928.htm\" target=\"_blank\">US FDA Reference Daily Intake<\/a> of a 2,000 calorie diet.<\/p>\n<p><iframe loading=\"lazy\" src=\"https:\/\/spreadsheets.google.com\/spreadsheet\/pub?hl=en_US&#038;hl=en_US&#038;key=0AithY_dqztjXdG1BNGROcHFNWnZxSnVNUV9hZXg2dlE&#038;single=true&#038;gid=0&#038;output=html\" width=\"1255\" height=\"230\" style=\"border: 0px;\"><\/iframe><\/p>\n<p>I was shocked, I figured I would at least be consuming 1,500 calories and more than 100% of the daily value in several categories. As it turns out, compared to the <a href=\"http:\/\/www.dailyspark.com\/blog.asp?post=top_10_list_the_worst_restaurant_salads_you_may_be_eating\" target=\"_blank\">10 Worst Restaurant Salads<\/a>, this sandwich would rank 2nd by sodium, but only 5th by calories and 10th by total fat! In fact, with a bit less sodium I would consider the Beef &#8216;n Cheddar healthy. Percentage wise, it&#8217;s actually the protein content which is furthest from the norm.<\/p>\n<p><a title=\"One Bite At A Time by madpickles, on Flickr\" href=\"http:\/\/www.flickr.com\/photos\/madpickles\/5866992386\/\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/farm6.static.flickr.com\/5069\/5866992386_128ded3b1b.jpg\" alt=\"One Bite At A Time\" width=\"375\" height=\"500\" \/><\/a><\/p>\n<p>An action shot.<\/p>\n<p><a title=\"In Progress by madpickles, on Flickr\" href=\"http:\/\/www.flickr.com\/photos\/madpickles\/5866992468\/\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/farm4.static.flickr.com\/3082\/5866992468_3f37da9697.jpg\" alt=\"In Progress\" width=\"375\" height=\"500\" \/><\/a><\/p>\n<p>Slow and steady.<\/p>\n<p>My friend finished his sandwich quite a few minutes before I did. The final 5 bites or so were tough, but in the end I too prevailed. However, a part of me still felt empty inside&#8230;we had not come up with a good name for the creation. I thought some permutation of the words in the sandwich names would pop out as an obvious choice, but that didn&#8217;t happen. In the end I decided to write a script to generate all the permutations (leaving out the &#8216;n &#8220;word&#8221;) which left me with 6! (720) possibilities. My first version was recursive and looked like this (thanx <a href=\"http:\/\/harryterkelsen.com\/\" title=\"Harry Terkelsen\" target=\"_blank\">Harry Terkelsen<\/a> for pointing out my boneheaded use of append where I should have used insert):<\/p>\n<pre>#!\/usr\/bin\/python\r\n\r\nimport sys\r\n\r\ndef permute(l):\r\n  if len(l) == 2:\r\n    original = list(l)\r\n    l.reverse()\r\n    return [original, l]\r\n\r\n  accumulated_permutations = []\r\n  for x in xrange(len(l)):\r\n    element = l[0]\r\n    permutations = permute(l[1:])\r\n    for permutation in permutations:\r\n      permutation.insert(x, element)\r\n    accumulated_permutations.extend(permutations)\r\n\r\n  return accumulated_permutations\r\n\r\ndef main(argv):\r\n  name_permutations = permute(['big', 'mac', 'double', 'down', 'beef', 'cheddar'])\r\n  for x in name_permutations:\r\n    print ' '.join(x)\r\n\r\nif __name__ == '__main__':\r\n  main(sys.argv)<\/pre>\n<p>That certainly worked, but a part of me wasn&#8217;t happy with the algorithm. It created an awful lot of new lists and generated the entire result set in memory before returning. If I ever wanted to push myself and combine 5 sandwiches where each name was a bigram (permute 10 words) it would take my computer 23 seconds (and 600M+ of RAM) to generate all 10! combinations. With 6 sandwiches (12 words) after 21 minutes my computer had used up 8GB of RAM and still wasn&#8217;t finished. Clearly it would be better to create some sort of iterator or generator to yield permutations as needed. Even better would be to have a method of requesting ranges of permutations as I could then use multiple computers in parallel to generate them and merge the results at the end.<\/p>\n<p>After some more thought I remembered reading about an interesting method of computing permutations based on patterns in <a href=\"http:\/\/hop.perl.plover.com\/book\/\" target=\"_blank\">Higher-Order Perl<\/a> and after a little more tweaking I had a parallelizable set of functions:<\/p>\n<pre>\r\n#!\/usr\/bin\/python\r\n\r\nimport sys\r\n\r\n\r\ndef nth_pattern(n, size):\r\n  \"\"\"Get the Nth pattern for a permutation of a given size.\"\"\"\r\n  pattern = []\r\n  for i in xrange(1, size + 1):\r\n    pattern.insert(0, n % i)\r\n    n = n \/ i\r\n  if n:\r\n    return []\r\n  else:\r\n    return pattern\r\n\r\n\r\ndef pattern_to_permutation(pattern, items):\r\n  \"\"\"Generate a permutation of items based on the pattern.\"\"\"\r\n  items = items[:]\r\n  r = []\r\n  for x in pattern:\r\n    r.append(items.pop(x))\r\n  return r\r\n\r\n\r\ndef permute(items, start_n, end_n):\r\n  \"\"\"Generate the range of permutations of items between start_n and end_n.\"\"\"\r\n  size = len(items)\r\n  while start_n &lt; end_n:\r\n     pattern = nth_pattern(start_n, size)\r\n     if not pattern:\r\n       break\r\n     result = pattern_to_permutation(pattern, items)\r\n     yield result \r\n    start_n += 1\r\n\r\n\r\ndef factorial(n):\r\n  \"\"\"Compute n!.\"\"\"\r\n  total  = 1\r\n  while n > 1:\r\n    total = total * n\r\n    n -= 1\r\n  return total\r\n\r\n\r\ndef main(argv):\r\n  \"\"\"Main driver which could be easily transformed into a MapReduce.\"\"\"\r\n  names = ['big', 'mac', 'double', 'down', 'beef', 'cheddar']\r\n  num_permutations = factorial(len(names))\r\n  num_machines = argv[1]  # Number of machines to use in parallel.\r\n  end_n = 0\r\n  for machine in xrange(num_machines):\r\n    size = num_permutations \/ num_machines\r\n    start_n = machine * size\r\n    end_n = (machine + 1) * size\r\n    # This would be an asynchronus  RPC if truely running in parallel.\r\n    p = permute(names, start_n, end_n)\r\n\r\n  # In case we have some leftover work\r\n  if end_n &lt; num_permutations:\r\n   p = permute(names, end_n + 1, num_permutations)\r\n\r\n\r\nif __name__ == '__main__':\r\n  main(sys.argv)\r\n<\/pre>\n<p>The parallizeable version also lends itself to random permutation requests e.g. should I ever visit McDonalds, Kentucky Fried Chicken, Arby&#8217;s, Taco Bell, Burger King, Carl&#8217;s Jr. and In-N-Out:<\/p>\n<pre>\r\nnames = ['big', 'mac', 'double', 'down', 'beef', 'cheddar', 'gordita', 'supreme', 'whopper', 'western', 'bacon', 'animal', 'style']\r\nnum_permutations = factorial(len(names))\r\nx = random.randint(0, num_permutations)\r\np = permute(names, x, x + 1)[0]\r\nfor permutation in p:\r\n  print permutation\r\n<\/pre>\n<p>I might order a: Double Bacon Down Whopper Gordita Mac Animal Big Cheddar Supreme Western Beef Style!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every now and then it&#8217;s useful to challenge oneself, to grow, to stretch. A couple of months ago, a friend of mine noticed a McDonalds, Kentucky Fried Chicken and Arby&#8217;s within spitting distance of each other, a trifecta of sorts. Then came the eureka moment, where he envisioned combining a Big Mac, Double Down and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[4,16,11,17],"_links":{"self":[{"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/posts\/502"}],"collection":[{"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/comments?post=502"}],"version-history":[{"count":42,"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/posts\/502\/revisions"}],"predecessor-version":[{"id":541,"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/posts\/502\/revisions\/541"}],"wp:attachment":[{"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/media?parent=502"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/categories?post=502"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.madpickles.org\/rokjoo\/wp-json\/wp\/v2\/tags?post=502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}