Writinghttp://blog.sitongpeng.com/2018-05-16T03:15:00-07:00How would you have a machine recognize a cat?2018-05-16T03:15:00-07:002018-05-16T03:15:00-07:00Sitong Pengtag:blog.sitongpeng.com,2018-05-16:/posts/how-would-you-have-a-machine-recognize-a-cat.html<p>How machine learning is changing how we program machines</p><p>I wrote my first computer program in college. It was, surprisingly, not “Hello World”, but typing the number “6” into a Scheme interpreter prompt. You can see how Scheme responded below.</p>
<div class="highlight"><pre><span></span>> 6
6
</pre></div>
<p>This may seem uninspiring but it was the first time I spoke to a computer, using a language we both could commonly understand. In fact, even though I was dutifully copying examples from my textbook, I distinctly remember feeling like I was having a conversation with my computer. I believe this feeling belies the core of what programming is: <em>communicating and delegating to a machine</em>.</p>
<p>At the time, I thought what needed to be communicated was a precise set of instructions on how I wanted the machine to complete a task. And before I could write the instructions, I had to thoroughly understand how I would personally complete the task. It was only then that I could tell a machine how to complete it. After all, machines were drones, they didn’t have their own minds, they just followed orders. Machines were an extension of myself, just with greater calculating power over a shorter time frame.</p>
<h2>Fast forward to today, some things are changing.</h2>
<p>I still write plenty of programs that specifically codify exactly how I want a machine to complete a task. To be frank it’s quite belittling toward machines. Imagine you walked into work every morning to your boss handing you a many paged document describing exactly how they want your day to go.</p>
<div class="highlight"><pre><span></span>You are to write up a presentation with exactly 12 slides, don’t use Google Docs use that new software we just bought that you hate, if Steve from Sales walks by your cubicle and wants to talk about fantasy football you are to ignore him, oh and make sure you clock out exactly at 5PM because the company doesn’t want to pay any more overtime.
</pre></div>
<p>It’d be a nightmare to work for such a boss, I’m certain I’d quit within the first week. We all want to work with a boss that’s better at delegating tasks, one that lets us exercise our creativity on how to best complete a task without assuming we are incompetent. Why don’t we give machines a similar courtesy?</p>
<p>Of course, we still need to provide clear and exact instructions to machines. But instead of telling them how to complete a task, we can tell them how to approach a task.</p>
<div class="highlight"><pre><span></span>We need to reach our quarterly profit goals. Here is a manual describing the experiments we ran in past quarters and how our profit changed. Figure out what to do with the data from our current quarter. And I’ll be honest with you, I have no idea what need to do to reach this goal, but I know you are efficient and calculating, I believe in you.
</pre></div>
<p>This approach to programming is machine learning in a nutshell (specifically supervised learning). The programmer can push the responsibility of domain knowledge to the machine, and instead focus on providing tools (data) and instructions on how to use these tools. This is a powerful idea because it means we’ll be able to leverage machines to accomplish tasks we don’t have the resources/training to do ourselves.</p>
<p>My first machine learning program was a cat classifier (this is the “Hello World” equivalent for machine learning). Essentially the program receives possible cat images and, using nothing but the RGB values of each pixel of it image, the program decides whether the photo contains a cat. It ended up having an 80% success rate on a test data set I used. Now, while it’s true that I could probably get at least a 99% success rate in classifying cat photos (accounting for some misclicks), I’m certain any explicit program I might write would operate at much worse than 80% accuracy. I wouldn’t even know where to start. A cat has pointy ears, but what are pointy ears, in fact, how do I describe what an ear looks like? How are pointy cat ears different from pointy mouse ears? Imagine having to describe what a cat looks like to a baby. You’d probably end up pointing out cats in real life until the baby learned itself through recognizing the patterns, a remarkably similar strategy to how we implement machine learning :).</p>
<p><span class="note">Now, you might be wondering how exactly a machine learns without a human explicitly teaching it how to do the task. Stick around, that’ll be the topic of an upcoming post :).</span></p>Artificial Intelligence, Machine Learning, and Deep Learning - What's the difference?2018-05-08T23:15:00-07:002018-05-08T23:15:00-07:00Sitong Pengtag:blog.sitongpeng.com,2018-05-08:/posts/ai-ml-dl-whats-the-difference.html<p>Quick explanation of the difference between AI, ML, and DL</p><p>This is the first question I had when I first started exploring these subjects a month ago. I have a better grasp on the terms now, so let's delve in.</p>
<h2>Artificial Intelligence</h2>
<p>I think generally when people think about Artificial Intelligence (AI), they think of Artificial General Intelligence (AGI), or the ability of a non-biological entity to be able to successfully perform a wide variety of tasks at a human level (or better) proficiency. This contrasts with narrow AI, which can perform specific tasks at human proficiency. We already have examples of narrow AI in everyday life, like in our personal phone or home assistants, self driving cars, or AlphaGo. We don’t, however, have any examples of AGI yet and there is no consensus as to when that might occur, but the holy grail of AI research is toward the development of human level AGI, with the possibility that super intelligent AI wouldn’t be very far behind.</p>
<h2>Machine Learning</h2>
<p>Machine learning is a field in which machines are trained to develop algorithms to perform a task. This field flies in the face of traditional programming, in which humans assemble the algorithms and program machines to compute them. In machine learning, humans provide the training data (inputs that lead to certain outcomes) and program machines to determine how certain inputs will lead to certain outcomes. This is a powerful paradigm because it frees humans from needing to know how to get to the outcomes themselves, they just need to provide enough training data for a machine to figure out how a certain combination of inputs can lead to an outcome. For instance, if the task at hand is to catch a fish, traditional programming would teach a machine how to use a fishing rod - how to hold the rod, how to release the spool, how to cast a line. Machine learning would give a machine a library of videos showing people succeeding or failing to catch fish, leaving it up to the machine to go through each video and determine/learn how to catch a fish . Perhaps certain casting techniques are better than others, or maybe the weather plays a big role, the machine might pick up on patterns a human doesn't even think consider.</p>
<h2>Deep Learning</h2>
<p>Deep learning is subset of machine learning in which the machine’s learning style is loosely based on the neural wirings of a biological brain. That is, the machine is programmed to replicate how brains learn, via an artificial neural network. I’ll talk about that further in a subsequent post, but these neural networks will have many layers of "neurons" that explore many possible pathways for a set of inputs to end up as a set of outcomes. What's fascinating is that it's very hard to analyze these neural nets since they are essentially a jumble of weights that calculate patterns in input data. Take an artificial neural net (ANN) that can recognize if a cat is in a photo. For humans, we identify cats via features we deem catlike (pointed ear, furry bodies, whiskers). An ANN might notice that some group of pixels relates to some other group of pixels in a way that suggests a cat is there, but to a human this just looks like a bunch of math and data. For all we know, the ANN may come up with a more precise way to recognize cats that no human has ever thought of, some subtle pattern that renders simple feature recognition (it has a cheezburger?) obsolete.</p>
<p>Anyways it's all pretty exciting stuff and I'm looking forward to breaking past my surface level knowledge of deep learning, machine learning, and AI. One question answered, many more to go.</p>
<h2>Spelling Bee Tldr;</h2>
<p><p class="quote">Deep learning is a technique in the field of machine learning that advances us closer to creating artificial general intelligence.</p></p>Back to the learning grind2018-05-07T23:45:00-07:002018-05-07T23:45:00-07:00Sitong Pengtag:blog.sitongpeng.com,2018-05-07:/posts/back-to-the-learning-grind.html<p>Introductory post about future machine learning posts</p><p>It’s been a long time coming, but I’m finally getting around to learning about machine learning. I’m hoping to get a better idea of what artificial general intelligence (AGI) could look like in the future and how that might affect the life I know.</p>
<p>As a first step I’m currently working through Andrew Ng’s <a href="https://www.coursera.org/specializations/deep-learning">Deep Learning</a> course to get my feet wet with some of the technical challenges of machine learning as well as reading Max Tegmark’s <a href="https://www.amazon.com/Life-3-0-Being-Artificial-Intelligence/dp/1101946598/">Life 3.0: Being Human in the Age of Artificial Intelligence</a> to get a grasp on potential big picture ideas about machine learning.</p>
<p>It’s my plan to keep a weekly log of things I’m learning as a way of organizing my thoughts. Wish me luck!</p>What's coming up 20172017-01-03T23:30:00-08:002017-01-03T23:30:00-08:00Sitong Pengtag:blog.sitongpeng.com,2017-01-03:/posts/whats-coming-up-2017.html<p>Talking about resolutions for 2017</p><ol>
<li>Read 18 books, at least 3 nonfiction.<br>
<span class="note">I’ve always averaged 5 books/year but I’d like to make reading more of a priority this year.</span></li>
<li>Commit to a longer side project (At least 3 months).<br>
<span class="note">I have at least one in mind :)</span></li>
<li>Accomplish two physical milestones.<br>
<span class="note">Potential examples: train for another run or swim or bike race, complete a major hike/trek, do a muscle up, etc...</span></li>
<li>Accomplish two creative milestones.<br>
<span class="note">Potential examples: getting better at freestyle hip hop, art, music, or even food composition/plating.</span></li>
</ol>
<p>Can't wait.</p>Resolving 20162017-01-02T21:30:00-08:002017-01-02T21:30:00-08:00Sitong Pengtag:blog.sitongpeng.com,2017-01-02:/posts/resolving-2016.html<p>Going over my 2016 resolutions</p><p><img alt="Torrey Pines State Beach" src="https://raw.github.com/stoneG/stoneg.github.com/master/images/tpstatebeach.jpg"></p>
<p>Let's go over my 2016 <a href="/posts/coming-up-in-2016.html">resolutions</a>:</p>
<p class="quote">"Ship something in virtual reality"</p>
<p>I made a scene in VR but nothing worth sharing or shipping. This resolution fell to the wayside since I was waiting for the touch controllers to come out. I also started some work on a 2D project. I might prefer 2D.</p>
<p class="quote">"Write 8 posts worthy of reading"</p>
<p>Well, it sure is rough to have fallen short on the first two resolutions. This one was related to the first, as I was planning on writing about things I learned in VR.</p>
<p class="quote">"Hike at two national parks, preferably new"</p>
<p>Hiked at Arches, Joshua Tree, Banff, Mt. Rainier, Crater Lake. Each park was deeply inspiring in its own way and I continue to feel lucky and humbled upon every visit. To get a feel for what I saw, check out my <a href="https://instagram.com/stoneG">instagram</a>.</p>
<p class="quote">“Live in a foreign country that's new to me"</p>
<p>I spent March living in Budapest. I had an amazing time in that city. Solo travel has shown me how much I care about human relationships. So it's exceedingly ironic that where I expected to find independence, I instead found how I crave the vulnerability of dependence.</p>
<p class="quote">“Develop a fluidity in the kitchen so most dishes I make are served on time"</p>
<p>I prepared somewhere between one to two handfuls of multiple course dinner parties (~6 people each time). And most were ready to go by the time the last guest arrived!</p>
<p class="quote">Be able to name all common herbs & spices by sight & smell"</p>
<p>TBD, I need to test myself and get this on tape.</p>
<p class="quote">"Accomplish at least two physical goals for surfing, snowboarding, skiing, or weightlifting"</p>
<p><em>Surfing</em>: After many youtube videos and lots of trial and error, I'm proud to say I can usually get up on the board, albeit sometimes only briefly before falling. I still need to work on my speed and foot placement.</p>
<p><em>Snowboarding</em>: I definitely progressed from beginner/intermediate to intermediate/advanced levels. I’m good enough to mess around on jumps at the terrain park and I can get some good speed on downhill runs.</p>
<p><em>Bonus physical goal</em>: I went from the couch to a half marathon this year :)</p>
<h2>All in all: 4 to 5 resolutions of 7.</h2>Dear Toronto,2016-01-08T12:00:00-08:002016-01-08T12:00:00-08:00Sitong Pengtag:blog.sitongpeng.com,2016-01-08:/posts/dear-toronto.html<p>A letter to the people I met in Toronto</p><p>I have a few things to say to the people I met in a city I wasn't sure I would like.</p>
<p><img alt="Toronto at night" src="https://raw.github.com/stoneG/stoneg.github.com/master/images/toronto.jpg"></p>
<p><strong>You</strong>, the pakistani man who makes butter chicken roti at your strangely NYC themed restaurant, who passably decorated it by throwing up old LIFE magazine covers on the walls, who has family trouble in California and a cousin doing a stint in our penal system.</p>
<p><strong>You</strong>, the pupusa lady that gave me an extra tamale on the house after I had such a hard time deciding which pupusas and tamale flavors I wanted to try, who then laughed when I immediately came back to order the fried plantains, which I saw while waiting for my order (they weren't on the menu I agonized over).</p>
<p><strong>You</strong>, the guy bumping to <em>Hotline Bling</em> outside your car that I grooved with, but politely had to decline your offer of a cigarette, because I had gone through D.A.R.E. three times as a kid.</p>
<p><strong>You</strong>, the roommate who was once a kingpin of street fighter arcade sticks as well as an elite Canadian memory champion, who is unfazed by face transplant images that made me jump out of my chair, who upon learning I was leaving Toronto without seeing Niagara Falls rented a car and drove us out there at midnight.</p>
<p><strong>You</strong>, the roommate who is a sound mixing engineer that did a tour of duty in Nashville but somehow managed to work on rock instead of country, who showed me the process for modern sound mixing using Britney Spears’ <em>I'm a Slave For You</em> (dozens of vocal tracks!), who stood in the hallway with me until 3am because we had delved too deep into our opinions about movies & games for sleep to matter anymore.</p>
<p><strong>You</strong>, the roommate who is polyglot that’s lived in many different countries, who works harder to balancing work and school than most anyone I've met, who still had the energy to unabashedly start dancing the one time I casually panned you into my snapchat video.</p>
<p><strong>You</strong>, the girl with an excitement that is palpable, contagious, and hard to forget, who unquestioningly shared your hopes and dreams to a complete stranger who slid into your DMs, who despite living there your whole life, seemed somehow less familiar with directions in Toronto than me.</p>
<p><strong>You</strong>, the guy who has not ventured out of Montreal for over 35 years, but gave me change for the bus and humored me while I chatted you up about how your city's bagels had ruined me for life.</p>
<p><strong>You all made me feel odd, like I was leaving a place that had become a home.</strong></p>
<p>Sincerely,</p>
<p>Confused in California.</p>Coming up in 20162016-01-06T20:00:00-08:002016-01-06T20:00:00-08:00Sitong Pengtag:blog.sitongpeng.com,2016-01-06:/posts/coming-up-in-2016.html<p>My plans for what is coming up in 2016</p><p>It’s been a few years since I’ve done this <a href="/posts/programming-resolutions.html">publicly</a>, but I’d like to bring this tradition back. Learning from past experiences, I’m keeping this list concise and specific. Life can sometimes get in the way but here’s what I’m agreeing to in 2016:</p>
<ol>
<li>Ship something in virtual reality.</li>
<li>Write 8 posts worthy of reading.</li>
<li>Hike at two national parks, preferably new.</li>
<li>Live in a foreign country that's new to me.</li>
<li>Develop a fluidity in the kitchen so most dishes I make are served on time.</li>
<li>Be able to name all common herbs & spices by sight & smell.</li>
<li>Accomplish at least two physical goals for surfing, snowboarding, skiing, or weightlifting.</li>
</ol>
<p>Time's ticking.</p>Refocusing2016-01-06T01:00:00-08:002016-01-06T01:00:00-08:00Sitong Pengtag:blog.sitongpeng.com,2016-01-06:/posts/refocusing.html<p>Going over my 2013 resolutions</p><p>Before I release the 2016 ones, here are my last set of resolutions from <a href="/posts/programming-resolutions.html">2013</a>:</p>
<p class="quote">"100 posts about programming things I’ve encountered and want to share"</p>
<p>Rode the new years train a bit too hard on this one. Even without life getting in the way, this would have been a tough one to keep, but glad I managed even 14 posts even if 13 came in the first half of the year.</p>
<p class="quote">"Contribute a couple patches or a bug fix to an open source project."</p>
<p>To my credit, I did make a very small contribution to Django REST Framework as well as other smaller repositories. Work and personal projects have always gotten the best of me. I’ve since forked projects and made features I’ve needed but I’ve always been too lazy to properly submit pull requests with tests.</p>
<p class="quote">"Do a weekend project and get it on the front page of HN"</p>
<p>In retrospect, it seems silly to make a project with the explicit intention of making the HN front page. No wonder this is the resolution I remember making the least. I suspect many developers have fallen into the same trap, but I have numerous projects that are anywhere from 50% to 80% complete. Shipping products is an art.</p>
<p class="quote">“Read more books: I need to expand my knowledge beyond just reading the news and blogs"</p>
<p>By my count, I’ve read around 18 books since then. Paltry, to be sure, but not nothing.</p>A little about push2014-02-02T23:30:00-08:002014-02-02T23:30:00-08:00Sitong Pengtag:blog.sitongpeng.com,2014-02-02:/posts/a-little-about-push.html<p>A little about iOS push notifications.</p><p>Last year I had the chance to take some time and get a better understanding of how push notifications work for iOS applications. But before I talk about that, it helps to understand why push notifications exist in the first place.</p>
<p>Apple developed iOS as a closed platform operating system. The source code is mostly closed except for the publicly available portions that developers use in networking programming or to interface with the camera or all the other fancy things that apps do. One of the most important design decisions made at Apple was to heavily restrict the capabilities of daemonized apps (apps running in the background). In fact, Apple's guidelines explicitly state that only apps such as music players, VoIP clients, and GPS navigation systems are allowed to run background tasks. That essentially means that once a user leaves your app, you're dead in the water until the user decides to tap your lovely retina icon again... at least that would have been the case if it weren't for push notifications.</p>
<p>Push notifications exist for the express purpose of letting applications pull users back into their experience. They're basically shouting "Hey, look at me, I have something to show you!"</p>
<p>The life of a push notification starts on an application. The application will ask iOS for a unique device token that identifies the device, sort of like an IP address. As you'd imagine, it's pretty important to know the address of the device you want to send something to. The operating system doesn't have this information regularly, it actually makes a request to the Apple Push Notification Service (APNS), which divulges a unique token for that specific iOS build on that specific device. The application should then pass the token to its backend server (this is the thing that I've been working on at <a href="https://www.myeatclub.com">EAT Club</a>).</p>
<p>Once you want to send a push notification to a specific user (for instance, a "Your food is ready for pickup!" notification that we send to users who have ordered a meal that day), just pluck that device token out of your database table and pass it to your push server to fire off to APNS. There are also third parties that exist as the middle man push server between your backend servers and APNS (see UrbanAirship). While it would be awesome if we could build servers that directly sent out pushes to iOS devices, Apple unfortunately maintains ultimate gatekeeper status and all your push notification requests must be routed through APNS. Such is the plight of developing on a closed source platform.</p>
<p>Then if all is fine and dandy, APNS will send your push to the user's device - along with a custom sound (i.e. the Gmail app), custom alert text, and even let you specify where the user lands when they open the notification (i.e. opening up the Twitter app and immediately dropping you on the tweet that just mentioned your handle).</p>The Self Aware Python Function2014-01-18T08:30:00-08:002014-01-18T08:30:00-08:00Sitong Pengtag:blog.sitongpeng.com,2014-01-18:/posts/the-self-aware-python-function.html<p>How would you write a function in Python that knows how many times it's been invoked?</p><p>I've been using Python for over a year now. It's what I learned to program with. About half a year ago, a fellow coder (friend of a friend) posed the following riddle upon learning that it was my language of choice:</p>
<p class="quote">"How would you write a function in Python that knows how many times it's been invoked?"</p>
<p>Let's consider this for a moment. A function that knows how many times it has been invoked is one that would need some access to a scope outside of it's own. Functions are generally pretty transient — they do their thing and then wait until they are told to do it again. There isn't a middling dormant state where they consider how many times they've been told to execute their (probably) menial task.</p>
<p>As a first stab, we might consider a global counter, as in the following setup:</p>
<div class="highlight"><pre><span></span><span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">self_aware_function</span><span class="p">():</span>
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">count</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">print</span> <span class="s1">'This is my first time doing this'</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s1">'I have done this {} times now.'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">count</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">self_aware_function</span><span class="p">()</span>
</pre></div>
<p>Those familiar with Python are up in arms right now, and rightfully so. Here's what you get when invoking <code>self_aware_function</code>:</p>
<div class="highlight"><pre><span></span>UnboundLocalError: <span class="nb">local</span> variable <span class="s1">'count'</span> referenced before assignment
</pre></div>
<p>In Python, when you are in a function and assign a value to an immutable type variable (such as our int <code>count</code>), you end up shadowing the global variable with one local to the function's scope. So when <code>count += 1</code> is evaluated (remember this is expanded to <code>count = count + 1</code>), Python cannot find the value for <code>count</code> in the expression to the right of the <code>=</code>.</p>
<h2>Okay, local variables won't work, how about we use the <code>global</code> keyword or mutable variables?</h2>
<div class="highlight"><pre><span></span><span class="c1"># global keyword</span>
<span class="k">def</span> <span class="nf">self_aware_function</span><span class="p">():</span>
<span class="k">global</span> <span class="n">count</span> <span class="c1"># Now we force the use of the global count</span>
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="c1"># ...</span>
</pre></div>
<div class="highlight"><pre><span></span><span class="c1"># using a list</span>
<span class="n">count</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">self_aware_function</span><span class="p">():</span>
<span class="n">count</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="c1"># ...</span>
</pre></div>
<p>These both work and globals were my first idea for a solution. However, when I asked if this was acceptable, I was met with opposition.</p>
<p class="quote">"You are only allowed to write code within the function, not outside of it."</p>
<p>That's rough. How do you become self aware of an outside world/scope that you can't even interact with?</p>
<p>Turns out, the answer lies within a popular Python <a href="http://effbot.org/zone/default-values.html">gotcha</a>.</p>
<h2>Self-awareness</h2>
<p>Here's how you define a default parameter in Python:</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">):</span>
<span class="k">return</span> <span class="n">default</span>
</pre></div>
<p>In Python, default parameters are evaluated ONLY once — when the function is defined. That means the default parameter is "the same" for all invocations of the function. I say "the same" because normally the default parameter will have the same value across multiple function invocations, but if your default parameter is mutable then you change it! And then you can do some really special things.</p>
<p>Case in point, self-awareness:</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">self_aware_function</span><span class="p">(</span><span class="n">count</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
<span class="n">count</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">count</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">print</span> <span class="s1">'This is my first time doing this'</span>
<span class="k">elif</span> <span class="n">count</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">>=</span> <span class="mi">10</span><span class="p">:</span>
<span class="k">print</span> <span class="s2">"Who are you to tell me what to do???"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s1">'I have done this {} times now.'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">count</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">self_aware_function</span><span class="p">()</span>
</pre></div>
<ul>
<li><code>count</code> is evaluated at function definition to be a mutable list with one integer element.</li>
<li>Each invocation of our <code>self_aware_function</code> adds another tick to our mutable <code>count</code> parameter.</li>
</ul>
<p>And we have our cheeky, self aware function!</p>
<div class="highlight"><pre><span></span>$ python aware.py
This is my first <span class="nb">time</span> doing this
I have <span class="k">done</span> this <span class="m">2</span> <span class="nb">times</span> now.
I have <span class="k">done</span> this <span class="m">3</span> <span class="nb">times</span> now.
I have <span class="k">done</span> this <span class="m">4</span> <span class="nb">times</span> now.
I have <span class="k">done</span> this <span class="m">5</span> <span class="nb">times</span> now.
I have <span class="k">done</span> this <span class="m">6</span> <span class="nb">times</span> now.
I have <span class="k">done</span> this <span class="m">7</span> <span class="nb">times</span> now.
I have <span class="k">done</span> this <span class="m">8</span> <span class="nb">times</span> now.
I have <span class="k">done</span> this <span class="m">9</span> <span class="nb">times</span> now.
Who are you to tell me what to <span class="k">do</span>???
</pre></div>
<p><span class="note">If you're wondering, mutable default arguments was the answer I gave after a good amount of thought. I believe there are other solutions and I invite you to share them in the comments :)</span></p>I moved your stuff but don't freak out cuz I left behind a symlink2013-06-29T23:00:00-07:002013-06-29T23:00:00-07:00Sitong Pengtag:blog.sitongpeng.com,2013-06-29:/posts/i-moved-your-stuff-but-dont-freak-out-cuz-i-left-behind-a-symlink.html<p>Dotfiles and symlinks otherwise known as cleaning $HOME</p><p><span id="note">Learning new <em>nix-craft is kinda like being handed shiny new electronics. You're instantly intrigued with what new stuff you can do with it. This entry is the first in a series about </em>nix-craft.</span></p>
<p>I'm not sure when I first heard of <a href="http://en.wikipedia.org/wiki/Symbolic_link">symlinking</a>, but the first time it hit me as "something I should get acquainted with" was while I was reading <a href="http://dotfiles.github.io/">dotfiles.github.io</a>. Context clues provided me with the idea that to symlink was to leave a little note to your OS about where you moved the file it expected to find there.</p>
<p>So, as I had endeavored to clean my virtual <code>$HOME</code> of dotfiles, it became apparent that I needed to get familiar with symlinks.</p>
<h2>Leaving a note</h2>
<p>To create a symlink, you'd type this into your terminal:</p>
<div class="highlight"><pre><span></span>ln -s path/to/target path/to/link
</pre></div>
<p>In English, this reads as:
Create a symlink at <code>path/to/link</code> that redirects to <code>path/to/target</code>.</p>
<h2>Reading the note</h2>
<p>Most programs play nicely with <code>symlinks</code>. For instance, if you were to symlink your <code>~/.vimrc</code> to <code>~/dotfiles/vim/.vimrc</code>, Vim would access <code>~/.vimrc</code> but would end up reading from <code>~/dotfiles/vim/.vimrc</code> instead. It's kind of like a HTTP 302 that redirects you to another URI, or in our case, another path on your filesystem. Microsoft Windows users might find symlinks to be similar to shortcuts. They're essentially the same thing with the caveat that Windows programs would unfortunately get cranky if you tried to pass the shortcut file as an executable file. In *nix systems, symlinks in place of the actual file is okay for the most part!</p>
<p>It's also helpful to know what path your existing symlinks are pointing to. A simple <code>ls</code> doesn't list out your symlinks. You'll want to run <code>ls -l</code>, and symlinks will look something like the second entry below:</p>
<div class="highlight"><pre><span></span>-rw------- 1 sitong staff 28054 Jun 29 17:52 .viminfo
lrwxr-xr-x 1 sitong staff 33 Jun 29 16:57 .vimrc -> /Users/sitong/dotfiles/vim/.vimrc
</pre></div>
<p><span id="note">I actually ran <code>ls -al</code> since the symlinks in my <code>$HOME</code> are all dotfiles.</span> </p>
<h2>Removing the note</h2>
<p>Removing the symlink is just an <code>rm</code> to the symlink. For instance:</p>
<div class="highlight"><pre><span></span>rm ~/.vimrc
</pre></div>
<h2>A little bonus</h2>
<p>So we saw that <code>ln -s</code> is the command for symlinks but what if you passed a naked <code>ln</code> command to your terminal?</p>
<p>You would actually be creating a <a href="http://en.wikipedia.org/wiki/Hard_link">hard link</a>. Hard links point directly to a file's memory space instead of a filesystem path as with symlinks. This means you can move or rename the target file and the hard link will still resolve to that original target file. If you were to move or rename your symlinked target file then when some program tries to resolve the symlink, it won't find anything at that path. Try it out yourself!</p>Objects, attributes, functions, and methods2013-04-07T16:00:00-07:002013-04-07T16:00:00-07:00Sitong Pengtag:blog.sitongpeng.com,2013-04-07:/posts/objects-attributes-functions-and-methods.html<p>Discussing python objects, attributes, and the difference between functions and methods</p><p>I set some time out to open the box on some <a href="http://www.python.org">Python</a> fundamentals this weekend. I have a few topics to write about but, for today, let's talk a little about objects.</p>
<h2>Objects</h2>
<p>Objects are a big deal in Python. And rightfully so, as most developers use Python in an object oriented manner, though you can certainly write imperatively or pseudo-functionally too. In fact, some people subscribe to the thought that <a href="http://www.diveintopython.net/getting_to_know_python/everything_is_an_object.html">everything in Python is an object</a>. I'm not going to argue about whether that's true or not so we'll just tip-toe around it and state that there are an <strong>awful lot of objects</strong>.</p>
<p>So what is an object? Let's use <a href="http://en.wikipedia.org/wiki/Object_(computer_science)#Properties_of_an_object">Wikipedia</a>'s definition. Objects are characterized by these properties:</p>
<h4>Identity (Objects are unique from each other)</h4>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Trivial</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">obj</span><span class="p">,</span> <span class="n">diff_obj</span> <span class="o">=</span> <span class="n">Trivial</span><span class="p">(),</span> <span class="n">Trivial</span><span class="p">()</span>
<span class="nb">id</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="c1"># 25851216</span>
<span class="nb">id</span><span class="p">(</span><span class="n">diff_obj</span><span class="p">)</span> <span class="c1"># 26133840</span>
</pre></div>
<h4>State (Can store data in object)</h4>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span> <span class="c1"># modules are objects</span>
<span class="n">os</span><span class="o">.</span><span class="n">my_data</span> <span class="o">=</span> <span class="s1">'arbitrary'</span>
<span class="k">print</span> <span class="n">os</span><span class="o">.</span><span class="n">my_data</span> <span class="c1"># arbitrary</span>
</pre></div>
<h4>Behavior (Can manipulate the object)</h4>
<div class="highlight"><pre><span></span><span class="k">print</span> <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s1">'strings'</span><span class="p">,</span> <span class="s1">'are'</span><span class="p">,</span> <span class="s1">'objects'</span><span class="p">,</span> <span class="s1">'with'</span><span class="p">,</span> <span class="s1">'methods'</span><span class="p">])</span>
<span class="c1"># strings are objects with methods</span>
</pre></div>
<h2>Attributes and Methods</h2>
<p>You're probably familiar with setting object attributes to static data or writing simple methods if you've worked with objects in the past.</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Lannister</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="k">def</span> <span class="nf">say_family_motto</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span> <span class="s1">'{} says: "Hear Me Roar!"'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
<span class="n">tyrion</span> <span class="o">=</span> <span class="n">Lannister</span><span class="p">()</span>
<span class="k">print</span> <span class="n">tyrion</span><span class="o">.</span><span class="n">name</span>
<span class="c1"># Tyrion Lannister</span>
<span class="n">tyrion</span><span class="o">.</span><span class="n">say_family_motto</span><span class="p">()</span>
<span class="c1"># Tyrion Lannister says: "Hear Me Roar!"</span>
</pre></div>
<p>But you're actually not limited to such trivial behavior. For instance, since functions are first class objects in Python, you could easily do the following too.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">say_common_motto</span><span class="p">():</span>
<span class="k">print</span> <span class="s1">'A Lannister Always Pays His Debts.'</span>
<span class="n">tyrion</span><span class="o">.</span><span class="n">say_common_motto</span> <span class="o">=</span> <span class="n">say_common_motto</span>
<span class="n">tyrion</span><span class="o">.</span><span class="n">say_common_motto</span><span class="p">()</span>
<span class="c1"># A Lannister Always Pays His Debts.</span>
</pre></div>
<p>As you can see, we've set the <code>.say_common_motto</code> attribute to the function object <code>say_common_motto</code>, then invoked the attribute.</p>
<p>Before we continue, we should make a distinction between <code>.say_common_motto</code> and <code>.say_family_motto</code>.</p>
<div class="highlight"><pre><span></span><span class="nb">type</span><span class="p">(</span><span class="n">tyrion</span><span class="o">.</span><span class="n">say_common_motto</span><span class="p">)</span>
<span class="c1"># <type 'function'></span>
<span class="nb">type</span><span class="p">(</span><span class="n">tyrion</span><span class="o">.</span><span class="n">say_family_motto</span><span class="p">)</span>
<span class="c1"># <type 'instancemethod'></span>
</pre></div>
<p>Python resolves the type of <code>.say_common_motto</code> to a function object and <code>.say_family_motto</code> to an instance method object. What's the difference?</p>
<p>You can think of a method as a function with a unique difference. A method always takes the object it's associated with as it's first argument. You don't have a choice on the matter.</p>
<p>Under the hood, when Python sees <code>tyrion.say_family_motto()</code>, it first looks for a <code>.say_family_motto</code> attribute in <code>tyrion</code> (this means you can override an object method by writing to an object attribute with the same name). When it doesn't find that, the interpreter will jump up to the class level and look for <code>say_family_motto</code> function defined at the class level. Once found, it will invoke the function as a method - namely, by attaching the <code>tyrion</code> object to the head of the argument list. That's also why a method definition always includes a positional argument placeholder first (traditionally called <code>self</code> in Python).</p>
<p>Methods are really just a shortcut though. You can actually just define your own function with an argument placeholder for an object and attach the function to the object attribute. An example makes this clearer. Suppose we rewrote the <code>say_common_motto</code> function to make it equivalent to a method.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">say_common_motto</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span> <span class="s1">'{} says: "A Lannister Always Pays His Debts."'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
<span class="n">tyrion</span><span class="o">.</span><span class="n">say_common_motto</span> <span class="o">=</span> <span class="n">say_common_motto</span>
<span class="n">tyrion</span><span class="o">.</span><span class="n">say_common_motto</span><span class="p">(</span><span class="n">tyrion</span><span class="p">)</span>
<span class="c1"># Tyrion Lannister says: "A Lannister Always Pays His Debts."</span>
<span class="n">tyrion</span><span class="o">.</span><span class="n">say_family_motto</span><span class="p">()</span>
<span class="c1"># Tyrion Lannister says: "Hear Me Roar!"</span>
</pre></div>
<p>As you can see, defining a method in the class is a lot cleaner than attaching a function to the instance object. But both styles get you to the same resolution eventually. </p>
<p>Anyways, hopefully you know a little more about Python objects now.</p>Sustained momentum2013-03-20T23:59:00-07:002013-03-20T23:59:00-07:00Sitong Pengtag:blog.sitongpeng.com,2013-03-20:/posts/sustained-momentum.html<p>My plans for the rest of the first half of 2013</p><p>In the next couple months, I'm planning on writing more about <code>Javascript</code> as I pick it up in work and from my own reading. Towards the end of <a href="https://www.hackerschool.com">Hacker School</a>, I decided I wanted to explore it as my second programming language. Reasoning: I can return to my functional programming roots and I can round out my understanding of web development by getting intimate with how the browser works.</p>
<p>However, this doesn't mean I will stop developing in <code>Python</code>. Aside from <a href="https://www.djangoproject.com/">Django</a> exposure at work, I'm planning to continue building web applications for myself - and hopefully with more robust front-end UI.</p>
<p>But, that's not quite good enough. If there was one thing I took away from Hacker School, it was the idea that I should always be pushing myself to become a better programmer. Web development is fun and lets me exercise my creative side, but I want to step outside my comfort zone and pursue other avenues of technology too. I'm not entirely sure what direction I'll look but I think my best bet is to attach myself to an open source project and develop a deep understanding of that problem space.</p>
<p>Anyways, I'll think on that and come back with my decision within the next month. Hold me to it!</p>No man is an island: Collaboration with git2013-03-12T20:55:00-07:002013-03-12T20:55:00-07:00Sitong Pengtag:blog.sitongpeng.com,2013-03-12:/posts/no-man-is-an-island.html<p>Branching, merging, rebasing</p><p>I'm currently in the middle of a Git crash course at work. Though to be honest, it's not really a course. It's more just me crashing. Luckily <code>git</code> is forgiving while I'm expanding my terminology past <code>add</code>, <code>commit</code>, <code>push</code>, <code>status</code>, <code>diff</code>, and <code>clone</code>. In this post, I'll summarize what I'm learning in my own words, but you should read the amazingly clear <a href="http://git-scm.com/book">Pro Git</a> text if you have the time.</p>
<h2>Version control for the masses</h2>
<p>When you're just a lone soul contributing to your own project, <code>git</code> is basically just a backup system. You're really only keeping snapshots of your project progress and not really worrying about concurrent user editing. But add other contributors into the equation and suddenly you'll need to be in control of all the moving parts of your codebase, or you may have a mess of things.</p>
<h2>Growing a forest from a single tree</h2>
<p>Every <code>git</code> repository holds a wealth of information about a project. Since each repository houses an entire project and it is dead simple to pull down repository clones from websites like <a href="https://github.com">Github</a> and <a href="https://bitbucket.org/">BitBucket</a>, it is easy to see how a popular project might spread its roots over many machines. This can lead to a lot of chaos though, and teams that are working together on projects will need to work on atomizing their changes. Individual commits do fulfill this fairly well on the small scale, but you also need to organize your commits into groups. A good way of conducting this separation is through <code>git</code>'s branching model.</p>
<div class="highlight"><pre><span></span>git branch [new_branch]
</pre></div>
<p>This command creates a new branch separate from your current development branch. Branching is useful to organize paths of development, as you're literally splitting off a new path. For instance, you might want to make a new branch for every bug-fix/feature request of your website or for both server and client sides of your new game. If not given a parameter, <code>git branch</code> will simply list your outstanding branches and show you which branch you're currently working in.</p>
<p>To actually move branches, you'll want to run this command:</p>
<div class="highlight"><pre><span></span>git checkout [existing_branch]
</pre></div>
<p>Then you can either <code>git branch</code> or <code>git status</code> to see where you are.</p>
<h2>Finding your way back home</h2>
<p>Great, so you've fixed three bugs and added two features, including pillow armor for your game's main character. How do you get all of that jazz back onto your main development or master branch?</p>
<p>Generally there's two ways about this.</p>
<div class="highlight"><pre><span></span>git merge [existing_side_branch]
</pre></div>
<p>While you're in a branch (such as the main/master branch) and you want to merge in a side branch, you'll generally be safe with this command. If your current branch never moved forward, the merge will just <code>fast forward</code> your current branch to the position of the side branch. If your current branch has progressed separately from the side branch, the merge will recursively find the two branches' common ancestor, then perform a three-way merge. You'll end up with an extra commit that merges your two branches. This extra commit will have two parents instead of one (one for each branch that it was merged from).</p>
<p>You can avoid having two parent commits and have a more straightforward development path with the second method of merging.</p>
<div class="highlight"><pre><span></span>git rebase [existing_main_branch]
</pre></div>
<p>You'll start in your side branch. The <code>rebase</code> command starts with the divergent main branch and tries to sequentially stack the each side branch's commits on top. If there are no merge conflicts, you'll end up with a straight development path.</p>
<h2>Knowing where your keys are</h2>
<p>The true beauty of <code>git</code> isn't realized until you spread out repositories onto different machines and servers. Remote locations are tracked in the <code>remote</code> variable.</p>
<div class="highlight"><pre><span></span>git remote
</pre></div>
<p>This lists all saved remote locations. Your list may contain <code>origin</code> (Github/Bitbucket), <code>heroku</code> (Heroku), or the name for your own private server.</p>
<p>Anyways, that's essentially the foundation you need for version control. Stay tuned to a later post for more advanced <code>git</code> control.</p>Understanding heaps2013-02-02T23:59:00-08:002013-02-02T23:59:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-02-02:/posts/understanding-heaps.html<p>Walking through the implementation of a heap and its insert/extract min methods</p><p>I'm spending this weekend filling in some of the holes in my programming background, data structures in particular. As part of the learning process, I want to share my new understanding of heaps.</p>
<h2>What is it?</h2>
<p>A heap is a type of <a href="http://en.wikipedia.org/wiki/Priority_queue">priority queue</a>, which is just a queue where dequeued elements are primarily selected based on their "priority" and secondarily selected based on the "first in first out" principle. A heap prioritizes by key values of objects it stores, which leads to the two flavors of heaps: the max heap and min heap. The max heap will dequeue the objects with the highest keys first. If there are multiple maxes, the heap will dequeue by order of insertion. As you'd expect, the min heap is the same except it dequeues objects with the lowest keys first.</p>
<h2>Introducing the max heap</h2>
<p>Although a heap is technically a priority queue, and although we are going to implement it as an array, heaps are commonly represented as a binary tree. Here is the max heap we're going to work with:</p>
<p><img alt="Binary max heap" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Heap_delete_step0.svg/500px-Heap_delete_step0.svg.png"></p>
<p>There are two conditions that must be met for a binary tree to be a max heap.</p>
<ol>
<li>Every parent node must be at least as large as either child nodes. This means the max key will always be at the top of the tree.</li>
<li>The tree must be complete at all levels except the deepest. The deepest level must be populated from the left. This means if the above tree had another node, it would be the left child of the node 8.</li>
</ol>
<p>We're going to implement this heap as an array. This boils down to extracting nodes left to right, top to bottom. Here's what it will look like:</p>
<div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">11</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
</pre></div>
<p><span id="note">Normally heaps hold objects with the keys we are showing in the tree and array representation. For simplicity, we'll just assume the objects and keys are one and the same.</span></p>
<p>We also need to keep track of the parent and children of any given node. That's pretty natural for binary trees but how is that implemented in arrays? Turns out it's pretty simple with one-indexing, due to the way we are pulling elements off the tree.</p>
<div class="highlight"><pre><span></span> 1 2 3 4 5 <-- One-indexing
[11, 5, 8, 3, 4]
EXAMPLE:
parent(i) = floor(i/2) parent(2) = 1
left_child(i) = i*2 left_child(2) = 4
right_child(i) = i*2 + 1 right_child(2) = 5
</pre></div>
<p>Let's code up what we have. I prefer to have zero-indexing so the math on the parent/children calculation will have to compensate.</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MaxHeap</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">arr</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">parent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="k">return</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">children</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
<span class="n">left</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span>
<span class="n">right</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">left</span><span class="p">,</span> <span class="n">right</span>
</pre></div>
<p>Now, a heap has two basic operations: insert and extract_max (extract_min). These are guaranteed to run in <code>O(logN)</code> time, or in other words, the height of the binary tree.</p>
<h2>Insert</h2>
<p>What does an insert look like in our binary tree model? Following the conditions of a binary heap, we have to insert the new object at the deepest level, moving in from the left. That corresponds to the node marked X below:</p>
<p><img alt="Insert at X" src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Heap_add_step1.svg/500px-Heap_add_step1.svg.png"></p>
<p>It should be pretty obvious that the object we insert could break the heap property of this tree. Whatever key we end up with, we first need to compare it with its parent node. The parent node's key is 8, so if we insert an object with <code>key <= 8</code> then we wouldn't have to do anything further. But what if the key is something higher like 15? Then our insertion would break heap condition #2.</p>
<p>In this situation, the next step is to swap our inserted node with it's parent node. </p>
<p><img alt="Swap with parent" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Heap_add_step2.svg/500px-Heap_add_step2.svg.png"></p>
<p>Cool. But now when we check 15 against its new parent, the root, we notice we're still in trouble. So we swap again. These swap acts are also known as "bubbling up" or "heapifying up", as the inserted object is promoted levels due to its priority.</p>
<p><img alt="Promoted to root" src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Heap_add_step3.svg/500px-Heap_add_step3.svg.png"></p>
<p>Now that 15 has made it's way up to the root node, we can stop. As you can see, the new tree follows all conditions to be classified as a max heap. Here's the code for the insert operation.</p>
<div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">insert</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="n">i</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
<span class="n">parent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">></span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">parent</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">parent</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">parent</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="k">if</span> <span class="n">parent</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">parent</span>
<span class="n">parent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span> <span class="c1"># parent is root</span>
<span class="k">break</span>
</pre></div>
<p>As you can see, we first insert to the end of the array, then while the inserted key is larger than its parent, we swap it upward until it finds its place.</p>
<h2>Extract Max</h2>
<p>I believe this is also known as Delete Max, but in either case, this operation removes the max from the heap. And because we're working with a heap, we know the max is the root of the tree (or first element of the array), so we certainly don't need to traverse through the entire structure to determine it.</p>
<p><img alt="Binary max heap" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Heap_delete_step0.svg/500px-Heap_delete_step0.svg.png"></p>
<p>Now, as mentioned before, the first step is to remove the root node. That leaves us with a tricky situation. What node will replace the root?</p>
<p>Let's go through our options.</p>
<ul>
<li>Pull up the 5. Well, now we fail both conditions. The root is now less than the right child, and more importantly we have an incomplete binary tree.</li>
<li>Pull up the 8. Cool, our root is the max, but now we have an entire empty branch on the right. That seems like a big problem and we can't just fix it by pulling from an entirely separate branch.</li>
<li>Pull up the 3. Breaks the complete tree again.</li>
<li>Pull up the 4. We still have a complete tree (in terms of a heap at least). We have a bad root but maybe we can shift that node back down.</li>
</ul>
<p>So the general solution seems to be, promote the last element of the tree/array.</p>
<p><img alt="Big promotion here" src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Heap_remove_step1.svg/500px-Heap_remove_step1.svg.png"></p>
<p>So now the new root is no longer the max. We need to swap it with one of its children. If we swap with 5, we'll still have the same problem. We'll need to swap with 8. This should lead us to the realization that we'll always want to swap with the higher of the two children, otherwise we'll just be making more of a mess of things.</p>
<p><img alt="Back to normalcy" src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Heap_remove_step2.svg/500px-Heap_remove_step2.svg.png"></p>
<p>Now we have our max extracted heap!</p>
<p>Here's the code:</p>
<div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">extract_max</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">children</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">while</span> <span class="n">right</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">):</span> <span class="c1"># if right exists, so does left</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="p">]:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">></span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">]</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">left</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="p">]</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">right</span>
<span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">children</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span> <span class="c1"># we have a heap again</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">left</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">]</span>
</pre></div>
<p><span id="note">I'm not actually returning the max here, but you can build that in pretty easily.</span></p>
<p><code>extract_max</code> is a bit more complicated than <code>insert</code>. Swapping the new root down takes a few more comparision steps as we have to decide which child to swap with. We're still within <code>O(logN)</code> time though, since we will never need to swap more than the height of the binary tree.</p>
<h2>So what are heaps good for?</h2>
<p>In general, when you constantly need to access the min or max of some data, heaps are a logical choice, as you just need to pluck it from the top of the tree/front of the array and do a little rearranging. This means they are useful for tasks like managing bandwith on a router (always send the prioritized traffic first) or handling asynchronous event processing (firing off shortest tasks first).</p>
<p>Heaps are also useful in speeding up certain algorithms that require multiple min or max computations. One example is Dijkstra's shortest path algorithm, where you are constantly computing the minimum path for each node.</p>
<p>So, hopefully you've now got a solid understanding of heaps. Next time you're working on something and you find yourself repeatedly taking minimums or maximums, you should give them a try. They will make your life easier.</p>Travelling Salesman2013-02-01T12:30:00-08:002013-02-01T12:30:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-02-01:/posts/travelling-salesman.html<p>A discussion about the travelling salesman problem</p><p>This is a challenging problem about a travelling salesman that wants to visit a number of cities efficiently. He needs to sell his product in all the cities so he needs to plot out the shortest path to visit all cities but each city only once. I'm not sure why he can't return to any cities but let's assume his tradecraft is in less agreeable goods.</p>
<p>We'll work through the quirks of the travelling salesman problem. The map can be modelled as a <a href="http://en.wikipedia.org/wiki/Graph_theory">graph</a> where nodes are cities. Also each node is connected to every other node, you can travel in either direction along any edge, and edge lengths are the distances between cities. In other words, you could refer to this graph as complete, undirected, and weighted.</p>
<p>Let's say there are 10 node cities: A to J. The salesman starts at node A.</p>
<h2>Finding a "short" path</h2>
<p>There's a simple way to find a "short" path. I say "short" but this could also lead us to a very long path in certain cases.</p>
<ol>
<li>Starting at A, traverse through each node and make note of which path is the shortest.</li>
<li>Take the shortest path (let's say to B) and mark A visited.</li>
<li>Repeat step 1 and 2 until all nodes are visited.</li>
</ol>
<p>When might this be the shortest path? Imagine the cities laid out in a line like so:</p>
<div class="highlight"><pre><span></span>(A) (B) (C) (D) (E) (F) (G) (H) (I) (J)
</pre></div>
<p>Using the "short" path algorithm, we can see that we'll just sequentially step left to right and that would certainly find us the shortest path.</p>
<p>When might this be a long path? Try the following:</p>
<div class="highlight"><pre><span></span>(J) (A) (B) (C) (D) (E) (F) (G) (H) (I)
</pre></div>
<p>In this case, we would visit J last, but clearly it would be faster to visit J first, then the rest of the nodes.</p>
<p>The problem with this "short" path algorithm is that we are considering too few paths.</p>
<h2>Exhaustive search</h2>
<p>One way to ensure that we have the shortest path is to simply construct all paths (try all permutations) and pick the shortest. This, however, can be prohibitively expensive as the number of cities increases (see <a href="http://en.wikipedia.org/wiki/Combinatorial_explosion">combinatorial explosion</a>). For less busy salesmen though, this is a viable option.</p>
<p>Essentially this search is brute force. It can be implemented as breadth first or depth first. They should take the same time since you'll need to search the entire graph in either case. However, usually it is easier to implement depth first search, so we can do that.</p>
<ol>
<li>Starting at A, move to next unvisited node, note distance and mark A as visited.</li>
<li>Repeat step 1 until all nodes visited, then you should have some array of all distances travelled. That is your distance path.</li>
<li>Now traverse back up your path until you have the option of visiting a different node. Visit that and dig deeper down until you also have that path complete. (in this case, traversing back up the path is done by finishing the innermost loop and moving on to the next node of the immediate outer loop)</li>
<li>Eventually you will visit every path and document the distances.</li>
</ol>
<p>We end up with <code>(N-1)!</code> paths which is pretty terrible in terms of computation time (Note this is not <code>N!</code> because we are actually only visiting <code>N-1</code> nodes since we have defined a start node and we don't return to it). But on the bright side, we know we have the shortest path because we calculated them all!</p>
<h2>So what about large N?</h2>
<p>Well I wish I could give a solid answer here, but this is a heavily studied academic problem that is beyond my current capabilities. I'll leave you with this Stack Overflow <a href="http://stackoverflow.com/questions/7159259/optimized-tsp-algorithms">link</a> though, which I plan to study a bit further. I'll be sure to share my findings in an upcoming post, so stay tuned.</p>
<p><span id="note">Shoot me an email or write a comment if you have any suggested material you think I should peruse. I'd love to learn more about this.</span></p>Bit manipulation fun2013-01-30T22:00:00-08:002013-01-30T22:00:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-30:/posts/bit-manipulation-fun.html<p>A few bit manipulation tricks</p><p>So while I was working on interview prep, I got a bit curious about what cool ways bit manipulation might alter the way we might write code. Here's a few examples of short functions you can write using only bit operations.</p>
<h2>Simple stuff first</h2>
<p>The following trick may be standard fare but seeing as I am not a "classically" trained programmer (no degree in computer science), this guy did tickle my fancy.</p>
<p>When you write out a integer in a binary representation, 5 as <code>0101</code> for example, the least significant bit (leftmost bit) represents if the integer is odd or even. Of course, bits further left represent powers of two, hence the term "base two".</p>
<div class="highlight"><pre><span></span>0101 is 0*(2^3) + 1*(2^2) + 0*(2^1) + 1*(2^0)
or 0*8 + 1*4 + 0*2 + 1*1
or 5
</pre></div>
<p>Anyone can write a simple function that tests if a given integer <code>x</code> is even. Usually it will involve checking to see if <code>x</code> mod 2 is 0.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_even</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
</pre></div>
<p>But, given that least significant bit of a binary value represents odd or even, we can write that same <code>is_even</code> function using the <code>AND</code> bit operation. </p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_even</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
</pre></div>
<p>For example 6 & 1 is 0.</p>
<div class="highlight"><pre><span></span> 0110 <-- 6
& 0001 <-- 1
======
0000
</pre></div>
<p>This ends up being the same amount of typing but it's interesting that we have this second option of writing the <code>is_even</code> function.</p>
<h2>Powerful twos</h2>
<p>If you work on <a href="http://projecteuler.net/">Project Euler</a> problems frequently, the following shortcut might be beneficial to keep in mind. Here's a function that checks if <code>x</code> is a power of two.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_power_of_two</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="n">power_of_two</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">while</span> <span class="n">power_of_two</span> <span class="o"><</span> <span class="n">x</span><span class="p">:</span>
<span class="n">power_of_two</span> <span class="o">*=</span> <span class="mi">2</span>
<span class="k">return</span> <span class="n">power_of_two</span> <span class="o">==</span> <span class="n">x</span>
</pre></div>
<p>That's pretty compact but it turns out binary is well suited to figure out if a number is a power of two.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_power_of_two</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">&</span> <span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> <span class="o">==</span> <span class="mi">0</span>
</pre></div>
<p>Let's see this in action with <code>x</code> as some random binary number:</p>
<div class="highlight"><pre><span></span> 010110000 <-- x
- 000000001
===========
010101111 <-- x-1
& 010110000
===========
010100000 <-- x & (x-1)
So, (x & (x-1)) just removed the left-most bit that was equal to 1. But then, when might (x & (x-1)) be 0? That would only happen when x has only one 1 bit, which means that x must be a power of 2.
</pre></div>
<h2>Swapping in place</h2>
<p>Python is nice in that you never have to use a temporary variable when you want to do variable swaps. This is, of course, not the same in other languages.</p>
<div class="highlight"><pre><span></span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">,</span> <span class="n">x</span>
</pre></div>
<p>Behind the scenes, Python accesses the values of <code>y</code> and <code>x</code>, then rotates them as it unpacks and assigns to <code>x</code> and <code>y</code>. Here's what that looks like when run through the Python disassembler:</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">dis</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span>
<span class="n">dis</span><span class="o">.</span><span class="n">dis</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
<span class="o">></span>
<span class="o">></span> <span class="mi">3</span> <span class="mi">0</span> <span class="n">LOAD_CONST</span> <span class="mi">1</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="o">></span> <span class="mi">3</span> <span class="n">STORE_FAST</span> <span class="mi">0</span> <span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="o">></span>
<span class="o">></span> <span class="mi">4</span> <span class="mi">6</span> <span class="n">LOAD_CONST</span> <span class="mi">2</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="o">></span> <span class="mi">9</span> <span class="n">STORE_FAST</span> <span class="mi">1</span> <span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="o">></span>
<span class="o">></span> <span class="mi">5</span> <span class="mi">12</span> <span class="n">LOAD_FAST</span> <span class="mi">0</span> <span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="o">></span> <span class="mi">15</span> <span class="n">LOAD_FAST</span> <span class="mi">1</span> <span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="o">></span> <span class="mi">18</span> <span class="n">ROT_TWO</span>
<span class="o">></span> <span class="mi">19</span> <span class="n">STORE_FAST</span> <span class="mi">0</span> <span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="o">></span> <span class="mi">22</span> <span class="n">STORE_FAST</span> <span class="mi">1</span> <span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="o">></span>
<span class="o">></span> <span class="mi">6</span> <span class="mi">25</span> <span class="n">LOAD_FAST</span> <span class="mi">1</span> <span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="o">></span> <span class="mi">28</span> <span class="n">LOAD_FAST</span> <span class="mi">0</span> <span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="o">></span> <span class="mi">31</span> <span class="n">ROT_TWO</span>
<span class="o">></span> <span class="mi">32</span> <span class="n">STORE_FAST</span> <span class="mi">0</span> <span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="o">></span> <span class="mi">35</span> <span class="n">STORE_FAST</span> <span class="mi">1</span> <span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="o">></span> <span class="mi">38</span> <span class="n">LOAD_CONST</span> <span class="mi">0</span> <span class="p">(</span><span class="bp">None</span><span class="p">)</span>
<span class="o">></span> <span class="mi">41</span> <span class="n">RETURN_VALUE</span>
</pre></div>
<p>But, did you know we can actually swap without a temporary variable using <code>XOR</code> too.</p>
<div class="highlight"><pre><span></span>x ^= y
y ^= x
x ^= y
</pre></div>
<p>To understand what's happening, you should recall that <code>XOR</code> is commutative, <code>x^x</code> is 0, and <code>x^0</code> is <code>x</code>. Let's break down the <a href="http://en.wikipedia.org/wiki/XOR_swap_algorithm">XOR Swap Algorithm</a> again.</p>
<div class="highlight"><pre><span></span><span class="gh">start -> breaking down -> commuting -> cancelling -> removing 0's</span>
<span class="gh">=============================================================================</span>
x ^= y -> x = x^y
y ^= x -> y = y^x^y -> y = x^y^y -> y = x^0 -> y = x
x ^= y -> x = x^y^y^x^y -> x = x^x^y^y^y -> x = 0^y^0 -> x = y
</pre></div>
<p>That's pretty cool but I'll stick to Python's easy swap. It is nice, however, to see how binary manipulation can be used to our advantage in languages that don't have an in-place swap.</p>
<p>Now for the disclaimer. While the XOR swap is pretty nifty, it doesn't have much practical use. If you actually plan on using it in the real world, hopefully your application fits in one of <a href="http://en.wikipedia.org/wiki/XOR_swap_algorithm#Reasons_for_use_in_practice">these</a> buckets. Turns out, optimizing compilers tend to make temporary variable swaps pretty efficient, often faster than this XOR swap.</p>
<p><span id="note">Have any more bit manipulation tricks you'd like to share? Leave me a comment, I'd love to see more in action.</span></p>The case for base cases2013-01-28T21:45:00-08:002013-01-28T21:45:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-28:/posts/the-case-for-base-cases.html<p>Breaking a problem down to its base case and solving the Tower of Hanoi</p><p>You have a complicated problem to solve. How do you start tackling it?</p>
<p>One of the most tried and tested methods of problem solving is nothing more than implementing some noise control. In other words, can you peel back the complexity of the problem and make it simpler?</p>
<h2>Tower of Hanoi</h2>
<p>I finally sat down and tried solving this problem two days ago. For those of you unfamiliar, the <a href="http://en.wikipedia.org/wiki/Tower_of_Hanoi">Tower of Hanoi</a> is an old puzzle that has been mostly re-appropriated as a classic example of algorithmic thought. Here's a version of it:</p>
<p><img alt="Tower of Hanoi, from Wikipedia" src="http://upload.wikimedia.org/wikipedia/commons/0/07/Tower_of_Hanoi.jpeg"></p>
<p>There are three rods and a number of different sized disks that can slide onto any rod. The puzzle starts with the disks in a neat stack, ascending by size, on the first rod. The objective of the puzzle is to move the entire stack to the last rod, obeying the following rules: </p>
<ol>
<li>Only one disk may be moved at a time. </li>
<li>Each move consists of taking the top-most disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod. </li>
<li>No disk may be placed on top of a disk smaller than it.</li>
</ol>
<p>Seems straightforward enough, but let's solve this for N disks. How should we start?</p>
<h2>Let's start with the base cases</h2>
<p>N=1</p>
<div class="highlight"><pre><span></span> | | |
| | |
-|- | |
========= ========= =========
A B C
1. -----------------> -|-
Done.
So we solve N=1 with one move of -|-.
</pre></div>
<p>N=2</p>
<div class="highlight"><pre><span></span> | | |
-|- | |
--|-- | |
========= ========= =========
A B C
1. -------> -|-
| | |
| | |
--|-- -|- |
========= ========= =========
A B C
2. ----------------> --|--
3. -------> -|-
Done.
Let's take a closer look at these moves:
1. Exactly like solving N=1, except A->B instead of A->C.
2. The second step places the largest disc at the base of C.
3. Also solves N=1, only B->C instead of A->C.
Done.
Let's rewrite our steps like this:
1. Solve N=1, except A->B
2. Move --|-- from A->C
3. Solve N=1, except B->C
Done.
</pre></div>
<p>N=3</p>
<div class="highlight"><pre><span></span> -|- | |
--|-- | |
---|--- | |
========= ========= =========
A B C
1. -----------------> -|-
2. ------> --|--
3. -|- <-------
| | |
| -|- |
---|--- --|-- |
========= ========= =========
A B C
4. ---------------> ---|---
5. -|- <-------
6. ------> --|--
7. -----------------> -|-
Done.
Notice how steps 1-3 solve N=2 and places it at B. Rewrite?
1. Solve N=2, except A->B
2. Move ---|--- from A->C
3. Solve N=2, except B->C
Done.
</pre></div>
<p>Interesting. Looks like we have a formula.</p>
<div class="highlight"><pre><span></span>N=n
1. Solve N=(n-1), except A->B
2. Move largest disc from A->C
3. Solve N=(n-1), except B->C
</pre></div>
<p>I was pretty excited when I saw this pattern, as it meant I could code up a solution in very few lines of code. Here it is in Python, using a list as a stack:</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">solve_hanoi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">C</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">solve_hanoi</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">A</span><span class="p">,</span> <span class="n">C</span><span class="p">,</span> <span class="n">B</span><span class="p">)</span>
<span class="n">C</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">A</span><span class="o">.</span><span class="n">pop</span><span class="p">())</span>
<span class="n">solve_hanoi</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">A</span><span class="p">,</span> <span class="n">C</span><span class="p">)</span>
</pre></div>
<p>The trick is to redefine the rods for each recursive <code>n-1</code> call. What's more is you really only need to think about which rod you're starting and ending at. The odd rod out is just the buffer.</p>
<p>I'd show you the code in action but all the computation is behind the scenes and not very interesting. Luckily a quick search on Youtube yielded a visual solution for N=6. Notice how there is a point of symmetry in the middle as the 5 smaller disks sit at B and the largest disk migrates over to C. Utterly awesome!</p>
<iframe style="margin-top:20px;" width="560" height="315" src="http://www.youtube.com/embed/JqC_LsF1iWg" frameborder="0" allowfullscreen></iframe>Unexpected random number generation2013-01-23T20:20:00-08:002013-01-23T20:20:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-23:/posts/unexpected-random-number-generation.html<p>How you might want to be careful with random number generation in child processes</p><p>So, last month, I was working on building test applications for <a href="https://github.com/stoneG/whiskey">Whiskey</a>, my Python WSGI server implementation. I wanted to ensure Whiskey was robust enough to keep going, even if it was serving applications that met critical, program-killing exceptions. To that end, I wrote a random exception throwing application to test with Whiskey. Here's the code, simplified and stripped down to its core.</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fork</span><span class="p">()</span>
<span class="k">if</span> <span class="n">pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># if we are in the child process</span>
<span class="k">print</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</pre></div>
<h2>A little background</h2>
<p>Whiskey handles concurrent client requests by forking new child processes. Calling <code>os.fork()</code> splits the current process into two, the parent and child. The child process will have a process identifier (pid) of 0. Recall that a forked child process has a copy of the same memory space/environment of its parent.</p>
<h2>Result</h2>
<div class="highlight"><pre><span></span>> 0.844421851525
> 0.844421851525
> 0.844421851525
> 0.844421851525
> 0.844421851525
> 0.844421851525
> 0.844421851525
</pre></div>
<p>You might not be surprised since you've already come into this post with some suspicion, but remember that this is the stripped down code. What I actually ran into, was an application that either always failed or never failed. So, what's going on?</p>
<p>Well, every client request leads to a forked child process that handles the request. However, each child process ends up having the same random seed, since it is always forked from the same parent process (or more specifically, a parent process which never changes its random seed). This results in a pesky situation where you unexpectedly have an expected random number.</p>
<h2>Solution</h2>
<p>We need to reset the random seed for each forked process. One way is to set the seed to the time of the request.</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">time</span> <span class="c1">##### ADDED THIS LINE ######</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fork</span><span class="p">()</span>
<span class="k">if</span> <span class="n">pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span> <span class="c1">##### ADDED THIS LINE ######</span>
<span class="k">print</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</pre></div>
<p>Randomness restored.</p>
<p><span id="update">Update</span><br>
My friend <a href="https://twitter.com/geofflee">Geoff</a> mentioned that for real applications, you wouldn't want to use <code>time.time()</code> as your seed. Besides you leaving yourself open to the chance of two requests spawning processes at the same time, any PRNG (pseudo random number generator) is unsuitable for security reasons. Instead using <code>/dev/random</code> (UNIX) or <code>CryptGenRandom</code> (Windows) is preferable, since you'd have true randomness then. For the Python implementation, you'd want to make a call to <code>os.urandom()</code> to access your OS's random file. You can find the documentation on that, <a href="http://docs.python.org/2/library/os.html#os.urandom">here</a>.</p>
<p><span id="note">I wish I could say I ran into this recently, but I've unfortunately been too busy applying to jobs instead of working on personal projects. I actually talked about this subject for a Hacker School weekly presentation on December 6th, 2012.</span></p>Play sweeper2013-01-17T16:20:00-08:002013-01-17T16:20:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-17:/posts/play-sweeper.html<p>Marketing my javascript minesweeper game</p><p>Been working on this for the last couple days. It's my first, real foray into writing in Javascript since I don't count the couple of functions I've written for my websites. It uses a bit of JQuery. A lot of learning went into the creation of this game so I might write more about that business later. But yeah, for now.. Play <a href="http://stoneg.github.com/sweeper/sweeper.html">sweeper</a>.</p>I am a real Vim user today2013-01-10T20:00:00-08:002013-01-10T20:00:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-10:/posts/i-am-a-real-vim-user-today.html<p>My first Vim shortcut</p><p>There comes a point, usually after you've been using something for awhile, when you realize you are no longer just using it casually. <strong><em>And no, I'm not talking about drugs.</em></strong>I'm talking about defining my first shortcut key in my <code>.vimrc</code>.</p>
<h2>A little background</h2>
<p>I was first introduced to <a href="http://www.vim.org/">Vim</a> by my <a href="http://www.hackerschool.com">Hacker School</a> buddy <a href="http://www.jamesshieh.com">James</a>. For those of you who don't know, Vim is a very peculiar text editor. It is an "improved" version of <a href="http://ex-vi.sourceforge.net/">Vi</a>, the de facto Unix editor. Vim allows for a very efficient coding experience in which your hands generally never have to leave their main resting positions on the keyboard. And unlike editors (see <a href="http://www.gnu.org/software/emacs/">Emacs</a>), Vim makes heavy usage of different input modes to separate document navigation, inserting content, and text selection. This makes for a steep initial learning curve, as the default mode in Vim is mostly navigational, which is a farcry from the style of most word processors (hjkl actually mean hjkl, not left down up right).</p>
<h2>Word Wrap</h2>
<p>So I was excited to be able to write these blog posts using Vim since I've gotten quite good and fast at using it. However, I quickly realized that a text editor that primarily displays lines of code needs a bit of work to properly display words and sentences.</p>
<p>For instance, here's what I was seeing everytime I wrote a paragraph of text:</p>
<div class="highlight"><pre><span></span>This is a medium paragraph of text. Everything is all fine and dandy until you
get to the end of the line. Then, whatever text you just wrote gets cut off p
recisely when you reach the column width of your Vim window. This leads to awk
ward and hard to read paragraphs!
</pre></div>
<p>So, after a bit of research, I threw this into my <code>.vimrc</code> file.</p>
<div class="highlight"><pre><span></span><span class="c">" F5 word wrap mode (great for writing blog posts!)</span>
<span class="k">set</span> <span class="nb">wrap</span>
<span class="nb">nnoremap</span> <span class="p"><</span>F5<span class="p">></span> :<span class="k">set</span> <span class="nb">linebreak</span><span class="p"><</span>CR<span class="p">></span>
<span class="nb">nnoremap</span> <span class="p"><</span>C<span class="p">-</span>F5<span class="p">></span> :<span class="k">set</span> <span class="nb">nolinebreak</span><span class="p"><</span>CR<span class="p">></span>
</pre></div>
<p>The first line turns the <code>wrap</code> option on. The second line binds <code>:set linebreak<CR></code> to <code>F5</code> in normal mode. The last line binds the reverse to <code>Ctrl</code> + <code>F5</code>. <code><CR></code> is a carriage return, otherwise known as the <code>enter</code> or <code>return</code> button.</p>
<p>So hitting <code>F5</code> in normal mode effectively types out <code>:set linebreak</code> then hits <code>enter</code> for you, rendering much more readable text for when you are not just writing code!</p>
<div class="highlight"><pre><span></span>This is a medium paragraph of text. Everything is all fine and dandy until
you get to the end of the line. Then, whatever text you just wrote gets cut
off precisely when you reach the column width of your Vim window. This
leads to awkward and hard to read paragraphs!
</pre></div>
<p><span id="note">For those of you that are curious, Vim will automatically break the line as soon as it encounters any of these characters <code>^I !@*-+;:,./?</code>. You can change that default by redefining the <code>breakat</code> option. See <a href="http://vim.wikia.com/wiki/Word_wrap_without_line_breaks">here</a> for details.</span></p>Trying out the static blog thing2013-01-08T16:35:00-08:002013-01-08T16:35:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-08:/posts/trying-out-the-static-blog-thing.html<p>Setting up a static blog site using Pelican</p><p>Since I started actively programming a few months ago, I've learned much about what technology I take for granted. In order to help me appreciate the many abstractions that our lives are built upon, I've made it my goal to be more technologically self-sufficent. The first step was to revamp my <a href="http://www.sitongpeng.com">personal website</a>. Next up was to move my code blog from Tumblr to my own domain, and then rebuild it on top of a static site/blog generator. That way, I would have complete ownership and control over my own posts.</p>
<h2>Static what nots?</h2>
<p>Static site generators do what they advertise. They take some content you provide, then generate a pre-determined set of static html pages that are web ready. The idea here is that once you finish setting up the styling and format of your site, you can simply focus on <strong><em>writing content</em></strong>. Of course, they have boiler plate templates ready for you too, if you'd rather jump right into writing.</p>
<h2>Getting set up</h2>
<p>You should certainly consult the <a href="https://pelican.readthedocs.org">Pelican docs</a> for the full guide, but here's my general guide on how to get started.</p>
<p>Pelican is written in Python (major selling point for me), so install it and it's dependencies using virtualenv and pip. Pelican only supports <a href="http://docutils.sourceforge.net/rst.html">reST</a> out of the box but provides <a href="http://daringfireball.net/projects/markdown/">Markdown</a> support upon installation of the <a href="http://packages.python.org/Markdown/">Python-Markdown</a> library. I use Markdown for my posts.</p>
<p>Then, you'll want to make a <code>settings.py</code> file somewhere in your project folder. This file will hold the global variables you set for Pelican. The important ones include:</p>
<div class="highlight"><pre><span></span>AUTHOR = 'YOUR NAME'
SITENAME = 'YOUR SITE NAME'
SITEURL = 'http://your-site.com'
</pre></div>
<p>For the purposes of setting up a blog on Pelican, you will want to set <code>DEFAULT_PAGINATION</code> to be the (number of posts)/page and <code>DEFAULT_ORPHANS</code> as the largest remainder of posts you'll allow on your last page. For my setup, I selected 5 posts/page, and no more than 3 posts on the last page (so up to 8 posts on the last page).</p>
<p>You can browse over all my selected settings <a href="https://github.com/stoneG/blarg/blob/master/settings.py">here</a>.</p>
<h2>Making it yours</h2>
<p>Now, you can certainly use the <a href="https://github.com/getpelican/pelican-themes/blob/master/notmyidea-cms-fr/screenshot.png">default theme</a> provided by Pelican, or one of their other <a href="https://github.com/getpelican/pelican-themes/blob/master/waterspill/screenshot.png">sample themes</a>, but I prefer to make a theme that suits my own tastes. Reading the Pelican documentation and working through the quickstart guide took up half of my weekend, which means I spent the other half on designing my theme.</p>
<p>You'll need some familiarity with <a href="http://jinja.pocoo.org/docs/">Jinja2</a> templates. At the minimum, you should read about the conditionals/loop syntax (especially loop attributes) and template inheritance (include and block). I believe Jinja2's templating system is similar to Django's, so you should feel at home if that's your forte.</p>
<p>Pelican is specific about what file structure it wants in a custom theme. The <a href="http://docs.getpelican.com/en/3.1.1/themes.html">documentation</a> outlines the structure, but doesn't give you adequate information on what attributes you can access from variable objects. If you need specific functionality beyond what objects and object attributes others have done in the sample themes, you'll probably just need to read through the Pelican source or ask some questions in their IRC channel.</p>
<p>I ended up starting with the default theme (called: notmyidea) templates and stripping it of everything I didn't want to use. For instance, I had no need for the category and author functionalities. I don't want to categorize posts and I'll be the only author on this blog, therefore, I did not supply:</p>
<div class="highlight"><pre><span></span>categories.html
category.html
author.html
authors.html
</pre></div>
<p>Pelican is smart enough to just use it's base templates from the Simple theme if you don't provide all the desired html templates.</p>
<p>You will, however, want to make the basic html frame for your blog and save it as <code>base.html</code>, as all other html templates will inherit from it. Otherwise, use the default theme's templates as a guide for building your custom templates.</p>
<p>Once you have your html templates set, you'll want to work on the CSS, which you will save in <code>static/css</code> folder.</p>
<p>The theme for this blog is <a href="https://github.com/stoneG/blarg/tree/master/themes/sitong">here</a>. Please give me a shoutout in the footer if you want to use it ;).</p>
<h2>Workflow</h2>
<p>So once you have your theme, you're ready to create content! I host my pages on <a href="http://pages.github.com/">Github Pages</a>, but you choose your own host.</p>
<p>Let's go through how I am publishing this post. First I write it (in vim!) and save it in my content folder, which stores all my posts for this year.</p>
<div class="highlight"><pre><span></span>content/2013/trying-out-the-static-blog-thing.md
</pre></div>
<p>I like to move out to the root of my Blog folder, then run Pelican to update all my static pages.</p>
<div class="highlight"><pre><span></span>$ pelican content/2013/ -s path/to/settings.py
</pre></div>
<p>The new static pages will be placed in</p>
<div class="highlight"><pre><span></span>output/
</pre></div>
<p>but you can always change that path in your <code>settings.py</code>.</p>
<p>Then I simply <code>$ git add .</code> in my output folder, throw on a commit message, then push it to Github.</p>
<h2>Final thoughts</h2>
<p>The entire set up process takes a bit of time, especially if you're making your own theme, but it's always nice to have ownership over your own content. That's just something you don't get on Tumblr or other browser based blogs. Pelican is an awesome option for anyone looking for a static blog generator and wanting to work in Python, I heartily recommend it.</p>On to better things2013-01-06T18:00:00-08:002013-01-06T18:00:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-06:/posts/on-to-better-things.html<p>Migrating my code blog to my personal domain</p><p>Pretty odd to have committed to writing 100 meaningful blog posts this year, and then promptly not post until Jan 6th. But as you can tell, my excuse is that I was spending all weekend building my new blog. Well I'm glad to say, <em><a href="http://blog.sitongpeng.com">here it is</a></em>. </p>
<p>I'm now running on the static site generator, <a href="http://docs.getpelican.com/">Pelican</a>. It's awesome because it is actively developed (version 3.1.1 as of 12/4/12) and it is written in Python, which means I didn't have to default to <a href="http://jekyllrb.com/">Jekyll</a>. It's not that I'm averse to Jekyll, I'd just rather work in the language I'm most comfortable in (<em>not Ruby</em>). Anyways, things I'm most excited about:</p>
<ul>
<li>Writing all my posts in Markdown</li>
<li>Being hosted on Github Pages</li>
<li>Having all my posts saved on my Dropbox</li>
<li>New syntax highlighting color scheme</li>
<li>Actually using my own domain</li>
</ul>
<p>I'm planning on writing about my experience building this blog in a post later this week. Stay tuned.</p>
<p>(find old posts on my <a href="http://hellositong.tumblr.com">tumblr</a>)</p>Programming Resolutions2013-01-02T19:23:00-08:002013-01-02T19:23:00-08:00Sitong Pengtag:blog.sitongpeng.com,2013-01-02:/posts/programming-resolutions.html<p>Last year was the first year in a long time that I did not make any
resolutions over the year. I’d like to get back to it this year, with a
few that I should be able to keep.</p>
</p><ol class="arabic simple">
<li>Articulation: 100 posts about programming things I’ve encountered and …</li></ol><p>Last year was the first year in a long time that I did not make any
resolutions over the year. I’d like to get back to it this year, with a
few that I should be able to keep.</p>
</p><ol class="arabic simple">
<li>Articulation: 100 posts about programming things I’ve encountered and want to share.</li>
<li>Get involved: Contribute a couple patches or a bug fix to an open source project.</li>
<li>Push myself: Do a weekend project and get it on the front page of HN.</li>
<li>Read more books: I need to expand my knowledge beyond just reading the news and blogs.</li>
</ol>
</p><p>Here’s to a great 2013!</p>
</p>