<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>EnigmaCurry &#187; Geek Humor</title>
	<atom:link href="http://www.enigmacurry.com/category/geek-humor/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.enigmacurry.com</link>
	<description>The Curry Enigma</description>
	<pubDate>Sun, 16 Nov 2008 16:15:27 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
	<language>en</language>
			<item>
		<title>My Hobby: Solving XKCD puzzles on my lunch break</title>
		<link>http://www.enigmacurry.com/2007/07/09/my-hobby-solving-xkcd-puzzles-on-my-lunch-break/</link>
		<comments>http://www.enigmacurry.com/2007/07/09/my-hobby-solving-xkcd-puzzles-on-my-lunch-break/#comments</comments>
		<pubDate>Mon, 09 Jul 2007 18:16:20 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
		
		<category><![CDATA[Geek Humor]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.enigmacurry.com/2007/07/09/my-hobby-solving-xkcd-puzzles-on-my-lunch-break/</guid>
		<description><![CDATA[I like geek comics. I especially like geek comics that have an embedded NP-Complete problem:


There are 2 solutions:
Solution #1:
        &#60;MenuItem Mixed Fruit 215&#62;
        &#60;MenuItem Hot Wings 355&#62;
        &#60;MenuItem Hot Wings 355&#62;
    [...]]]></description>
			<content:encoded><![CDATA[<p>I like geek comics. I <em>especially</em> like geek comics that have an <a href="http://xkcd.com/c287.html">embedded NP-Complete problem</a>:</p>
<p><img src="/blog-post-images/xkcd_np_complete.png" alt="XKCD July 9, 2007" title="General solutions get you a 50% tip." /></p>
<pre>
There are 2 solutions:
Solution #1:
        &lt;MenuItem Mixed Fruit 215&gt;
        &lt;MenuItem Hot Wings 355&gt;
        &lt;MenuItem Hot Wings 355&gt;
        &lt;MenuItem Sampler Plate 580&gt;
Solution #2:
        &lt;MenuItem Mixed Fruit 215&gt;
        &lt;MenuItem Mixed Fruit 215&gt;
        &lt;MenuItem Mixed Fruit 215&gt;
        &lt;MenuItem Mixed Fruit 215&gt;
        &lt;MenuItem Mixed Fruit 215&gt;
        &lt;MenuItem Mixed Fruit 215&gt;
        &lt;MenuItem Mixed Fruit 215&gt;
</pre>
<p>This isn&#039;t &#034;as fast as possible&#034; to be sure, but it should be a general solution.</p>
<pre lang="python">
#!/usr/bin/env python

"""Attempt to solve XKCD from July 9 2007"""

#All monetary values are in pennies to avoid floating point errors
# (Yea, I could use decimal.Decimal but it's SLOW!)

import operator

class MenuItem:
    def __init__(self, name, price):
        self.name = name
        self.price = price
    def __add__(self, other):
        if hasattr(other,"name") and hasattr(other,"price"):
            #This is a MenuItem
            return self.price + other.price
        else:
            return self.price + other
    def __repr__(self):
        return "<MenuItem %s %s>" % (self.name,self.price)

appetizers = ( MenuItem("Mixed Fruit",      215),
               MenuItem("French Fries",     275),
               MenuItem("Side Salad",       335),
               MenuItem("Hot Wings",        355),
               MenuItem("Mozarella Sticks", 420),
               MenuItem("Sampler Plate",    580))

target_price = 1505

def find_solutions(stack=[],solutions=set()):
    """Find combinations of appetizers that equal target_price"""
    #Find if initial stack equals target_price
    stack_price = sum([x.price for x in stack])
    if stack_price == target_price:
        #print("Found a solution!!! " + str(stack) + " == " + str(target_price))
        stack.sort(key=operator.attrgetter('price'))
        solutions.add(tuple(stack))
    elif stack_price > target_price:
        #No solutions for this stack
        return set()
    #Recurse for each item
    for item in appetizers:
        find_solutions(stack + [item])
    return solutions

if __name__ == "__main__":
    solutions = find_solutions()
    print "There are %d solutions:" % (len(solutions))
    solution_num = 1
    for solution in solutions:
        print "Solution #%d:" % (solution_num)
        for item in solution:
            print "\t%s" % item
        solution_num += 1
</pre>
<p><strong>Update July 10:</strong> Visitor wac pointed out that my program is pretty inefficient. I agree - I did it really quick on my lunch break yesterday. For order values above $20 it becomes an intractable solution pretty quick. Here is a much more efficient solution that implements value caching (at the cost of requiring more memory than the previous solution):</p>
<pre lang="python">
#!/usr/bin/env python

"""Attempt to solve XKCD from July 9 2007

This is a new version that uses a cache for calculations
"""

#All monetary values are in pennies to avoid floating point errors
# (Yea, I could use decimal.Decimal but it's SLOW!)

import operator
import sys

class MenuItem:
    def __init__(self, name, price):
        self.name = name
        self.price = price
    def __add__(self, other):
        if hasattr(other,"name") and hasattr(other,"price"):
            #This is a MenuItem
            return self.price + other.price
        else:
            return self.price + other
    def __repr__(self):
        return "<MenuItem %s %s>" % (self.name,self.price)

appetizers = ( MenuItem("Mixed Fruit",      215),
               MenuItem("French Fries",     275),
               MenuItem("Side Salad",       335),
               MenuItem("Hot Wings",        355),
               MenuItem("Mozarella Sticks", 420),
               MenuItem("Sampler Plate",    580))

class OrderCache:
    """a cache of all the possible variations of an order for a given price"""
    def __init__(self):
        self.cache = {0:set([()])} # price -> set([(item1,item2 ...), ...])
    def derrive_order(self, price):
        "Return all combinations for a given price"
        try:
            return self.cache[price]
        except KeyError:
            orders = set()
            for item in appetizers:
                if price - item.price >= 0:
                    for order in self.derrive_order(price - item.price):
                        new_order = list(order) + [item]
                        new_order.sort(key=operator.attrgetter('price'))
                        orders.add(tuple(new_order))
            self.cache[price] = orders
            return orders

if __name__ == "__main__":
    if len(sys.argv) == 2:
        target_price = int(sys.argv[1])
    else:
        target_price = 1505
    order_cache = OrderCache()
    solutions = order_cache.derrive_order(target_price)
    print "There are %d solutions:" % (len(solutions))
    solution_num = 1
    for solution in solutions:
        print "Solution #%d:" % (solution_num)
        for item in solution:
            print "\t%s" % item
        solution_num += 1
</pre>
<p>With the improved version I can calculate order values up to $75 in under a minute. That&#039;s interesting in and of itself really, because although the second algorithm is <strong><em>much</em></strong> more efficient it would still be practically impossible to calculate an order value of $1000. That&#039;s the nature of NP problems for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.enigmacurry.com/2007/07/09/my-hobby-solving-xkcd-puzzles-on-my-lunch-break/feed/</wfw:commentRss>
		</item>
		<item>
		<title>LOLPython</title>
		<link>http://www.enigmacurry.com/2007/06/06/100/</link>
		<comments>http://www.enigmacurry.com/2007/06/06/100/#comments</comments>
		<pubDate>Wed, 06 Jun 2007 20:17:45 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
		
		<category><![CDATA[Geek Humor]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.enigmacurry.com/2007/06/06/100/</guid>
		<description><![CDATA[
IN MAI time GIMME localtime LIKE TIMEZOR

IZ __name__ KINDA LIKE "__main__"?
    VISIBLE "YOUZ GOT CHEEZBURGERS?"
    CATURDAY CAN HAS FIV
    TODAYZ CAN HAS TIMEZOR THING LOOK AT SIKS!
    YOUGOTZ CAN HAS raw_input THING
    IZ YOUGOTZ OWN lower THING KINDA LIKE "yes"?
 [...]]]></description>
			<content:encoded><![CDATA[<pre lang="python">
IN MAI time GIMME localtime LIKE TIMEZOR

IZ __name__ KINDA LIKE "__main__"?
    VISIBLE "YOUZ GOT CHEEZBURGERS?"
    CATURDAY CAN HAS FIV
    TODAYZ CAN HAS TIMEZOR THING LOOK AT SIKS!
    YOUGOTZ CAN HAS raw_input THING
    IZ YOUGOTZ OWN lower THING KINDA LIKE "yes"?
        IZ TODAYZ KINDA LIKE CATURDAY?
            MYLOOPZ CAN HAS THR33
            WHILE I CUTE?
                VISIBLE "TODAYZ CATURDAY! I GETZ ALL YOUS CHEEZBURGERS!"
                MYLOOPZ THROWZ AWAY ONCE
                IZ MYLOOPZ SMALL LIKE EASTERBUNNY?
                    KTHXBYE
        NOPE?
            VISIBLE "O RLY? CAN I HAS YOUS CHEEZBURGER?"
    NOPE?
        VISIBLE "I SAW WHAT YOU DID, YOU ATE MY CHEEZBURGERS!"
</pre>
<p>Yea, you&#039;re probably saying to yourself, <em><strong>&#034;WTF IS THAT?&#034;</strong></em></p>
<p>It&#039;s <a href="http://www.dalkescientific.com/writings/diary/archive/2007/06/01/lolpython.html">LOLPython</a>, the geekiest, funniest thing I&#039;ve seen all week!</p>
<p>The LOLPython interpreter translates a variation of <a href="http://lolcode.com/">LOLCode</a> into standard python. <a href="http://lolcode.com/">LOLCode</a> itself is pretty neat, but because LOLPython is based on Python, it automatically inherits all of the Python library too. Here&#039;s the above code after translation:</p>
<pre lang="python">
from time import localtime as TIMEZOR
if __name__ == '__main__' :
    print 'YOUZ GOT CHEEZBURGERS?'
    CATURDAY = 5
    TODAYZ = TIMEZOR ()[ 6 ]
    YOUGOTZ = raw_input ()
    if YOUGOTZ . lower ()== 'yes' :
        if TODAYZ == CATURDAY :
            MYLOOPZ = 3
            while 1:
                print 'TODAYZ CATURDAY! I GETZ ALL YOUS CHEEZBURGERS!'
                MYLOOPZ -= 1
                if MYLOOPZ <= 0 :
                    break
        else :
            print 'O RLY? CAN I HAS YOUS CHEEZBURGER?'
    else :
        print 'I SAW WHAT YOU DID, YOU ATE MY CHEEZBURGERS!'
</pre>
<p><center><br />
<a href="http://icanhascheezburger.com/2007/02/16/newb1/"><img id="image101" src="http://www.enigmacurry.com/wp-content/uploads/2007/06/You%20have%20to%20push%20start%20newb.jpg" alt="1337 Cat Tellin like it is" /></a></center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.enigmacurry.com/2007/06/06/100/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Yep, I&#039;m a nerd</title>
		<link>http://www.enigmacurry.com/2006/01/11/yep-im-a-nerd/</link>
		<comments>http://www.enigmacurry.com/2006/01/11/yep-im-a-nerd/#comments</comments>
		<pubDate>Wed, 11 Jan 2006 19:36:36 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
		
		<category><![CDATA[Geek Humor]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.enigmacurry.com/?p=41</guid>
		<description><![CDATA[I was just reading today&#039;s Foxtrot.

Check this out:

bin = ['01011001','01001111','01010101',
       '01001110','01000101','01010010','01000100']
for b in bin:
   print chr(int(b,2)),

I Love comics that are made just for me. 
]]></description>
			<content:encoded><![CDATA[<p>I was just reading today&#039;s <a href="http://www.ucomics.com/foxtrot/2006/01/11/">Foxtrot</a>.<br />
<center><img id="image102" src="http://www.enigmacurry.com/wp-content/uploads/2007/06/foxtrot060111.gif" alt="foxtrot060111.gif" /></center><br />
Check this out:</p>
<pre lang="python">
bin = ['01011001','01001111','01010101',
       '01001110','01000101','01010010','01000100']
for b in bin:
   print chr(int(b,2)),
</pre>
<p>I Love comics that are made just for me. <img src='http://www.enigmacurry.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.enigmacurry.com/2006/01/11/yep-im-a-nerd/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
