<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Vairoj</title>
 <link href="http://vairoj.com/atom.xml" rel="self"/>
 <link href="http://www.vairoj.com/"/>
 <updated>2013-11-24T17:00:53-08:00</updated>
 <id>http://www.vairoj.com/</id>
 <author>
   <name>Vairoj Arunyaangkul</name>
   <email>e.jelly@gmail.com</email>
 </author>
 
 
 <entry>
   <title>Create pre-allocated nested lists in Python</title>
   <link href="http://www.vairoj.com/2011/07/create-pre-allocated-nested-list-in-python.html"/>
   <updated>2011-07-03T00:00:00-07:00</updated>
   <id>http://vairoj.com/2011/07/create-pre-allocated-nested-list-in-python</id>
   <content type="html">&lt;p&gt;Python programmers should be familiar with the following idiom:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; &amp;quot;A&amp;quot; * 3
&amp;quot;AAA&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It can be used to create pre-allocated lists, mimicking arrays.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; [0] * 3
[0, 0, 0]
&amp;gt;&amp;gt;&amp;gt; [None] * 3
[None, None, None]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Thus, to a pre-allocated nested list, i.e. a 2-dimensional array representing a matrix, the first thing that came to my mind is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; [[0] * 3] * 3
[[0, 0, 0],
 [0, 0, 0],
 [0, 0, 0]]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But that is wrong, unfortunately. Though it might not be obvious at first, assigning value to an entry changes the values in every row.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; a[0][0] = 1
[[1, 0, 0],
 [1, 0, 0],
 [1, 0, 0]]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It actually turns out that the &lt;code&gt;*&lt;/code&gt; operator doesn&amp;#8217;t create copies of a specified object, but rather &lt;a href='http://stackoverflow.com/questions/3587215/python-dynamic-nested-list/3587269#3587269'&gt;repeats the reference to that same object&lt;/a&gt;. This explains why it is no issue when the created objects are immutable. It doesn&amp;#8217;t matter whether there are multiple references to the same immutable object; the object&amp;#8217;s state cannot be changed so there is no harm. The only thing you can do is to change the reference to another object entirely.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; a = [&amp;quot;A&amp;quot;] * 3
[&amp;quot;A&amp;quot;, &amp;quot;A&amp;quot;, &amp;quot;A&amp;quot;]
&amp;gt;&amp;gt;&amp;gt; a[0] = &amp;quot;B&amp;quot;
[&amp;quot;B&amp;quot;, &amp;quot;A&amp;quot;, &amp;quot;A&amp;quot;]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On the other hand, mutable objects are modifiable. When the state of a mutable object is altered, all references to that object will reflect that changes.&lt;/p&gt;

&lt;p&gt;The gotcha is perhaps hardly observable because most Python&amp;#8217;s built-in types are immutable. List and other container types are mutable, however. Therefore when you create nested lists, i.e. list of lists, the issue is apparent.&lt;/p&gt;

&lt;p&gt;To properly create pre-allocated lists, use &lt;a href='http://docs.python.org/tutorial/datastructures.html#list-comprehensions'&gt;list comprehension&lt;/a&gt; instead:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; [0 for x in range(3)]
[0, 0, 0]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And for nested lists:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; m = [[0 for x in range(3)] for x in range(3)]
[[0, 0, 0],
 [0, 0, 0],
 [0, 0, 0]]
&amp;gt;&amp;gt;&amp;gt; m[0][0] = 1
[[1, 0, 0],
 [0, 0, 0],
 [0, 0, 0]]&lt;/code&gt;&lt;/pre&gt;</content>
 </entry>
 
 <entry>
   <title>Google Code Jam 2011 My take on Bot Trust</title>
   <link href="http://www.vairoj.com/2011/05/google-code-jam-2011-my-take-on-bot-trust.html"/>
   <updated>2011-05-08T00:00:00-07:00</updated>
   <id>http://vairoj.com/2011/05/google-code-jam-2011-my-take-on-bot-trust</id>
   <content type="html">&lt;p&gt;I enjoyed yesterday&amp;#8217;s qualification round of &lt;a href='http://code.google.com/codejam/contests.html'&gt;Google Code Jam 2011&lt;/a&gt;. Once figured out, the problems are arguably straightforward. Code Jam website also provides informative explanation for the solutions to each problems.&lt;/p&gt;

&lt;p&gt;Nevertheless, I want to chip in on the Bot Trust problem. Code Jam&amp;#8217;s solution is a straightforward one, though I find that my solution is more concise yet still simple to understand. Let&amp;#8217;s look at the code:&lt;/p&gt;
&lt;script src='https://gist.github.com/961766.js?file=bottrust.py'&gt;bottrust.py&lt;/script&gt;
&lt;p&gt;The idea is simple, as the problem wants the minimum time to complete the order, this algorithm does exactly that without the need for calculation at every time increment. Instead, it iterates through each command and calculates the time the corresponding bot completed the command. Last location and time of both bots are maintained. If the time a bot uses is less than the current &lt;code&gt;time&lt;/code&gt;, it means that the bot moved in place earlier but has to wait for the other bot to push the switch, hence the time it takes is either its moving time or the latest time, whichever is larger. The +1 at the end is the time used to push the switch.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Upgrade OCZ Vertex 2 firmware on OS X</title>
   <link href="http://www.vairoj.com/2011/05/upgrade-ocz-vertex-2-firmware-on-os-x.html"/>
   <updated>2011-05-03T00:00:00-07:00</updated>
   <id>http://vairoj.com/2011/05/upgrade-ocz-vertex-2-firmware-on-os-x</id>
   <content type="html">&lt;p&gt;Those who use OCZ&amp;#8217;s Sandforce-based SSDs such as Vertex 2 with a Mac perhaps question the possibility of upgrading the drive&amp;#8217;s firmware. From OCZ&amp;#8217;s &lt;a href='http://www.ocztechnology.com/ssd_tools/OCZ_Vertex_2,_Vertex_LE,_Agility_2/'&gt;download page&lt;/a&gt;, it looks like the firmware update tool only supports Windows. In fact, OCZ also provides a firmware update tool for Linux. But for some reason, OCZ decided to conceal the link in a &lt;a href='http://www.ocztechnologyforum.com/forum/showthread.php?82289-OCZ-SandForce-Linux-based-firmware-update-tool'&gt;forum post&lt;/a&gt; rather than making it visible on their download page.&lt;/p&gt;

&lt;p&gt;The &lt;a href='http://www.ocztechnologyforum.com/forum/showthread.php?82289-OCZ-SandForce-Linux-based-firmware-update-tool'&gt;OCZ-Sandforce Linux-based firmware update tool&lt;/a&gt; can be used together with a Linux Live CD to boot up a Mac machine and flash the SSD&amp;#8217;s firmware. One OCZ forum member posted a very &lt;a href='http://www.ocztechnologyforum.com/forum/showthread.php?85402-Patching-Firmware-on-OS-X-only-System-(Fix-for-quot-frozen-quot-harddrive)'&gt;nice detailed instruction&lt;/a&gt; on the topic. I&amp;#8217;ve updated my firmware from 1.27 to 1.33 following the instruction and it works perfectly. The update fixes the hibernation issue on the Mac and now I can hibernate my MacBook Pro again. There is one caveat: PCLinuxOS ISO image cannot be burned properly to DVD. You&amp;#8217;ll need CDR/RW for that.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[9/5/11]&lt;/em&gt;: You might also want to check out &lt;a href='http://www.ocztechnologyforum.com/forum/forumdisplay.php?237-OCZ-SSD-Support-for-Linux-and-Apple-OSX'&gt;Linux and OS X forum&lt;/a&gt; at OCZ website. People has been posting unofficial guides on upgrading firmware on OS X there, and you may find one that suits your scenario better than others. For instance, there is &lt;a href='http://www.ocztechnologyforum.com/forum/showthread.php?92009-Updating-firmware-of-Vertex-3-Agility-3-Solid-3-drives-on-2011-Macs-using-a-Linux-CD'&gt;an instruction specific to MBP 2011&lt;/a&gt; if you have trouble using the above method.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Correctly install pyspatialite</title>
   <link href="http://www.vairoj.com/2011/04/pyspatialite.html"/>
   <updated>2011-04-15T00:00:00-07:00</updated>
   <id>http://vairoj.com/2011/04/pyspatialite</id>
   <content type="html">&lt;p&gt;You need &lt;a href='http://code.google.com/p/pyspatialite/'&gt;pyspatialite&lt;/a&gt; to use spatialite with Python code. If you install it with easy_install, probably you will run into an error, &lt;code&gt;symbol not found: _iconv&lt;/code&gt;, when importing the module. The tarball at &lt;a href='http://code.google.com/p/pyspatialite/'&gt;pyspatialite website&lt;/a&gt; has the problem fixed though. Apparently, the version available at &lt;a href='http://pypi.python.org/pypi/pyspatialite/2.6.1'&gt;easy_install repository&lt;/a&gt; is not up-to-date.&lt;/p&gt;

&lt;p&gt;Therefore, in the meantime, don&amp;#8217;t use easy_install and download the tarball directly from the website. Note that it is not necessary to install libspatialite separately as pyspatialite includes the library and will build it as part of &lt;code&gt;python setup.py install&lt;/code&gt; process. Also, if pyspatialite has already been installed through easy_install, you need to &lt;a href='http://thingsilearned.com/2009/04/13/easy_install-uninstalling/'&gt;uninstall it&lt;/a&gt; first, otherwise; that version will still get picked up when importing the module.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>What is Amazon Corporate Housing?</title>
   <link href="http://www.vairoj.com/2011/03/amazon-corporate-housing.html"/>
   <updated>2011-03-31T00:00:00-07:00</updated>
   <id>http://vairoj.com/2011/03/amazon-corporate-housing</id>
   <content type="html">&lt;p&gt;If you get an internship offer from Amazon.com, one thing you need to decide as part of your offering package is housing option. Essentially you are given two choices: one-time stipend or Amazon-provided housing. The former is quite obvious&amp;#8212;Amazon pays you a fixed amount of money and you are on your own. However, if you are like me, it may not be clear at first what Amazon corporate housing is like. Not only that you don&amp;#8217;t get the stipend with this option, part of your salary will also be deducted for rental payment. Is corporate housing option really worth it?&lt;/p&gt;

&lt;p&gt;With corporate housing option, an apartment unit is rented for you. The apartment could be one of many standard apartments in Seattle. As you may already aware of what corporate housing offers, here are the quick summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose to live alone, or with a roommate in two-bedroom apartment. Obviously you pay less on the latter option.&lt;/li&gt;

&lt;li&gt;If you choose to live with a roommate, Graebel does roommate matching with another Amazon intern for you.&lt;/li&gt;

&lt;li&gt;The apartment is fully furnished. There are TV, internet, couches, dining set, and kitchenwares. Just move in and fill the fridge. In addition, one parking spot is included if you will be driving.&lt;/li&gt;

&lt;li&gt;Housekeeping service is included.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simply put, the corporate housing option is favorable for interns. Living there for just 3 months, you might not want to go through the hassles of finding the places, buying furnitures, and so forth. Nevertheless, if you&amp;#8217;re comfortable with those stuffs, the stipend option gives you freedom. Folks who find their own places could make extra cash e.g. by renting a place in some farther areas.&lt;/p&gt;

&lt;p&gt;Last summer, I lived at &lt;a href='http://www.onethousand8thavenueapts.com'&gt;this place&lt;/a&gt; with a nice roommate. The apartment was 15 minute walk to Amazon office in International District where I worked. While the unit was pretty decent, feature-wise, it was no way like the pictures on its website. If you&amp;#8217;ve ever shopped for apartments, you probably know what I&amp;#8217;m talking about.&lt;/p&gt;

&lt;h1 id='a_few_suggestions'&gt;A few suggestions&lt;/h1&gt;

&lt;p&gt;Whichever option you take, here are some tips to avoid surprises:&lt;/p&gt;

&lt;h2 id='graebel_may_not_be_your_friend'&gt;Graebel may not be your friend&lt;/h2&gt;

&lt;p&gt;If my experience is any indication, communicating with Graebel could be frustrating. In my case, I couldn&amp;#8217;t reach my contact person until 3 days before my start date. That means flight ticket, housing, and everything had to be rushed in the last minute.&lt;/p&gt;

&lt;h2 id='know_where_you_will_be_working_at'&gt;Know where you will be working at&lt;/h2&gt;

&lt;p&gt;Amazon offices used to scattered around buildings throughout downtown areas, depending on what team you will be working with. However, they had been moving to their new campus at &lt;a href='http://en.wikipedia.org/wiki/South_Lake_Union'&gt;South Lake Union&lt;/a&gt; and I assume that they are all at SLU now. Check with your HR person so you have an idea how your daily commute will be. Personally I find public transportation in Seattle pretty convenient. If you want to learn about bus routes check out &lt;a href='http://metro.kingcounty.gov'&gt;King County Metro Transit&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='neighborhoods'&gt;Neighborhoods&lt;/h2&gt;

&lt;p&gt;Different neighborhoods in Seattle have different vibes. You may want to research on areas that you prefer or areas that you want to avoid. Although Seattle is considered a safe city, some people felt a bit uneasy in &lt;a href='http://www.neighborhoodscout.com/wa/seattle/crime'&gt;some downtown areas&lt;/a&gt; especially at night.&lt;/p&gt;

&lt;h2 id='dont_be_fooled_by_pretty_photos'&gt;Don&amp;#8217;t be fooled by pretty photos&lt;/h2&gt;

&lt;p&gt;When you are offered with a place, look it up online. See how the area is like. Find some reviews on Google Maps. The apartment website itself doesn&amp;#8217;t tell you much. If you don&amp;#8217;t like the place, you could ask for a change. After all, you will be living there for 3 months.&lt;/p&gt;

&lt;p&gt;I hope this information helps a bit. Feel free to post questions about Seattle or Amazon internship in the comment below. You can also get in touch with me in Twitter (&lt;a href='http://twitter.com/ejel'&gt;@ejel&lt;/a&gt;) too.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>GitX couldn't connect to app server</title>
   <link href="http://www.vairoj.com/2011/03/gitx-couldnt-connect-to-app-server.html"/>
   <updated>2011-03-15T00:00:00-07:00</updated>
   <id>http://vairoj.com/2011/03/gitx-couldnt-connect-to-app-server</id>
   <content type="html">&lt;p&gt;If you install &lt;a href='http://gitx.frim.nl'&gt;GitX&lt;/a&gt; through &lt;a href='http://www.macports.org'&gt;MacPorts&lt;/a&gt; and try launching it from the the shell, you might be greeted with an error:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt; 
% gitx
Couldn&amp;#39;t connect to app server!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What you need to do you is to launch GitX.app at least once. MacPorts puts it at &lt;code&gt;/Applications/MacPorts/GitX.app&lt;/code&gt;. It seems that some initialization is required before the command-line tool can be used.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Upgraded MacBook Pro with SSD</title>
   <link href="http://www.vairoj.com/2011/02/upgraded-macbook-pro-with-ssd.html"/>
   <updated>2011-02-16T00:00:00-08:00</updated>
   <id>http://vairoj.com/2011/02/upgraded-macbook-pro-with-ssd</id>
   <content type="html">&lt;p&gt;I finally joined the SSD upgrade train. After resisting the itch for some time, eventually posts from &lt;a href='http://www.codinghorror.com/blog/2010/09/revisiting-solid-state-hard-drives.html'&gt;Coding Horror&lt;/a&gt;, &lt;a href='http://akitaonrails.com/2011/01/02/off-topic-upgrading-my-macbook-pro-with-an-ssd'&gt;AkitaOnRails&lt;/a&gt;, and &lt;a href='http://lifehacker.com/#!5740655/why-the-limitations-of-ssds-are-actually-good'&gt;Lifehacker&lt;/a&gt; won over my temptation. I would say the performance gain is fairly dramatic like what people say. On my MacBook Pro, the whole boot time (from power on until login finishes) went down from 105 to merely 30 seconds&amp;#8212;almost 4 times faster. Everything is of course a lot more snappier. Applications such as Chrome, TextMate, or Twitter launch instantly. If you are interested, you can find more detail about SSD including benchmark results from the mentioned posts.&lt;/p&gt;

&lt;p&gt;&lt;img alt='OCZ Vertex 2 installed in my MBP' src='http://farm6.static.flickr.com/5099/5456675547_eee9b62331.jpg' /&gt;&lt;/p&gt;

&lt;p&gt;The SSD I bought is the &lt;a href='http://www.amazon.com/OCZ-Technology-Vertex-2-5-Inch-OCZSSD2-2VTXE240G/dp/B003NE5JCY/?tag=vairojlog-20'&gt;240GB OCZ Vertex 2&lt;/a&gt;. I chose OCZ over &lt;a href='http://www.amazon.com/Crucial-RealSSD-2-5-Inch-Transfer-CTFDDAC256MAG-1G1CCA/dp/B003WAN5SY/?tag=vairojlog-20'&gt;Crucial RealSSD&lt;/a&gt; (which also receives many positive reviews) because Crucial seems to yield optimal performance only when used with fast SATA 3.0 controllers.&lt;/p&gt;

&lt;p&gt;Since my MacBook Pro is the early-2008 model, changing the drive is a little more involved that I expected. Fortunately, &lt;a href='http://www.youtube.com/watch?v=K9r1UAVq9AU'&gt;this YouTube video&lt;/a&gt; provides a step-by-step instruction including the required tools. Thus be sure to check out the video before trying to crack the case to avoid damaging your MBP.&lt;/p&gt;

&lt;p&gt;One outcome from this upgrade is I no longer need to keep many apps opened anymore. Usually, there are a few apps that are needed occasionally. However, when needed, they have to show up fast enough not to divert me away from my flow&amp;#8211;e.g. things like Dictionary, TextMate, or even Dashboard. Previously, I kept these apps opened all the time but the problem was they cluttered my Dock and Alt-Tab. I also rarely used Dashboard because of its initial startup time. Thanks to SSD&amp;#8217;s fast access time, now I can launch the apps whenever I need and close them immediately after I am done. I also find myself using Dashboard widgets more and more.&lt;/p&gt;

&lt;p&gt;There is one problem with the new drive though. My laptop crashes with kernel panic every time it wakes up from hibernation. The problem appears to be &lt;a href='http://bit.ly/hrzgBA'&gt;Vertex 2-specific problem&lt;/a&gt; though. Anyway, some folks recommend &lt;a href='http://www.ocztechnologyforum.com/forum/showthread.php?85076-Switch-off-hibernate-in-OS-X'&gt;turning off hibernation&lt;/a&gt; completely when you are using SSD to prolong its life. I am still undecided on the approach though.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Powered by Jekyll</title>
   <link href="http://www.vairoj.com/2011/02/powered-by-jekyll.html"/>
   <updated>2011-02-10T00:00:00-08:00</updated>
   <id>http://vairoj.com/2011/02/powered-by-jekyll</id>
   <content type="html">&lt;p&gt;Formatting posts on Wordpress is tedious. It is one of the reasons that had kept me from regular blogging. I would prefer to write posts in my favorite text editor using some sane format such as &lt;a href='http://daringfireball.net/projects/markdown'&gt;Markdown&lt;/a&gt;. Finally, after stumbled on a &lt;a href='http://programmers.stackexchange.com/questions/10880/whats-the-best-platform-for-blogging-about-coding'&gt;Stack Exchange question&lt;/a&gt; about blogging platforms, I finally found my solution. It is &lt;a href='http://jekyllrb.com'&gt;Jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jekyll is essentially, in its own words, &amp;#8220;a simple blog aware, static site generator&amp;#8221;. There are &lt;a href='http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html'&gt;already&lt;/a&gt; &lt;a href='http://paulstamatiou.com/how-to-wordpress-to-jekyll'&gt;a few&lt;/a&gt; &lt;a href='http://henrik.nyh.se/2009/04/jekyll'&gt;places&lt;/a&gt; discussing its virtues so I won&amp;#8217;t repeat it here.&lt;/p&gt;

&lt;p&gt;The thing that touches me most is its simplicity. Now I can just fire up my text editor, write the prose, save the file, and commit it to my Git repository. All posts belong with me, no longer obscured in a MySQL database hosted somewhere I don&amp;#8217;t know.&lt;/p&gt;

&lt;p&gt;Also, because of its simplicity, I feel excited to design own website for the first time. This thought never occurs to me when using Wordpress as theming Wordpress seems too much of a hassle.&lt;/p&gt;

&lt;p&gt;Hopefully this move will bring me back to more frequent blogging.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Installing libxml-ruby on Windows: The painless way</title>
   <link href="http://www.vairoj.com/2010/06/installing-libxml-ruby-on-windows-the-painless-way.html"/>
   <updated>2010-06-17T00:00:00-07:00</updated>
   <id>http://vairoj.com/2010/06/installing-libxml-ruby-on-windows-the-painless-way</id>
   <content type="html">&lt;p&gt;Most of the pages I googled for how to install LibXml Ruby on Windows mention building the required libraries on Windows. Not only that it is a hassle, but I could not make it works either. I finally found a straightforward way and hope it can save you some time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;em&gt;As you guys pointed out in the comments, I updated the instruction with some more detail and steps that I didn&amp;#8217;t mention previously.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Prerequisite: Make sure that you already have &lt;code&gt;rake&lt;/code&gt; installed.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    gem install rake

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You also probably need Ruby DevKit in order to install native libraries. Follow &lt;a href='https://github.com/oneclick/rubyinstaller/wiki/Development-Kit'&gt;DevKit Installation Instructions&lt;/a&gt; on its wiki page.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;As mentioned on &lt;a href='http://libxml.rubyforge.org/rdoc/index.html'&gt;LibXml RDoc&lt;/a&gt;, you need to download Win32 RubyGem which includes all the required binaries. This way you don&amp;#8217;t have to go through the hassle of building all the libraries yourself. To install libxml with prebuilt binaries for Windows, executing the following command: (Thanks @Carl for the suggestion)&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    gem install libxml-ruby --platform x86-mswin32-60

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If there is error at this step make sure you have DevKit installed.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The DLLs must also be available in PATH environment variable. Assuming that your &lt;code&gt;&amp;lt;ruby-path&amp;gt;\bin&lt;/code&gt; is already in your PATH (as set by RubyInstaller), copy &lt;code&gt;libxml2-2.dll&lt;/code&gt; and &lt;code&gt;libiconv2.dll&lt;/code&gt; from &lt;code&gt;&amp;lt;ruby-path&amp;gt;\lib\gems\1.8\gems\libxml-ruby-xxx\lib&lt;/code&gt; to your &lt;code&gt;&amp;lt;ruby-path&amp;gt;\bin&lt;/code&gt; directory. Your &lt;code&gt;&amp;lt;ruby-path&amp;gt;&lt;/code&gt; should be something like &lt;code&gt;C:\Ruby187&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Test if everything works by entering &lt;code&gt;irb&lt;/code&gt; and require both &lt;code&gt;rubygems&lt;/code&gt; and &lt;code&gt;libxml&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;irb&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;main&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;&lt;span class='mo'&gt;001&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
&lt;span class='n'&gt;irb&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;main&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;&lt;span class='mo'&gt;002&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;libxml&amp;#39;&lt;/span&gt;
&lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
&lt;span class='n'&gt;irb&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;main&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;&lt;span class='mo'&gt;003&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And that&amp;#8217;s it. Now you should be able to use LibXml with your Ruby code!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Replace Python range() with xrange() for speed</title>
   <link href="http://www.vairoj.com/2010/04/replace-python-range-with-xrange-for-speed.html"/>
   <updated>2010-04-29T00:00:00-07:00</updated>
   <id>http://vairoj.com/2010/04/replace-python-range-with-xrange-for-speed</id>
   <content type="html">&lt;p&gt;A few weeks ago I stumbled on an interesting programming problem at &lt;a href='http://www.codechef.com/APRIL10/problems/TRIP/'&gt;CodeChef&lt;/a&gt;. The problem reminded me of dynamic programming thus I decided to try implementing a solution in Python.&lt;/p&gt;

&lt;p&gt;Initially, the main part of the algorithm I implemented looked something like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;range&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
  &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;range&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='c'&gt;# a few lines of basic comparisons,&lt;/span&gt;
    &lt;span class='c'&gt;# calculations, and assignments&lt;/span&gt;
    &lt;span class='c'&gt;# ......&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just a simple nested loop. When I ran the code with the test input where &lt;code&gt;x&lt;/code&gt; is 100000 and &lt;code&gt;y&lt;/code&gt; is 1000, however, it took 60 seconds to complete! Far from the problem&amp;#8217;s time limit of 2 seconds. Although this is a nested loop, the running time is O(xy) which should not be that long.&lt;/p&gt;

&lt;p&gt;To my surprise, the result from &lt;a href='http://docs.python.org/library/profile.html'&gt;cProfile&lt;/a&gt; showed that most time were spent on calls to &lt;code&gt;range&lt;/code&gt; function. After spending a few minutes googling for an explanation, it was apparent to me. When calling &lt;code&gt;range&lt;/code&gt; function, it creates a list of all objects in the specified range all at once. In my case, the range call in the outer loop creates one million number objects right away. And that&amp;#8217;s why it was slow.&lt;/p&gt;

&lt;p&gt;The remedy? &lt;a href='http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Usexrangeinsteadofrange'&gt;Use xrange instead of range&lt;/a&gt;. &lt;code&gt;xrange&lt;/code&gt; is similar to &lt;code&gt;range&lt;/code&gt; but it is a generator object which does not create any object immediately, but rather when you pull from the generator.&lt;/p&gt;

&lt;p&gt;Changing &lt;code&gt;range&lt;/code&gt; to &lt;code&gt;xrange&lt;/code&gt; in the above code reduced the running time from 60 to 6 seconds right away. The moral of this story is to consider using &lt;code&gt;xrange&lt;/code&gt; instead of &lt;code&gt;range&lt;/code&gt; when the number is large. Note that this only applies to Python 2.x though. In Python 3 &lt;code&gt;range&lt;/code&gt; provides an iterator over range and thus &lt;code&gt;xrange&lt;/code&gt; was removed.&lt;/p&gt;

&lt;p&gt;Continue further, cProfile showed that the time-consuming section now is calls to &lt;code&gt;raw_input&lt;/code&gt;. Yes, I naively read a million line of inputs by calling &lt;code&gt;raw_input&lt;/code&gt; in a loop. After changing the part to using sys.stdin.readlines(), the running time was decreased to 2.7 seconds. Here is the final version of my code:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;num_stations&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fuel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nb'&gt;int&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;raw_input&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='p'&gt;()]&lt;/span&gt;
&lt;span class='c'&gt;# read station distances&lt;/span&gt;
&lt;span class='n'&gt;dist&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nb'&gt;int&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;sys&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;stdin&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;readlines&lt;/span&gt;&lt;span class='p'&gt;()]&lt;/span&gt;

&lt;span class='n'&gt;stops&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;MAX_DIST&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nb'&gt;len&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dist&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;num_sols&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nb'&gt;len&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dist&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;stops&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;
&lt;span class='n'&gt;num_sols&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
&lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;xrange&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;len&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dist&lt;/span&gt;&lt;span class='p'&gt;)):&lt;/span&gt;
  &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;xrange&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='c'&gt;# backtrack until out of fuel range&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;dist&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='n'&gt;dist&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;fuel&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='k'&gt;break&lt;/span&gt;
    &lt;span class='c'&gt;# assert dist[i] - dist[j] &amp;lt;= fuel&lt;/span&gt;
    &lt;span class='n'&gt;cur_stop&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;stops&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;stops&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;cur_stop&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='c'&gt;# new min stops&lt;/span&gt;
      &lt;span class='n'&gt;stops&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;cur_stop&lt;/span&gt;
      &lt;span class='n'&gt;num_sols&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;num_sols&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='c'&gt;# reset number of solutions&lt;/span&gt;
    &lt;span class='k'&gt;elif&lt;/span&gt; &lt;span class='n'&gt;cur_stop&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;stops&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]:&lt;/span&gt; &lt;span class='c'&gt;# another optimal solution&lt;/span&gt;
      &lt;span class='n'&gt;num_sols&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
&lt;span class='k'&gt;print&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;%d&lt;/span&gt;&lt;span class='s'&gt; &lt;/span&gt;&lt;span class='si'&gt;%d&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;stops&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;num_sols&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='c'&gt;# remove final stop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I believe that there are still parts which can be further optimized, ideally to meet the 2 seconds time limit. If you have any idea or spot anything wrong, please let me know in the comment.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Hello world!</title>
   <link href="http://www.vairoj.com/2010/01/hello-world.html"/>
   <updated>2010-01-27T00:00:00-08:00</updated>
   <id>http://vairoj.com/2010/01/hello-world</id>
   <content type="html">&lt;p&gt;Finally I have my own blog and website. Don&amp;#8217;t ask me why it took so long. Anyway, I am still not sure what the content of this blog would be. While figuring that out, it would probably be random things that come up to my mind. It might not be as bad as it sounds though.&lt;/p&gt;</content>
 </entry>
 
 
</feed>
