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

<channel>
	<title>a monochromatic oeuvre</title>
	<atom:link href="http://blog.marquiswang.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.marquiswang.com</link>
	<description>&#34;well c&#039;mon, it&#039;s just snow&#34;</description>
	<lastBuildDate>Tue, 24 Jan 2012 01:59:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Adium Sort By Log Size</title>
		<link>http://blog.marquiswang.com/2012/01/22/adium-sort-by-log-size/</link>
		<comments>http://blog.marquiswang.com/2012/01/22/adium-sort-by-log-size/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 20:25:22 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.marquiswang.com/?p=206</guid>
		<description><![CDATA[Back when I was using Pidgin, I loved its &#8220;sort by log size&#8221; feature. It organized your contact list for you, floating your most-talked-to contacts to the top. It was also fun to see which of your friends &#8220;wins&#8221; by being on top. Adium had a plugin that did this, unsurprisingly called the Sort By [...]]]></description>
			<content:encoded><![CDATA[<p>Back when I was using Pidgin, I loved its &#8220;sort by log size&#8221; feature. It organized your contact list for you, floating your most-talked-to contacts to the top. It was also fun to see which of your friends &#8220;wins&#8221; by being on top.</p>
<p>Adium had a plugin that did this, unsurprisingly called the Sort By Log Size Plugin. Unfortunately, it was partly incompatible with Adium 1.4, occasionally preventing the contact list from loading at all. Even worse, it appeared that the plugin had been abandoned, with no updates since June 2009.</p>
<p>For the last several years I have been relying on manually sorting my contacts into ordered groups on Adium, but I finally got my lazy ass off my couch yesterday and fixed the bug myself. I&#8217;m trying to get into contact with the developer, but until then it can be downloaded from my <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL21hcnF1aXN3YW5nL2FkaXVtLXNvcnRieWxvZ3NpemUvZG93bmxvYWRz">Github</a> (<a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL2Rvd25sb2Fkcy9tYXJxdWlzd2FuZy9hZGl1bS1zb3J0Ynlsb2dzaXplL1NvcnRCeUxvZ1NpemVQbHVnaW4uQWRpdW1QbHVnaW4uemlw">direct download</a>).</p>
<p><strong>Update:</strong> The developer has accepted the patch and is providing an update that will be available pending approval! Hooray!  </p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=206" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2012/01/22/adium-sort-by-log-size/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Best Seemingly Useless VIM Trick Ever</title>
		<link>http://blog.marquiswang.com/2010/11/02/best-seemingly-useless-vim-trick-ever/</link>
		<comments>http://blog.marquiswang.com/2010/11/02/best-seemingly-useless-vim-trick-ever/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 22:21:30 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.marquiswang.com/?p=194</guid>
		<description><![CDATA[At some point this summer, I discovered the vim commands Ctrl+A and Ctrl+X. In normal mode, they find the first number on the current line and increment and decrement it, respectively. What&#8217;s your first thought when you read that? Mine was &#8220;Why the heck is that useful enough to be included as default functionality? How [...]]]></description>
			<content:encoded><![CDATA[<p>At some point this summer, I discovered the vim commands Ctrl+A and Ctrl+X. In normal mode, they find the first number on the current line and increment and decrement it, respectively.</p>
<p>What&#8217;s your first thought when you read that? Mine was &#8220;Why the heck is that useful enough to be included as default functionality? How often can you need that? That is a complete waste of a keybinding and is just confusing.&#8221;</p>
<p>Well, I stand partially corrected. It is not <em>completely</em> useless. I have found myself using it several times in the last month or so. My favorite use case is for making lists:</p>
<p>First, type</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;"> 1. Some list element.</pre></div></div>

<p>Then, in normal mode, record the following macro:</p>

<div class="wp_syntax"><div class="code"><pre class="vim" style="font-family:monospace;">qa
Y
p
Ctrl<span style="color: #000000;">-</span>A
q</pre></div></div>

<p>Now, 10@a will perform the macro 10 times, copying the line and auto-incrementing the number each time.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">1. Some list element.
2. Some list element.
3. Some list element.
4. Some list element.
 ... etc.</pre></div></div>

<p>Neat! I&#8217;m still not entirely convinced it&#8217;s actually useful, but its cute nonetheless.</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=194" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2010/11/02/best-seemingly-useless-vim-trick-ever/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Amazon Prime is Ruining My Budget</title>
		<link>http://blog.marquiswang.com/2010/10/27/amazon-prime-make-impulsive-purchases-reaally-easy/</link>
		<comments>http://blog.marquiswang.com/2010/10/27/amazon-prime-make-impulsive-purchases-reaally-easy/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 09:29:38 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://blog.marquiswang.com/?p=182</guid>
		<description><![CDATA[Amazon Prime for students is brilliant. In the last two weeks, just because if I have the slightest impulse to buy something, I can load up Amazon and get it in 2 days, I have bought: 12 pairs of socks (I was running out of clean socks but really didn&#8217;t want to do laundry.) A [...]]]></description>
			<content:encoded><![CDATA[<p>Amazon Prime for students is brilliant. In the last two weeks, just because if I have the slightest impulse to buy something, I can load up Amazon and get it in 2 days, I have bought:</p>
<ul>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMTFXSjlDRz9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDExV0o5Q0c=">12 pairs of socks</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=B0011WJ9CG" border="0" alt="" width="1" height="1" /> (I was running out of clean socks but really didn&#8217;t want to do laundry.)</li>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvMDMxMjM2NzU0Nj9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPTAzMTIzNjc1NDY=">A Wrinkle in Time</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=0312367546" border="0" alt="" width="1" height="1" /> (Partly for a class, partly because I wanted it.)</li>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMDA4VlNKUD9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDAwOFZTSlA=">S-Video Cable</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=B00008VSJP" border="0" alt="" width="1" height="1" /> (Would have bought it from Monoprice, but it would have cost the same after shipping.)</li>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMThPOUpJRz9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDE4TzlKSUc=">Bluetooth Dongle</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=B0018O9JIG" border="0" alt="" width="1" height="1" /> (It was tiny and adorable and I wanted to connect my WiiMote to my media center computer.</li>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMk1LNlFLTz9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDJNSzZRS08="> Bathroom Scale </a> <img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=B002MK6QKO" border="0" alt="" width="1" height="1" /></li>
<p><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMk1LNlFLTz9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDJNSzZRS08="> </a></p>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMk1LNlFLTz9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDJNSzZRS08="></a><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMUlIWEZRSz9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDFJSFhGUUs=">Scalp Massager</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=B001IHXFQK" border="0" alt="" width="1" height="1" /> Tingly!</li>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvMDc2MzYyMjU5MT9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPTA3NjM2MjI1OTE=">Feed</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=0763622591" border="0" alt="" width="1" height="1" /></li>
<li><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMEtPVUs3RT9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDBLT1VLN0U=">Idahoan Mashed Potatoes</a> (Delicious instant mashed potatoes! I would have bought <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2dwL3Byb2R1Y3QvQjAwMEtPVUs2QT9pZT1VVEY4JmFtcDt0YWc9bWFycXVpc3dhbmdjby0yMCZhbXA7bGlua0NvZGU9YXMyJmFtcDtjYW1wPTE3ODkmYW1wO2NyZWF0aXZlPTM5MDk1NyZhbXA7Y3JlYXRpdmVBU0lOPUIwMDBLT1VLNkE=">this one</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=marquiswangco-20&amp;l=as2&amp;o=1&amp;a=B000KOUK6A" border="0" alt="" width="1" height="1" /> but for some dumb reason its twice as expensive. I can justify $16 of mashed potatoes but $36?)</li>
</ul>
<p>Impulsive purchases are just so easy now. Thanks to my good friends at Amazon and their free 2-day shipping, I am now a much poorer college student, but am enriched by instant mashed potatoes and children&#8217;s books. (Good god, I just went through that list and it costs $130. Those little things really do add up.)</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=182" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2010/10/27/amazon-prime-make-impulsive-purchases-reaally-easy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Calvin and Hobbes + NASA Astronomy Picture of the Day</title>
		<link>http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/</link>
		<comments>http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 07:53:09 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.marquiswang.com/?p=156</guid>
		<description><![CDATA[ihaveideas on reddit had an excellent idea. I have been playing with ImageMagick recently so I figured implementing this would be good practice. I think it works so far . Here are some results: Pretty sweet, huh? Code is available here. It&#8217;s kinda hacky right now, but it seems to work. The bash script takes [...]]]></description>
			<content:encoded><![CDATA[<p>ihaveideas on reddit had an excellent <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5yZWRkaXQuY29tL3IvcGljcy9jb21tZW50cy9kOXpmZy9pX3VzZWRfdG9fY2hhbmdlX215X2Rlc2t0b3BfYmFja2dyb3VuZF9ldmVyeV9kYXkvYzB5bzA5aQ==">idea</a>.</p>
<p>I have been playing with ImageMagick recently so I figured implementing this would be good practice.</p>
<p>I think it works so far <img src='http://blog.marquiswang.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Here are some results:<br />

<a href='http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/ch_coronalhaug2010_sdo900/' title='ch_CoronalHaug2010_sdo900'><img width="150" height="150" src="http://blog.marquiswang.com/wp-content/uploads/2010/09/ch_CoronalHaug2010_sdo900-150x150.jpg" class="attachment-thumbnail" alt="ch_CoronalHaug2010_sdo900" title="ch_CoronalHaug2010_sdo900" /></a>
<a href='http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/ch_earthmoon_messenger/' title='ch_earthmoon_messenger'><img width="150" height="150" src="http://blog.marquiswang.com/wp-content/uploads/2010/09/ch_earthmoon_messenger-150x150.jpg" class="attachment-thumbnail" alt="ch_earthmoon_messenger" title="ch_earthmoon_messenger" /></a>
<a href='http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/ch_ngc7635_jurasevich_900c/' title='ch_ngc7635_jurasevich_900c'><img width="150" height="150" src="http://blog.marquiswang.com/wp-content/uploads/2010/09/ch_ngc7635_jurasevich_900c-150x150.jpg" class="attachment-thumbnail" alt="ch_ngc7635_jurasevich_900c" title="ch_ngc7635_jurasevich_900c" /></a>
<a href='http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/ch_smc_jarzyna_900c/' title='ch_SMC_jarzyna_900c'><img width="150" height="150" src="http://blog.marquiswang.com/wp-content/uploads/2010/09/ch_SMC_jarzyna_900c-150x150.jpg" class="attachment-thumbnail" alt="ch_SMC_jarzyna_900c" title="ch_SMC_jarzyna_900c" /></a>
<a href='http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/ch_vltlaser_beletsky/' title='ch_vltlaser_beletsky'><img width="150" height="150" src="http://blog.marquiswang.com/wp-content/uploads/2010/09/ch_vltlaser_beletsky-150x150.jpg" class="attachment-thumbnail" alt="ch_vltlaser_beletsky" title="ch_vltlaser_beletsky" /></a>
</p>
<p>Pretty sweet, huh?</p>
<p>Code is available <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2RhZWRhbHVzLm1hcnF1aXN3YW5nLmNvbS9kcm9wYm94L2Fwb2RjaC56aXA=">here.</a> It&#8217;s kinda hacky right now, but it seems to work.<br />
The bash script takes one argument, the URL of the APOD post. If no argument is given it defaults to the most recent post.</p>
<p>Possible future improvements: Write a program that runs this daily and sets it as your desktop background. That can wait until at least tomorrow.</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=156" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2010/09/06/calvin-and-hobbes-nasa-astronomy-picture-of-the-day/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Auto-Uploading Screenshots in OS X</title>
		<link>http://blog.marquiswang.com/2010/08/08/auto-uploading-screenshots-in-os-x/</link>
		<comments>http://blog.marquiswang.com/2010/08/08/auto-uploading-screenshots-in-os-x/#comments</comments>
		<pubDate>Sun, 08 Aug 2010 23:59:15 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.marquiswang.com/?p=138</guid>
		<description><![CDATA[99% of time I take a screenshot, its to show someone. The workflow there is: Take a screenshot of a selected area with Cmd+Shift+4. OS X saves it to the Desktop. Open a terminal. SCP the file to my web directory. Open the web directory in a browser to make sure the upload worked and [...]]]></description>
			<content:encoded><![CDATA[<p>99% of time I take a screenshot, its to show someone. The workflow there is:</p>
<ol>
<li>Take a screenshot of a selected area with Cmd+Shift+4. OS X saves it to the Desktop.</li>
<li>Open a terminal.</li>
<li>SCP the file to my web directory.</li>
<li>Open the web directory in a browser to make sure the upload worked and so I can copy the URL.</li>
<li>Paste the URL to whoever I want to share it with.</li>
</ol>
<p>This is slow and boring. The other day my fellow intern <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5saW5rZWRpbi5jb20vaW4vbGFycnloYW4=">Larry</a> showed me his way of auto-uploading these screenshots, so I shamelessly stole it, modified it a little and am now claiming it as my own:</p>
<p>First, I made an Automator application that runs the following shell script:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">USER</span>=<span style="color: #ff0000;">&quot;user&quot;</span>
<span style="color: #007800;">HOST</span>=<span style="color: #ff0000;">&quot;host.com&quot;</span>
<span style="color: #007800;">UPLOAD_DIR</span>=<span style="color: #ff0000;">&quot;/var/www/screenshots&quot;</span>
<span style="color: #007800;">WEB_DIR</span>=<span style="color: #ff0000;">&quot;screenshots&quot;</span>
<span style="color: #007800;">LOCAL_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/Desktop&quot;</span>
&nbsp;
<span style="color: #007800;">FILE</span>=<span style="color: #ff0000;">&quot;Screenshot.<span style="color: #780078;">`date +%m%d%H%M%S`</span>.png&quot;</span>
<span style="color: #007800;">URL</span>=<span style="color: #ff0000;">&quot;http://<span style="color: #007800;">$HOST</span>/<span style="color: #007800;">$WEB_DIR</span>/<span style="color: #007800;">$FILE</span>&quot;</span>
&nbsp;
screencapture <span style="color: #660033;">-xi</span> <span style="color: #007800;">$LOCAL_DIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$FILE</span>
<span style="color: #c20cb9; font-weight: bold;">ping</span> <span style="color: #660033;">-t</span> <span style="color: #000000;">1</span> <span style="color: #660033;">-c</span> <span style="color: #000000;">1</span> <span style="color: #007800;">$HOST</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #c20cb9; font-weight: bold;">scp</span> <span style="color: #007800;">$LOCAL_DIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$FILE</span> <span style="color: #007800;">$USER</span><span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$HOST</span>:<span style="color: #007800;">$UPLOAD_DIR</span><span style="color: #000000; font-weight: bold;">/</span>
        <span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #007800;">$LOCAL_DIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$FILE</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$URL</span> <span style="color: #000000; font-weight: bold;">|</span> pbcopy
        growlnotify <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;Screenshot uploaded to <span style="color: #007800;">$URL</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$LOCAL_DIR</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$FILE</span> <span style="color: #000000; font-weight: bold;">|</span> pbcopy
        growlnotify <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;Screenshot copied to Desktop&quot;</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></td></tr></table></div>

<p>Then, I used Quicksilver to bind Cmd+Shift+4 to call this Application. I have an SSH key set up so the SCP works without any interaction from me. The script takes the screenshot, checks to see if the server is up, uploads the image, and copies the URL to my clipboard. If the server is down, it reverts to the default functionality of leaving the image on the Desktop.</p>
<p>The workflow is now:</p>
<ol>
<li>Take a screenshot of a selected area with Cmd+Shift+4.</li>
<li>Magic!</li>
<li>Paste the URL to whoever I want to share it with.</li>
</ol>
<p>Larry just has Quicksilver run the code as a shell script but I like the automator application since it adds a little busy spinner in the taskbar while the script runs since uploading can be a bit slow if the connection sucks.</p>
<p>Dependencies: Quicksilver, Automator, growlnotify, I suppose. Automator, growlnotify, and possibly Quicksilver are all optional.</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=138" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2010/08/08/auto-uploading-screenshots-in-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fibonacci functions and Dynamic Programming</title>
		<link>http://blog.marquiswang.com/2010/02/20/fibonacci-functions-and-dynamic-programming/</link>
		<comments>http://blog.marquiswang.com/2010/02/20/fibonacci-functions-and-dynamic-programming/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 00:54:13 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.marquiswang.com/?p=126</guid>
		<description><![CDATA[Bhargav and I had a short discussion regarding Fibonacci number generating functions over winter break and I recently answered an interview question along the same vein, so I guess its a question worth looking at: The recursive formula for the generation of the nth Fibonacci number Fn is Fn = Fn-1 + Fn-2, where F1 [...]]]></description>
			<content:encoded><![CDATA[<p>Bhargav and I had a short discussion regarding Fibonacci number generating functions over winter break and I recently answered an interview question along the same vein, so I guess its a question worth looking at:</p>
<p>The recursive formula for the generation of the nth Fibonacci number F<sub>n</sub> is F<sub>n</sub> =  F<sub>n-1</sub> +  F<sub>n-2</sub>, where F<sub>1</sub> = F<sub>2</sub> = 1. How then, do we write a function that generates the nth Fibonacci number? The simplest approach is to convert this formula directly into code (all sample code given in python):</p>
<pre>def F(n):
    if n == 1 or n == 2:
         return 1
    else:
         return F(n-1) + F(n-2)</pre>
<p>This works, but there&#8217;s a minor problem. When we run it for small numbers, it seems fine, but it slows down rapidly for large values of n. On my computer (which, admittedly, isn&#8217;t very fast, but it&#8217;s still a reasonably nice computer),  F<sub>30</sub> takes about half a second to run, F<sub>35</sub> takes about 6 seconds, and I don&#8217;t even want to know when F<sub>50</sub> will finish (according to my rough calculations, in about 6 days). This is clearly unacceptable. I could calculate F<sub>50</sub> by hand in less than 6 days (or 20 minutes). So what&#8217;s wrong?</p>
<p>If we look at the function, we&#8217;ll see that when you call F(n), it makes two recursive calls to F(n-1) and F(n-2), each of those makes two more recursive calls, which each make two more, and so on. Furthermore, each additional call only reduces the problem size by a constant factor, one or two. This leads to exponential growth, where a call to F(n) takes almost twice as long as a call to F(n-1). This is bad! The culprit here is we&#8217;re doing extra work. Here is the tree of recursive calls for F(6):<br />
<a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cubWFycXVpc3dhbmcuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDEwLzAyL1VudGl0bGVkLnBuZw=="><img class="aligncenter size-medium wp-image-129" title="Fib_6_calls" src="http://blog.marquiswang.com/wp-content/uploads/2010/02/Untitled-300x227.png" alt="Recursive tree of function calls for F(6)" width="300" height="227" /></a></p>
<p>As you can see, F(4) is being calculated in both subtrees of F(6), and F(3) is calculated in three different subtrees. As n gets larger, more and more work is being redone in multiple subtrees.</p>
<p>Bhargav&#8217;s solution was to use a hash table to save a solution once it&#8217;s been calculated, so that future calls can check if the solution has already been found for some n before calculating it again:</p>
<pre>fib_results = {1:1, 2:1}
def F(n):
    if n in fib_results:
         return fib_results[n]
    else:
         fib_results[n] = F(n-1) + F(n-2)
         return fib_results[n]</pre>
<p>This is in fact much faster and runs in linear time instead of exponential time. Unfortunately, it takes linear space in the form of the hash table, and it is unclear how or whether we can avoid using that space, though it seems like it might be possible since we didn&#8217;t use linear space in the naive solution. This approach is called memoization. Memoization is an example of a top-down alternative to <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EeW5hbWljX3Byb2dyYW1taW5n">dynamic programming</a>. It&#8217;s advantage over the bottom-up approach, called dynamic programming, is that it is much easier to convert a naive recursive algorithm to a memoized algorithm. The disadvantage is that dynamic programming is generally somewhat faster in implementation and more powerful, making it clearer how to make optimizations such as getting rid of that linear space hash table.</p>
<p>The idea behind dynamic programming is, once we&#8217;ve defined a problem in terms of its subproblems, to solve it by starting from the base cases and solving subsequently larger problems, usually in tabular form. To find F(n), we create an array of n cells, filling cells 1 and 2 with the value 1 (those are the base cases). To fill each cell, we look at the two previous cells and fill it with their sum. Conveniently, this means that the ith cell contains the value of F(i). Hence, by the time we fill the nth cell we will have found the value of F(n).</p>
<p><a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cubWFycXVpc3dhbmcuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDEwLzAyL0RQLWZpYi5wbmc="><img class="aligncenter size-medium wp-image-133" title="DP-fib" src="http://blog.marquiswang.com/wp-content/uploads/2010/02/DP-fib-300x217.png" alt="Sequence for filling DP table to solve F(n)." width="300" height="217" /></a></p>
<p>This algorithm would look like this:</p>
<pre>def F(n):
    # Create an array of n cells
    fib_table = [None]*n

    # Initialize base cases
    fib_table[0] = 1
    fib_table[1] = 1

    # Fill table
    for i in range(2, n):
        fib_table[i] = fib_table[i-1] + fib_table[i-2]
    return fib_table[n-1]</pre>
<p>Unfortunately, this still takes linear space! It will probably be a little faster than the memoized algorithm, since arrays are a little faster than dictionaries, but we still haven&#8217;t got rid of the need for the lookup table. However, if we look at this algorithm, it becomes clear that to fill each cell, we only need to look at the two cells before it. In fact, we can forget the values in every cell before those two, since we&#8217;ll never need them again. To save using that space, we can just reuse the same three cells over and over again. In fact, since we only have three cells, we can just use variables instead of creating a table:</p>
<pre>def F(n):
    a = 1
    b = 1
    c = 1
    for i in range(2, n):
        c = a + b
        a = b
        b = c
    return c</pre>
<p>Mission accomplished. We have a Fibonacci number function that runs in linear time and constant space. Dynamic programming is clearly awesome. A Fibonacci number function is one of the simplest applications of dynamic programming. One could easily imagine coming up with this solution without going through this thought process. However, there are many more complex problems that dynamic programming can solve, without which the best solutions are incredibly difficult to find. Some applications of dynamic programming include <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC85OTI1Nzg0">RNA folding</a> and <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TZWFtX2NhcnZpbmc=">seam carving</a> (crazy content aware image resizing)</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=126" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2010/02/20/fibonacci-functions-and-dynamic-programming/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Poetry Spam?*</title>
		<link>http://blog.marquiswang.com/2009/07/09/poetry-spam/</link>
		<comments>http://blog.marquiswang.com/2009/07/09/poetry-spam/#comments</comments>
		<pubDate>Thu, 09 Jul 2009 07:39:32 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Computers]]></category>

		<guid isPermaLink="false">http://blog.marquiswang.com/?p=122</guid>
		<description><![CDATA[Some time in mid-February, I got tired of my spam filter&#8217;s many false positives and decided to turn it off. I preferred having to sift through 10-20 spam emails by hand than risk missing an important email falsely flagged and blocked. An additional bonus was the entertainment value of new and novel spam. Over the [...]]]></description>
			<content:encoded><![CDATA[<p>Some time in mid-February, I got tired of my spam filter&#8217;s many false positives and decided to turn it off. I preferred having to sift through 10-20 spam emails by hand than risk missing an important email falsely flagged and blocked. An additional bonus was the entertainment value of new and novel spam. Over the last month or two, I noticed a large amount of weird spam (as in not like your average spam, since all spam is pretty weird). This phenomenon peaked around two weeks ago, when I was receiving upwards of 5-10 of them a day.</p>
<p>Each email consisted of a subject, and when appeared to be a couplet of 19th-century-poetry sounding text. Some examples included:</p>
<blockquote><p>Subject: and said, as her tear drops back she forced,<br />
and, though i should say it never,<br />
the trees bring forth sweet ecstasy only for the sake of present ease or gratification?</p></blockquote>
<blockquote><p>Subject: launched on yon shining bay,&#8211;<br />
the latest spawn the press hath cast,&#8211;<br />
father, father, where are you going look on the rising sun: there god does live</p></blockquote>
<blockquote><p>Subject: thy summer&#8217;s play younger and younger every day;<br />
darkness passes away then cherish pity; lest you drive an angel from<br />
answer&#8217;d the lovely maid and said; i am a watry weed, this time last evening. right there! all aboard!&#8221;</p></blockquote>
<p>And that was it! No link to porn, no methods to please my man in bed, no pills to grow myself a 4 foot penis.</p>
<p>I think Scott put it best.</p>
<blockquote><p>Subject: Re: the sky-lark and thrush,<br />
From: Scott Smith<br />
&#8230;the fuck?</p>
<p>On Sat, Jun 27, 2009 at 1:15 AM, Nathan Harrison<br />
wrote:</p>
<p>&gt; he doth give his joy to all. sits and smiles on the night.<br />
&gt; become a garden mild. the miner pauses in his rugged labor,</p></blockquote>
<p>Incidentally, that one is my favorite, for some reason. It almost makes sense.</p>
<p>In the name of science, I did a little snooping regarding the emails. First, I checked the originating IP addresses from the email headers. I looked at maybe a dozen emails and traced the originating countries to see if they came from any one place. They came from a variety of countries, including Uruguay, Kuwait, Germany, Italy, and even Urbana, Ohio. Was this a semi-sentient global botnet determined to demonstrate its Vogon-esque poetry skills to the world?</p>
<p>The next question then is, were these couplets originally composed or plagarized from some famous poems? I pulled up Google and searched for some of the more coherent sounding phrases, and indeed several of them were hits. It appeared that this botnet was channeling the works of William Blake and Bret Harte to create its poetic genius.</p>
<p>So what&#8217;s going on? My guess is probably some variant on standard <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9CYXllc2lhbl9wb2lzb25pbmc=">Bayesian poisoning</a>, to try to confuse spam checkers.  According to the wikipedia article on <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FLW1haWxfc3BhbQ==">email spam</a>, a common technique for Bayesian poisoning involves taking text from Project Gutenberg, and suspiciously, both Blake and Harte are in there.</p>
<p>However, Bayesian poisoning is used for text that goes along with spam trying to sell things, not random text by itself. Meh, whatever. Over the course of the last week, these emails have slowed, and I haven&#8217;t seen one in a couple days.  All I get now are my normal &#8220;How to Have rGeat sex &#8211; Smash alll Records www. bu15. net. Bewitcheed, Bedazzled, uBsted&#8221; emails.  Perhaps this will forever become a mystery.</p>
<p>Hey, maybe this is Conficker finally doing something interesting</p>
<p>* Note: Not to be confused with <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TcG9ldHJ5">spam poetry</a> or &#8220;spoetry&#8221;, another interesting phenomenon where people make poems out of spam subject lines. <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL0FOVEhPTE9HWS1TUEFNLVBPRVRSWS1NT1JUT04tSFVSTEVZL2RwL0IwMDE2RjdMSEkvcmVmPXNyXzFfMT9pZT1VVEY4JmFtcDtzPWJvb2tzJmFtcDtxaWQ9MTI0NzEyNTQwMyZhbXA7c3I9OC0x">Seriously</a>.</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=122" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2009/07/09/poetry-spam/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing Google’s PHP optimization tips</title>
		<link>http://blog.marquiswang.com/2009/06/27/testing-googles-php-optimization-tips/</link>
		<comments>http://blog.marquiswang.com/2009/06/27/testing-googles-php-optimization-tips/#comments</comments>
		<pubDate>Sun, 28 Jun 2009 06:13:19 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.marquisw.com/2009/06/27/testing-googles-php-optimization-tips/</guid>
		<description><![CDATA[Recently, Google posted a series of articles titled &#8220;Let&#8217;s make the web faster&#8220;, including one by Google webmaster Eric Higgins about optimizing PHP. Some of Google&#8217;s tips are obvious, like using caching or avoiding unnecessary SQL queries. A couple, however, seemed pretty weird to me, so I ran some benchmarks to check them out for [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, Google posted a series of articles titled &#8220;<a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9zcGVlZC9hcnRpY2xlcy8=">Let&#8217;s make the web faster</a>&#8220;, including one by Google webmaster Eric Higgins about <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9zcGVlZC9hcnRpY2xlcy9vcHRpbWl6aW5nLXBocC5odG1s">optimizing PHP</a>.</p>
<p>Some of Google&#8217;s tips are obvious, like using caching or avoiding unnecessary SQL queries. A couple, however, seemed pretty weird to me, so I ran some benchmarks to check them out for myself. (See bottom of post for specs, and other info on how I ran the benchmarks)</p>
<ul>
<li><strong>Use echo instead of print</strong>: Higgins doesn&#8217;t explain why he thinks echo is faster than print. The PHP documentation links to <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5mYXF0cy5jb20va25vd2xlZGdlX2Jhc2Uvdmlldy5waHRtbC9haWQvMS9maWQvNDA=">an faq</a> that explains the difference, and mentions that echo is marginally faster because it doesn&#8217;t set a return value, but there is no real difference in speed between the two.
<p>To test this, I ran two tests, using <code>echo</code> and then <code>print</code> to print a short string (5 characters) and then a long string (5000 characters) 1,000 times each.</p>
<h4>The Benchmark</h4>
<p>Using <code>echo</code> to print a short string 1,000 times: 1170 microseconds<br />
Using <code>print</code> to print a short string 1,000 times: 1180 microseconds</p>
<p>Using <code>echo</code> to print a long string 1,000 times: 1163 microseconds<br />
Using <code>print</code> to print a long string 1,000 times: 1182 microseconds</p>
<p><strong>Verdict:</strong> For short strings, <code>echo</code> was slightly faster, and for long strings, it looks like <code>print</code> was slightly faster. For both cases, this was a difference of only about a couple hundred-millionths of a second per call, and likely well within normal variation between calls. I&#8217;d say use whichever one you feel like using, personally.</li>
<li><strong>Use <code>switch/case</code> instead of <code>if/else</code> for loosely-typed comparisons</strong>:Apparently this has better performance, readability, and maintainability. I&#8217;ll bit on the readability and maintainability, but this article is about performance.
<p>I&#8217;m testing with code very similar to the example that Higgins provided for this one. There are four branches, each of which calls a function that does nothing but return, and each branch is equally likely.</p>
<h4>The Benchmark</h4>
<p>Using <code>if/else</code>, repeated 1,000 times: 422 microseconds<br />
Using <code>switch/case</code>, repeated 1,000 times: 425 microseconds</p>
<p><strong>Verdict</strong>: Once again, the difference is barely noticeable, and it looks like <code>if/else</code> was actually slightly faster on this test. I would say not to worry too much about it, though the <code>switch/case</code> definitely looks better from a code readability point of view.</li>
<li><strong>Provide echo with many strings as arguments instead of using concatenation</strong>: In the video, Eric replaced each of the periods in an echo call with commas, so that the strings were passed as many arguments to echo instead of concatenating them before passing them in. This seems definitely weird to me, but it might work.
<p>For this one, I&#8217;m testing <code>echo "Hello "."World!"."\n";</code> vs. <code>echo "Hello ","World!","\n";</code></p>
<h4>The Benchmark</h4>
<p>Using concatenation, repeated 1,000 times: 1225 microseconds<br />
Using arguments, repeated 1,000 times: 3255 microseconds</p>
<p>Ouch! No way is it faster to pass in multiple arguments to echo than concatenation them first! I notice that I have three arguments to echo and that took almost 3 times as long to run&#8230; let&#8217;s try it with 6 arguments. This time I&#8217;m testing <code>echo "Hello "."World!"."\n"."Hello "."World!"."\n";</code> vs. <code>echo "Hello ","World!","\n"." ","World!","\n";</code></p>
<h4>The Benchmark (2)</h4>
<p>Using concatenation, repeated 1,000 times: 1445 microseconds<br />
Using arguments, repeated 1,000 times: 5354 microseconds</p>
<p>It&#8217;s not quite linear, but it&#8217;s definitely correlated.</p>
<p><strong>Verdict</strong>: There&#8217;s no question about it. Use concatenation! It&#8217;s better! Google doesn&#8217;t know everything!</li>
</ul>
<p>The moral of this story&#8230; Google is smart, but they don&#8217;t know everything. Test things for yourself to make sure their results are the same as yours. It&#8217;s possible that Google is using a different version of PHP, running on different hardware, or something like that. Each computer is different and if these small optimizations matter to you, you have to try it for yourself to make sure.</p>
<p>Edit: The <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dyb3Vwcy5nb29nbGUuY29tL2dyb3VwL21ha2UtdGhlLXdlYi1mYXN0ZXIvYnJvd3NlX3RocmVhZC90aHJlYWQvZGRmYmU4MmRkODA0MDhjYz9wbGk9MQ==">PHP devs</a> and at least one <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jb2RleG9uLmNvbS9wb3N0cy9kZWJ1bmtpbmctZ29vZ2xlcy1pbnRlcm5ldC1vcHRpbWl6YXRpb24tdGlwcw==">other blogger</a> have reached about the same conclusions.</p>
<p>Note: I ran these benchmarks on my Linode VPS, with 360MB RAM and 4&#215;2.50GHz processors. I was using PHP 5.2.6-3ubuntu4.1 with Suhosin-Patch 0.9.6.2 from the command line, and the PHP Benchmark library. Each reported time was an average over 100 trials. Source code for my benchmarks is available <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3NhbmRib3gubWFycXVpc3cuY29tL2ZpbGVzL2JlbmNobWFya3MudHh0">here</a>. You have to pipe stdout to /dev/null, since I&#8217;m using print and echo. Results are in stderr.</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=112" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2009/06/27/testing-googles-php-optimization-tips/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Writing a keygen: Hacker challenge</title>
		<link>http://blog.marquiswang.com/2009/04/01/writing-a-keygen-hacker-challenge/</link>
		<comments>http://blog.marquiswang.com/2009/04/01/writing-a-keygen-hacker-challenge/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 23:51:06 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.marquisw.com/?p=101</guid>
		<description><![CDATA[I stumbled upon a hacker challenge posed by blogger Andy Sloane last night.  He explained how, as a hobby, likes to try to crack or create key generators for commercial programs.  Naturally, he never distributes these cracks, but is only doing it for the intellectual challenge.  Writing a key generator is usually more useful than [...]]]></description>
			<content:encoded><![CDATA[<p>I stumbled upon a <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2ExazBuLm5ldC9ibGFoL2FyY2hpdmVzLzIwMDkvMDMvMzEvaW5kZXguaHRtbA==">hacker challenge</a> posed by blogger Andy Sloane last night.  He explained how, as a hobby, likes to try to crack or create key generators for commercial programs.  Naturally, he never distributes these cracks, but is only doing it for the intellectual challenge.  Writing a key generator is usually more useful than cracking, since a good keygen typically allows you to receive future updates.  Often, it is also more interesting from an intellectual point of view, as writing a keygen usually requires some knowledge in reverse engineering and number theory.  Andy tries to demonstrate what he means by providing a simple key checker of his own for us to break.  Since I had a lighter workload last night, I figured I&#8217;d try it.</p>
<p>For his challenge to the world, he offers the source code of the key checker and three working keys.  The source is available on his blog.  (While a normal keygen writer would not have access to the source code of the key checker, it is usually simple, though tedious, to decompile and interpret the compiled binaries that would be released.)</p>
<p>After downloading and skimming the source, I spent a while trying to understand the custom written (and minimally commented) library he uses for large (125 bit, in this case) integers.  Rather than try to interpret the code itself, I used gdb to inspect the way the library worked, and had soon figured out the inner workings of the key checker:</p>
<p>Each key that it received, it would convert into an integer.  Each key had a unique integer <em>k</em> (with some exceptions: O, Q, and 0; I and 1; and Z and 2 were considered to be interchangeable to lower the change of an misread key) to which it was decoded.</p>
<p>Two magic numbers <em>n</em> = 21967608700894359473408781171922272451 and <em>d</em>=4444901153489723031681183441752517327 were hard-coded into the program.  A new number <em>m</em> ≡ <em>k<sup>d</sup></em> <em>mod</em> <em>n</em> was created.  The key was accepted if <em>m</em> ≡ 12345678 <em>mod</em> <em>c, </em>where <em>c = </em>⌊<em>n/2<sup>32</sup></em>⌋ (rounded down to the nearest integer).</p>
<p>This was clearly a problem for number theory! This algorithm looked suspiciously similar to the <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SU0E=">RSA</a> encryption algorithm, which similarly employs two large numbers with special properties.</p>
<p>A quick summary of the steps behind RSA encryption:</p>
<ol>
<li>Pick two large primes <em>p</em> and <em>q.<br />
</em></li>
<li>Compute <em>n = pq</em>.</li>
<li>Compute the totient of <em>n, φ(<em>n</em>) = (p-1)(q-1)</em>.</li>
<li>Choose an integer <em>e</em> such that <em>e </em>is relatively prime to and less than <em>φ(<em>n</em>)</em>.</li>
<li>Compute the integer <em>d</em> such that <em>ed </em>≡ 1 <em>mod </em><em>φ(<em>n</em>)</em>.</li>
<li>For your message <em>m</em>, encrypt it by generating ciphertext <em>c ≡ m<sup>e</sup> mod n</em>. <em>e </em>is known as the public key and is used to encrypt the message.</li>
<li>The person who receives the ciphertext by using <em>d</em> and applying the formula <em>m = </em><em>c<sup>d</sup> mod n</em>.</li>
</ol>
<p>This works because of Euler&#8217;s theorem, which states that <em>a<sup>φ(n) </sup></em><em>≡ a</em><em> mod n</em> for any integers <em>a </em>and <em>n. </em></p>
<p>From that, <em>c<sup>d </sup></em><em>=</em>(<em>m<sup>e</sup></em>)<sup>d</sup>=<em>m<sup>ed</sup></em>= <em>m<sup>1+kφ(n) </sup></em>≡ <em>m mod n</em>. (Check out the explanation of RSA on wikipedia for a more in depth explanation.</p>
<p>I quickly used Mathematica to factor <em>n</em> to see if it was the product of two primes. It was!  I checked that <em>d</em> was relatively prime to <em>φ(<em>n</em>) </em>to be sure.  It also was. The only part where this differed from RSA was the final step where it checked to see if <em>m</em> ≡ 12345678 <em>mod</em> <em>c </em>before accepting the key.</p>
<p>I was a little thrown off by <em>c </em>being related to <em>n</em>, but I quickly realized that it didn&#8217;t matter what <em>c</em> was.  It was just there to make sure that more than one <em>m</em> (and therefore more than one key) was accepted.  Effectively, what this key checker did was to take RSA generated ciphertext as a key and check to see if it decryped to a message that left a remainder of 12345678 when divided by <em>c</em>.</p>
<p>Therefore, to generate a key, I needed to create a correct message and encrypt it, then convert the ciphertext back to the &#8220;key&#8221; format.  Creating a message is easy. <em>m</em> is an accepted message if <em>m</em> ≡ 12345678 <em>mod</em> <em>c</em>, so <em>m = ac + </em>12345678, where <em>a </em>is any natural number.  To encrypt <em>m</em>, I need to find the private key <em>e</em>.  Since <em>n</em> is small enough to factor and <em>ed </em>≡ 1 <em>mod </em><em>φ(<em>n</em>)</em>, it is easy to find <em>e</em> through modular arithmetic.</p>
<p>Voila! Now I have everything I need to write a keygen for Andy&#8217;s example key checker. In fact, <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3NhbmRib3gubWFycXVpc3cuY29tL2ZpbGVzL2tleWdlbi50eHQ=">here</a> it is.  Now, clearly, I should go do my homework, having wasted several hours on this.</p>
<ol><em></em></ol>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=101" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2009/04/01/writing-a-keygen-hacker-challenge/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Good password habits?</title>
		<link>http://blog.marquiswang.com/2009/03/05/good-password-habits/</link>
		<comments>http://blog.marquiswang.com/2009/03/05/good-password-habits/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 08:04:29 +0000</pubDate>
		<dc:creator>Marquis Wang</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://blog.marquisw.com/?p=90</guid>
		<description><![CDATA[Cardinary Sins of Passwords Using short passwords with few numbers or special characters. Using the same password for many things (or everything). Rarely (or never) changing passwords. Using a name or common phrase in a password. If you&#8217;re guilty of one or more of these bad password habits, raise your hand! *Raises hand* Despite being [...]]]></description>
			<content:encoded><![CDATA[<h3>Cardinary Sins of Passwords</h3>
<ul>
<li> Using short passwords with few numbers or special characters.</li>
<li> Using the same password for many things (or everything).</li>
<li> Rarely (or never) changing passwords.</li>
<li> Using a name or common phrase in a password.</li>
</ul>
<p>If you&#8217;re guilty of one or more of these bad password habits, raise your hand!</p>
<p>*Raises hand*</p>
<p>Despite being (I think) very tech savvy, I have some very bad password habits, and I would not be at all surprised if many of my similarly computer-smart friends do too. Mostly, I use the same password for many things, and I rarely change my passwords.  The password I use most often, for almost all of my accounts on various websites, I first used with my <em>first</em> email account so long ago in the mid 90s.  It is a relatively short and simple password, and someone could definitely wreak some havoc if they got their hands on it, though they wouldn&#8217;t have access to anything important.  Of my other passwords, the newest one is about 3 years old and I came up with the oldest one almost 7 years ago.  That&#8217;s plenty of time for someone to get their hands on the keys to my personal information, bank accounts, etc.</p>
<p>One of my new years resolutions this year was to improve on my password habits, and I definitely haven&#8217;t gotten anywhere with that.  (Another one was to blog more, heh, fail there too.)  So I guess the question is, why <em>is</em> it so hard to keep passwords up to date and secure?</p>
<p>For me, the number one barrier to changing passwords regularly is the hassle of having to memorize a new password, especially a complex one with numbers and special characters. Similarly, I reuse the 3 or 4 passwords I use most often to minimize the risk of forgetting a password.  With so many different services which require passwords, and more every week as I sign up for a new web site, it is sometimes difficult to remember whether I <em>have</em> an account to a certain site, much less remember a unique password for each one. Furthermore, I&#8217;ve never had any problems with security, so I don&#8217;t have any real motivation to change them.</p>
<h3>Possible solutions</h3>
<p><strong>Using a password manager:</strong> I got a free license for <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FnaWxld2Vic29sdXRpb25zLmNvbS9wcm9kdWN0cy8xUGFzc3dvcmQ=">1password</a> during MacHeist&#8217;s Giving Tree this year, which I&#8217;m going to start using. This allows me to use more passwords of greater complexity, and not have to worry about forgetting them.  Of course, this is only as secure as the master password I use for 1password, and I have to figure something out for when I am on a public computer.  If I don&#8217;t actually remember my passwords, I won&#8217;t be able to get to my accounts away from my computer.<br />
<strong>Using phrase passwords:</strong> Instead of the traditional 8-12 character random passwords, use a 20-30 character phrase that is easy to memorize but difficult to guess.  To help mitigate the risk of getting locked out of my accounts if I lose access to my password manager somehow, I think I will start using phrases from songs or quotes or something as passwords, instead.  Unfortunately, the longer a phrase is, the greater a chance for a typo while typing it in.<br />
<strong>Using a password generation system:</strong> Another option which might be safer than phrase passwords is using a system to generate secure passwords that are unique for every site.  One such system is <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xpZmVoYWNrZXIuY29tL3NvZnR3YXJlL3Bhc3N3b3Jkcy9nZWVrLXRvLWxpdmUtLWNob29zZS1hbmQtcmVtZW1iZXItZ3JlYXQtcGFzc3dvcmRzLTE4NDc3My5waHA=">this one</a> suggested by <a href="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xpZmVoYWNrZXIuY29t">Lifehacker</a>.</p>
<p>I&#8217;m starting to migrate towards these practices right now. Hopefully, I&#8217;ll be able to keep it up and maintain my good luck with regard to password security for a while longer.</p>
 <img src="http://blog.marquiswang.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=90" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.marquiswang.com/2009/03/05/good-password-habits/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

