<?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>The Quixotic Engineer &#187; Programming</title>
	<atom:link href="http://gangles.ca/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://gangles.ca</link>
	<description>A game design blog by Matthew Gallant</description>
	<lastBuildDate>Sat, 06 Aug 2011 17:14:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>The Principles of Programming in SpaceChem</title>
		<link>http://gangles.ca/2011/06/19/programming-in-spacechem/</link>
		<comments>http://gangles.ca/2011/06/19/programming-in-spacechem/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 03:15:43 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Video Games]]></category>
		<category><![CDATA[SpaceChem]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=251</guid>
		<description><![CDATA[SpaceChem is a remarkable puzzle game about fake chemistry. The game challenges you to build a factory in order to transmute the given input molecules into the given output molecules. While chemistry is the theme, on a mechanical level it has more in common with programming. The methods used to tackle challenges in SpaceChem are [...]]]></description>
			<content:encoded><![CDATA[<p align="center" ><img src="http://gangles.ca/images/SpaceChem.png" alt="SpaceChem screenshot" title="SpaceChem" class="blogimage" /></p>
<p><a href="http://www.spacechemthegame.com/"><cite>SpaceChem</cite></a> is a remarkable puzzle game about fake chemistry. The game challenges you to build a factory in order to transmute the given input molecules into the given output molecules. While chemistry is the theme, on a mechanical level it has more in common with programming. The methods used to tackle challenges in <cite>SpaceChem</cite> are akin to real techniques used by computer programmers. I’d like to elaborate on these manifold similarities, as well as explore how games like <cite>SpaceChem</cite> could be used to promote procedural literacy.</p>
<p>The player commands two circular “waldoes” by laying out paths and instructions for them. The waldoes follow the path and sequentially execute any instruction they come across. They can grab, drop, rotate, sync, bond, fuse, request input or dispatch output. The waldo’s analogue in computing is the processor, a hardware component that sequentially executes basic operations defined by machine code. Like processors, waldoes are the engines that drive the control flow of a <cite>SpaceChem</cite> factory.</p>
<p>When a waldo grabs a molecule, it gains the ability to perform instructions directly on it. In other words, a grabbed element is more readily and rapidly available than one lying elsewhere on the grid. Conceptually this is analogous to storing data in registers, a form of computer memory that is accessed very quickly and that the CPU manipulates directly. Just as a waldo can only grab one molecule at a time, computers have very few registers and must therefore rely on caching.</p>
<p>If grabbed molecules are like data in registers, then molecules left on the grid are cached. The cache is a larger, cheaper form of memory, but it is slower to read and write. Data must be written from the cache to a register in order to be manipulated directly by the CPU. The amount of memory in <cite>SpaceChem</cite>’s “cache” is governed by the area of the grid (8 x 10). Each coordinate on the grid can therefore be considered a unique memory address. This analogy is enforced mechanically: a factory “crashes” if two atoms collide on the grid, since you can’t store two values in the same memory address.</p>
<p align="center" ><img src="http://gangles.ca/images/SpaceChem2.png" alt="SpaceChem screenshot" title="SpaceChem - Nuking the Squid" class="blogimage" /></p>
<p>Each factory has two waldoes, and they must be properly coordinated as they move through time and space. This coordination is facilitated by the sync node, which tells a waldo to wait until its twin has also hit a sync node. Parallel waldo management is akin to parallel programming, and they share the same perils: deadlock, starvation, race conditions, etc. The waldoes are like threads operating on shared memory space, and sync nodes are functionally similar to semaphores (operations that tell threads to <em>signal</em> and <em>wait</em>.) Operating two waldoes simultaneously in <cite>SpaceChem</cite> forces the player to confront the same shared resource problems as parallel computing.</p>
<p><cite>SpaceChem</cite> and programming involve similar challenges: laying out simple instructions to achieve a complex result while managing limited time and resources. Like a good software specification, each puzzle is clearly presented as a black box defined only by its inputs and outputs. The player lays out instructions, starts up the factory, observes errors and corrects them, iterating until the puzzle is solved. Solutions can then be further optimized to take less time and use fewer instructions. <cite>SpaceChem</cite> and programming are engaging, flow-inducing activities because they have an identical inner loop: implementing, debugging and optimizing.</p>
<p>At this year’s GDC, Michael John asserted that programming is 21<sup>st</sup> century literacy. If computer programming is currently considered esoteric knowledge, it’s because our general education is not preparing students to think about problems in an algorithmic or systematic manner. Ian Bogost calls this <a href="http://www.bogost.com/writing/procedural_literacy.shtml">procedural literacy</a>: “the ability to reconfigure basic concepts and rules to understand and solve problems.” <cite>SpaceChem</cite> may not be an ideal game for the classroom (it’s far too difficult, for one), but it strongly suggests that the best way to learn about and engage with complex systems it to play with them.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2011/06/19/programming-in-spacechem/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>No Fun Games &#8211; CUSEC DemoCamp</title>
		<link>http://gangles.ca/2010/04/02/cusec-democamp/</link>
		<comments>http://gangles.ca/2010/04/02/cusec-democamp/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 22:50:15 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Video Games]]></category>
		<category><![CDATA[CUSEC]]></category>
		<category><![CDATA[No Fun Games]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=232</guid>
		<description><![CDATA[Back in January, Henk, Thomas and I presented two games we were working on (Norwegian Wood and an alpha build of Pax Britannica) to the DemoCamp at CUSEC 2010. DemoCamp is a really cool informal event where programmers can show off what they&#8217;ve been hacking on. The rules are simple: 15 minutes maximum, no powerpoint, [...]]]></description>
			<content:encoded><![CDATA[<p align="center"><object width="500" height="281"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=10636247&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=10636247&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="500" height="281"></embed></object></p>
<p>Back in January, <a href="http://henk.ca/">Henk</a>, <a href="http://www.t-hibbs.ca/">Thomas</a> and I presented two games we were working on (<a href="http://norwegianwood.gangles.ca/"><cite>Norwegian Wood</cite></a> and an alpha build of <a href="http://gangles.ca/2010/02/27/pax-britannica/"><cite>Pax Britannica</cite></a>) to the <a href="http://2010.cusec.net/01-07/cusec-wants-you-to-show-off-your-stuff/">DemoCamp at CUSEC 2010</a>. DemoCamp is a really cool informal event where programmers can show off what they&#8217;ve been hacking on. The rules are simple: 15 minutes maximum, no powerpoint, show working code!</p>
<p>I think the talk went really well, we got by with some laughs and a little bit of casual swearing. Big thanks to the CUSEC organizers, host <a href="http://www.joeydevilla.com/">Joey DeVilla</a> and A/V tech <a href="http://smokinn.com/blog/">Guillaume Theoret</a> for giving us a chance to show off our games!</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2010/04/02/cusec-democamp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Postmortem: Norwegian Wood</title>
		<link>http://gangles.ca/2009/10/11/postmortem-norwegian-wood/</link>
		<comments>http://gangles.ca/2009/10/11/postmortem-norwegian-wood/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 05:53:04 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Video Games]]></category>
		<category><![CDATA[Independent Games]]></category>
		<category><![CDATA[No Fun Games]]></category>
		<category><![CDATA[Postmortem]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=217</guid>
		<description><![CDATA[The project that became Norwegian Wood began in late April of this year. With school winding down and the weather heating up, I felt the itch to tackle something new. By chance I had met a number of like-minded people over the winter; students with big ideas and aspirations of working in the game industry. [...]]]></description>
			<content:encoded><![CDATA[<p>The project that became <a href="http://norwegianwood.gangles.ca/"><em>Norwegian Wood</em></a> began in late April of this year. With school winding down and the weather heating up, I felt the itch to tackle something new. By chance I had met a number of like-minded people over the winter; students with big ideas and aspirations of working in the game industry. Inspired by this collective potential, I decided to reach out to my local friends and colleagues about coming together to make a game over the summer.</p>
<p>The response was overwhelming; of the nine people I had e-mailed, seven of them were interested in participating. The project was suddenly much larger than I had anticipated, but I didn&#8217;t have the heart to turn anyone away. The eight of us (<a href="http://henk.ca/">Henk Boom</a>, Thomas Hibbert, <a href="http://philippejones.com/">Phil Jones</a>, <a href="http://theinstructionlimit.com/">Renaud Bédard</a>, <a href="http://alex-charlton.com/">Alex Charlton</a>, <a href="http://brilliam.cikro.com/writes/">William Mitchell</a>, Kyle Sama and I<sup>1</sup>) formed the facetiously titled collective No Fun Games.</p>
<p align="center" class="center"><img src="http://gangles.ca/images/pulpcharacters.jpg" alt="Pulp Characters by Phil Jones" title="Pulp Characters by Phil Jones" width="500" /></p>
<p>You might be surprised to learn that our original game idea had nothing to do with music, shoot &#8216;em ups or The Beatles. While we explored a number of different game ideas, we settled on creating a murder mystery game set in an JRPG-style lumber town. We gave the development version the nickname <em>Pulp</em><sup>2</sup>.</p>
<p><em>Pulp</em>&#8216;s main character was &#8220;Penny&#8221;, a local girl with a knack for mysteries. She teamed up with retired Sherlock Holmes analogue &#8220;Detective Powell&#8221; to solve the murder of his former partner &#8220;Dr. Watson&#8221; (we never really settled on official names). You can see Phil&#8217;s concept art for some of the characters above.</p>
<p>We developed an elaborate back story which outlined the motivation behind the murder and its connection to the protagonists. However, our ideas for the game&#8217;s actual plot and structure were little more than a skeleton. Truthfully, we possessed neither the inclination nor the talent to write good fiction and this was ultimately the game&#8217;s downfall.</p>
<p align="center" class="center"><img src="http://gangles.ca/images/pulp.png" alt="No Fun Games - Pulp" title="No Fun Games - Pulp" /></p>
<p>On the programming side, we put together a basic game engine in Python with the help of the Pygame and PyOpenGL libraries. It gave us the bare essentials, allowing us to add actors to the screen and assign them behaviours. As seen above, we created a simple world for Penny to run around and interact with (the Fez spritesheet was placeholder art lent to us by Renaud).</p>
<p>Sadly, this is as far as the <em>Pulp</em> project ever got. Despite our best intentions, we drifted apart over the summer. Everyone had personal commitments, internships, and travel plans. We simply didn&#8217;t have the time or motivation for leisure coding. By July, <em>Pulp</em> had reluctantly become vapourware. Fortunately, this wasn&#8217;t the end of No Fun Games.</p>
<p>By late August, things in my life were starting to slow down. I was back living in Montreal (after spending the summer at IBM in Ottawa), and had a couple of weeks off before the fall semester. Blessed with free time, I decided to reconnect with my teammates for a final sprint. Naturally, we wanted to release something after all our hard work.</p>
<p>Of course, not everyone had the luxury of time off. While we all wanted to participate, only Henk, Thomas and I had the hours to spare. Our artist Phil was also interested, but couldn&#8217;t commit to the heavy art demands of the murder mystery concept. With this in mind, we decided to drop that idea and reuse the engine we had created to pursue an entirely different genre.</p>
<p align="center" class="center"><img src="http://gangles.ca/images/pulpbranch.png" alt="Branching Pulp into Norwegian Wood" title="Branching Pulp into Norwegian Wood" /></p>
<p>The concept for <em>Norwegian Wood</em> came from our desire to explore the burgeoning intersection of music and gameplay. We wanted to create a game where listening and following the rhythm played a strong role in the player&#8217;s experience, but less directly than a game like <em>Rock Band</em>.</p>
<p>This idea manifested as a shoot &#8216;em up game where the bullet patterns are timed to the individual instruments. The decision to use The Beatles&#8217; music was somewhat incidental; I happened to be listening to <em>Rubber Soul</em> when the game concept occurred to me. However, the song has certain qualities that make it rather ideal. For instance, the notes are quite discrete, making it easy to divide the instruments and record timestamps. More importantly, using a calm lilting ballad with subtle dark undertones contrasted nicely with the upbeat synth-metal used in most shoot &#8216;em up games.</p>
<p align="center" class="center"><img src="http://gangles.ca/images/pulpprototype.png" alt="Norwegian Wood Prototype" title="Norwegian Wood Prototype" /></p>
<p>Henk, Thomas and I got together at school to work on the game, working nearly full time for two weeks. We managed to create a playable prototype within a few days, then put the majority of our work into refining and iterating on the core gameplay. We also placed a strong emphasis on player feedback, bugging everyone around us to playtest it.</p>
<p>After chasing down the cross-platform bugs and ironing out the details of deployment, we finally released <em>Norwegian Wood</em> in late September. Thanks in large part to <a href="http://gangles.ca/images/nw_twitterfriends.png">friends on Twitter</a> spreading the word, we&#8217;ve had thousands of hits, hundreds of <a href="http://norwegianwood.gangles.ca/highscores/">high scores</a> and some <a href="http://www.offworld.com/2009/09/beatles-hell-no-funs-quarter-n.html">very positive feedback</a>. We&#8217;re thrilled that so many people have enjoyed our game, and promise to put all that excitement right back into making more of them.</p>
<p>To summarize <a href="http://www.gamasutra.com/features/postmortem/">Gamasutra-style</a>, here are some lessons we learned during development:</p>
<h4>What Went Right</h4>
<p><strong>1. Working Together Locally</strong><br/>While most of the work on <em>Pulp</em> had been completed remotely, it came at a cost to communication and motivation. For <em>Norwegian Wood</em> we decided that there is really <a href="http://www.geekflex.com/2009/05/10/no-substitute-for-face-to-face/">no substitute for face-to-face time</a> and met up in person every day. This was extremely effective, both for making consistent measurable progress and sharing a common creative vision.</p>
<p><strong>2. Recording Global High Scores</strong><br/>The online high score table was a minor last-minute addition to the game. However, as Eric Swain pointed out in his insightful <a href="http://www.thegamecritique.com/recent-posts/indie-game-spotlight-norwegian-wood/440/">Indie Spotlight</a>, it added a ton of value in terms of competition and replayability. &#8220;Even after all these years and innovations it is still a huge motivation to play. [...] It isn’t all about competition, but the close knit community that get formed in that competition.&#8221;</p>
<p><strong>3. Sidestepping Copyright</strong><br/>It took a lot of thinking to come up with a way to release a music game without infringing on The Beatles&#8217; copyright<sup>3</sup>. Despite our doubts, having the user provide their own mp3 turned out to be a very successful strategy. Of course, it&#8217;s a shame that we picked the one band whose music can&#8217;t be downloaded legally. In the future, we&#8217;d very much like to reexplore this concept with <a href="http://creativecommons.ca/">Creative Commons</a> licensed music.</p>
<h4>What Went Wrong</h4>
<p><strong>1. Big Team Woes</strong><br/>Starting out with such a large development team on <em>Pulp</em> was a major challenge. Responsibility was spread too thin, and no one felt like they had creative control of the game on an individual level. In retrospect, I would recommend a team of no more than 4 for your first indie collaboration. Furthermore, it helps to have a fairly autocratic team leader.</p>
<p><strong>2. Summertime Blues</strong><br/>I had assumed that summer would be the perfect time for students to pursue a side project. Working nine to five at an internship means having evenings off and lots of free time, right? Sadly, I was way off. The temperament of summer is lazy and leisurely; it&#8217;s hardly a season for picking up additional work. Furthermore, working full-time turns casual hacking into an unpleasant chore. Counter-intuitively, students would much rather attempt side projects while they&#8217;re juggling exams and assignments in the fall.</p>
<p><strong>3. Storytelling Failure</strong><br/>We were incredibly naive about the process of writing a story for <em>Pulp</em>. We had the big picture ideas and the game mechanics, and just assumed that the moment-to-moment narrative experience would flow from that. We quickly discovered that writing a good story is an extremely demanding task, one we were ill-equipped to handle. Lesson learned: if you insist on having a narrative element to your game, make sure you have a dedicated writer (or <a href="http://corvus.zakelro.com/2009/04/semionautical-adventures/">semionaut</a>) on the team.</p>
<p>Thanks again to everyone who was involved in <em>Norwegian Wood</em>, including those of you who playtested it and helped spread the word on release day. Making this game was a terrific experience, and it taught me a great deal about game design, programming and project management. I look forward to applying these lessons to my next game!</p>
<p><img src="http://gangles.ca/images/hr.gif" alt="" /></p>
<p><small><sup>1</sup> <a href="http://drgamelove.blogspot.com/">Ben Abraham</a> was also briefly involved as music director, he wrote us a <a href="http://gangles.ca/audio/benabraham-dirge.mp3">lovely dirge</a> for <em>Pulp</em>.<br/><sup>2</sup> Funny how <em>Pulp</em> turned into <em>Norwegian Wood</em>. The arboreal theme is coincidental.<br/><sup>3</sup> Actually, <a href="http://www.newton64.ca/blog/">Nick</a> suggested this approach. Thanks Nick!</small></p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2009/10/11/postmortem-norwegian-wood/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
<enclosure url="http://gangles.ca/audio/benabraham-dirge.mp3" length="2107084" type="audio/mpeg" />
		</item>
		<item>
		<title>Purple Monkey Dishwasher</title>
		<link>http://gangles.ca/2008/06/12/purple-monkey-dishwasher/</link>
		<comments>http://gangles.ca/2008/06/12/purple-monkey-dishwasher/#comments</comments>
		<pubDate>Thu, 12 Jun 2008 04:18:25 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[A.I.]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Markov Chains]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=115</guid>
		<description><![CDATA[I was originally introduced to Markov chains by Josh Millard&#8217;s Garkov, a project that applies this mathematical model to Garfield comics. I thought it was an amusingly random idea, but didn&#8217;t fully appreciate the concept until Jeff Atwood wrote a post detailing how Markov Chains work. To quickly summarize, the algorithm chooses its next word [...]]]></description>
			<content:encoded><![CDATA[<p align="center" class="center"><a href="/images/garkov.jpg" title="Click to enlarge"><img src="/images/garkov.jpg" title="Click to enlarge" alt="Garkov" width="490" /></a></p>
<p>I was originally introduced to Markov chains by Josh Millard&#8217;s <a href="http://www.joshmillard.com/garkov/" title="Garfield + Markov Chains = Garkov">Garkov</a>, a project that applies this mathematical model to Garfield comics. I thought it was an amusingly random idea, but didn&#8217;t fully appreciate the concept until <a href="http://www.codinghorror.com/blog/archives/001132.html" title="Markov and You - Coding Horror">Jeff Atwood wrote a post</a> detailing how Markov Chains work.</p>
<p>To quickly summarize, the algorithm chooses its next word using a probabilistic function based on two criteria: the current word, and a large sample of coherent text. The chance of a word being chosen is based entirely on how frequently it follows the current word in the sample text. For instance, if the sample was &#8220;To be, or not to be, that is the Question&#8221;, the word &#8220;be&#8221; would have a 50/50 chance of being followed by &#8220;or&#8221; or &#8220;that.&#8221; As the sample size increases, the text produced becomes increasingly sound. [<em>Update</em>: The size of the sample does not necessarily increase the coherency of the text, the number of words used in the seed is the biggest determining factor. Thanks for the correction, Josh.]</p>
<p>Reading about this got me very curious. What would a Markov chain generated using my own writing look like? Would it overuse &#8220;however&#8221; and frequently misapply the word &#8220;parse&#8221; like I do? I decided some experimentation using the <a href="http://www.beetleinabox.com/mkv_input.html">Markov Text Synthesizer</a> was in order.</p>
<p>The first test sample was my <a href="http://gangles.ca/tag/rockin-the-boat/">Rockin&#8217; The Boat</a> series on rock &#8216;n&#8217; roll and race relations in 1950&#8242;s America. At a scant ~4000 words it was a poor sample, which made it quite possible to recognize parts of the original sample in the text:</p>
<blockquote><p>Rock ‘n’ roll party. Freed considered completely alien. Mintz had his personal success, but rather the Speeds had been a little pressed for school facilities. They were subject to unsuccessful alternative names such as much for the trend was classified under the Brown v. Board of, in ten in, most popular opinion in the same records was no memory of the major label was a lesson. He was a token job. The major record store owner in postwar economy. During the following lyrics which were localized in America. A successful rhythm and I feel would sing to popular.</p></blockquote>
<p>For my next attempt, I used every post listed under the <a href="http://gangles.ca/category/video-games/">Video Games category</a>. This was over ten times larger than my original sample, and the text was much more randomized as a result (it even snuck in a &#8220;however&#8221;, hooray!):</p>
<blockquote><p>There are games have two things spectacularly well. One where it will work at first. They mix means of Internet hype around the U.S. Addresses Only. Heartbroken, I was, however, describe what is one of the censor, the creative Wiimote according to the end. Plot holes and Escapist feature. Embedded below is minutes of military shooters had her to convince you feel that the game will work done with blood all available up the narrative. He created the Medic class impressions. The use of his weekly feature film was already breaking my favourite newspaper articles. Read the end. The very effective ways. My favorite aspect of a short stories, particularly dystopian centuries. At first game Rock Band, but the best like a timeless void movie revolved largely passed under them all.</p></blockquote>
<p>Next, I decided to use the same sample but increase the &#8220;word grouping&#8221; to two. This means that the function will now determine how frequently a word follows the two previous words (in order.) This made the text much more coherent, but brought back the problem of being similar to the original sample:</p>
<blockquote><p>There have been used by other games in the villa’s lobby. Recharging your beam sword’s energy with a Little Sister crying for “Mr. Bubbles”, but it costs a whopping. December is a classic for years to come. Valve could have easily rested on their laurels and sold Portal on its PS release Tools of Destruction, with some great part series detailing each other, it seems that the FPS genre has been getting a lot of the murder investigation. The evidence found and is by far the best thing the Bioshock movie revolved largely around and go buckwild with ADAM. I would rescue them all. It was also annoying at times. To move Zack around you have to mimic it in real life.</p></blockquote>
<p>Finally, I decided to test the program with a very very large sample: <a href="http://craphound.com/littlebrother/download/">Cory Doctorow&#8217;s free e-book <em>Little Brother</em></a>. I don&#8217;t think this is the sort of remixing Doctorow had in mind when he released his book under Creative Commons, but here goes:</p>
<blockquote><p>I&#8217;m a stone Disney park freak see my fear. Marcus, it can fill you with our magic coffee bean supply. If you&#8217;ve got it for a lot longer than me. One only spoke Arabic he began, when one of the country, the world to know it&#8217;s there. The truck drew closer. I kept hitting it with both hands. She was dressed in a drawer with the texture of very ugly stuff on the back of a polished marble plinth. I decided I wanted to do stand down. Will you promise me that? They promised with all the walls and other little devices, my wallet intact. Forbidden Planet rarely do I go to jail, Marcus, and not that many cool puzzles that you wanted to be a part of that Hummer, my head for my book by net or phone and memory sticks are private. Thats because of cryptography message scrambling. The math behind crypto is good and solid, and you wonder, Was it always like that? I hadn&#8217;t thought about trying to intimidate me the picture she&#8217;d snapped of us, if you wanted to.</p></blockquote>
<p>I&#8217;m amazed, a very large sample with a word grouping of two or greater can produce some terrific results. It makes me wonder why spammers always end up with such nonsense titles, use a larger sample you jerks!</p>
<p>In my various attempts, I also ended up with some rather spectacular phrases. Here are some of my favourites, I swear I did not make any of these up:</p>
<blockquote><p>The whimsical charms of each of disappointed children</p></blockquote>
<blockquote><p>Holding the Wiimote in the holiday rush? Either way, you’re probably online looking for awesome news like this</p></blockquote>
<blockquote><p>Your character’s level is on a couch. They’re comfortable for both sides.</p></blockquote>
<blockquote><p>a combination of raw stem cells, dubbed thing, and the USA</p></blockquote>
<blockquote><p>I believe I was blindsided by exploiting my childhood memories</p></blockquote>
<p>&#8230;and the best one by far:</p>
<blockquote><p>This essay will be successfully ignored altogether.</p></blockquote>
<p>Check out <a href="http://drgamelove.blogspot.com/2008/06/markov-chain-madness.html">Ben Abraham&#8217;s post</a> for some more great ones (he beat me to the punch by a few hours.) Finally, I&#8217;ll leave you with a challenge. Can you guess what sample I used to produce the text below?</p>
<blockquote><p>Peyote solidities of halls, backyard green tree cemetery dawns, wine drunkenness over the rooftops, storefront boroughs of teahead joyride neon blinking traffic light, sun and moon and tree vibrations in the roaring winter dusks of Brook-lyn, ashcan rantings and kind king light of mind, who chained themselves to subways for the endless ride from Battery to holy Bronx on benzedrine until the noise of wheels and children brought them down shuddering mouth-wracked and battered bleak of brain all drained of brilliance in the drear light of Zoo,</p></blockquote>
<h5 align="center">***********ANSWER***********</h5>
<p>Trick question, it&#8217;s actually a word-for-word excerpt from <a href="http://members.tripod.com/~Sprayberry/poems/howl.txt">Allen Ginsberg&#8217;s <em>Howl</em></a>. Only the formatting has been edited. I think the beat poets would have dug Markov chains, don&#8217;t you?</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/06/12/purple-monkey-dishwasher/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Fixing Simple XHTML Errors with Python</title>
		<link>http://gangles.ca/2008/06/11/fixing-simple-xhtml-errors-with-python/</link>
		<comments>http://gangles.ca/2008/06/11/fixing-simple-xhtml-errors-with-python/#comments</comments>
		<pubDate>Wed, 11 Jun 2008 05:11:12 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=114</guid>
		<description><![CDATA[For a long time, one of my secret shames as a programmer was that there were parts of this website held together by some rather shoddy code. Writing this blog has been a great learning experience, but as a consequence I&#8217;ve often accidentally done things the &#8220;not quite right&#8221; way. Armed now with a better [...]]]></description>
			<content:encoded><![CDATA[<p>For a long time, one of my secret shames as a programmer was that there were parts of this website held together by some rather shoddy code. Writing this blog has been a great learning experience, but as a consequence I&#8217;ve often accidentally done things the &#8220;not quite right&#8221; way. Armed now with a better understanding of XHTML and CSS, I thought it might be a good idea to fix some of that spaghetti code and bring my blog up to at least <a href="http://www.w3.org/MarkUp/#flavors" title="XHTML 1.0 Transitional Documentation">XHTML 1.0 Transitional</a>.</p>
<p>As a long overdue followup to my <a href="http://gangles.ca/2008/01/08/the-case-of-the-mystery-operator/" title="The Quixotic Engineer - The Case of the Mystery Operator">previous experimentation with Python</a>, I decided to kill two birds with one stone by writing a script to clean up some common errors in my posts. Blame it on my sloppy HTML education, but I make these mistakes <em>all the time</em>. For instance:</p>
<ul>
<li>Using &lt;i&gt; instead of &lt;em&gt;</li>
<li>Using &lt;b&gt; instead of &lt;strong&gt;</li>
<li>Not closing my IMG and BR tags</li>
<li>Forgetting to give my images &#8220;alt&#8221; text</li>
</ul>
<p>Furthermore, due mostly to my <a href="http://gangles.ca/tag/the-musical-box/" title="The Quixotic Engineer - The Musical Box">Musical Box series</a>, I&#8217;ve embedded a rather large number of YouTube videos in my posts. For some crazy reason, the default code uses the deprecated &lt;embed&gt; tag and is therefore not XHTML 1.0 compliant! The mind-blowing part is that it&#8217;s relatively simple to <a href="http://www.bernzilla.com/item.php?id=681" title="Embedding YouTube Videos as Valid XHTML 1.0">embed videos in an XHTML friendly way</a>. Why isn&#8217;t this code available by default?</p>
<p>Armed with my copy of <a href="http://diveintopython.org/">Dive Into Python</a> and basic experience with regular expressions from Perl, I went about writing a script to parse my blog posts and fix the sloppy HTML. Since trying to embed Python code in a blog post would be inelegant at best, I present the script in three different formats (including some neat <a href="http://softwaremaniacs.org/soft/highlight/en/" title="highlight.js">JavaScript syntax highlighting</a>):</p>
<ul>
<li><a href="http://gangles.ca/code/XHTMLscript.py">Python Script File (.py)</a></li>
<li><a href="http://gangles.ca/code/XHTMLscript_light.html">Syntax-highlighted HTML (Light)</a></li>
<li><a href="http://gangles.ca/code/XHTMLscript_dark.html">Syntax-highlighted HTML (Dark)</a></li>
</ul>
<p>I&#8217;m not sure that my code is especially <a href="http://faassen.n--tree.net/blog/view/weblog/2005/08/06/0" title="What is Pythonic?">pythonic</a>; sadly I have too many bad habits from Perl and Java. While I&#8217;m told that Python is frequently used as a scripting language, I get the impression that its real strength lies in larger applications. Furthermore, using regular expressions to parse HTML is a suboptimal solution, in retrospect I should have used an XML parser module. Any constructive criticism of my code is more than welcome, I&#8217;m here to learn.</p>
<p align="center" class="center"><a href="http://validator.w3.org/check?uri=http%3A%2F%2Fgangles.ca%2F"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Transitional" height="31" width="88" /></a><a href="http://jigsaw.w3.org/css-validator/"><img style="border:0;width:88px;height:31px" src="http://jigsaw.w3.org/css-validator/images/vcss"            alt="Valid CSS!" /></a></p>
<p>Code qualms aside, I can now proudly say that <em>The Quixotic Engineer</em> is written in valid XHTML 1.0 Transitional (the front page at least, I&#8217;m still working on some of the archive posts.) Coming up next: XHTML 1.0 Strict, and perhaps some CSS experimentation to spruce the place up a bit.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/06/11/fixing-simple-xhtml-errors-with-python/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Formality in Software Engineering</title>
		<link>http://gangles.ca/2008/04/09/formality-in-software-engineering/</link>
		<comments>http://gangles.ca/2008/04/09/formality-in-software-engineering/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 07:21:56 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Documentation]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=102</guid>
		<description><![CDATA[I&#8217;ve been following a very interesting thread on the skrud.net forums recently about the role of formal documentation in the software process. In it, Dr. Constantinos Constantinides interjected with some sound arguments in favor of formal documentation. I thought he presented a very persuasive defense of an aspect of software design that is often maligned [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been following a very interesting thread on the <a href="http://forum.skrud.net/">skrud.net forums</a> recently about the role of formal documentation in the software process. In it, <a href="http://www.cs.concordia.ca/~cc">Dr. Constantinos Constantinides</a> interjected with some sound arguments in favor of formal documentation. I thought he presented a very persuasive defense of an aspect of software design that is often maligned by undergraduate students. Because the thread in question requires forum registration to read, I sought his permission to reproduce the arguments here</p>
<p>The topic of discussion was SOEN341, Concordia&#8217;s &#8220;Software Process&#8221; class. Many past and present Concordia students were grumbling about what they felt was excessive formality and an overemphasis on arbitrary documentation completeness in the class. Dr. Constantinides&#8217; argument was as follows:</p>
<blockquote><p>In Software Engineering, I am not much interested in those things which you either can build on your own or you build only for yourself. I am very interested in those things that you alone cannot build and in those things that you together with a team of engineers build for others.  In doing that, you must prove to me (your boss, line-manager, stakeholder, etc.)  that what you are about to build is what you are expected to build (validation), and what you have built is what you were expected to build (verification). Asking me to &#8220;just trust&#8221; your code because &#8220;you know what you are doing&#8221; (maybe because you had a high GPA in some college, or you&#8217;ve been programming in this language for many years, etc.) is not enough for me. I cannot trust my medical / financial / &#8230; data on how sexy your CV looks. I want proof of concept for a solution to my problem. Architects and civil engineers refer to this as &#8220;blueprints&#8221;; Electrical engineers refer to this as &#8220;circuit diagrams&#8221;, etc. The proof of concept can done by paper and pencil, chalk on a blackboard, drawing software, etc.</p>
</blockquote>
<p>Later in the discussion he elaborated on this position:</p>
<blockquote><p>Let us talk about development as the production of a number of artifacts, at various levels of abstraction.</p>
<p>In my opinion EVERY artifact produced during development is important:  You have artifacts produced in a natural language (e.g. English), others produced in a modeling language (e.g. UML) and others produced in a formal system (e.g. C++). You must be fluent with all different languages because you use each one for a different purpose. Yes, we can argue that implementation is vital because code is absolutely necessary for a system to run. However, in the absence of a requirements / analysis / architecture / design model, your level of confidence on the correctness of the system is rather low (and the maintainability of your system is very low).</p>
<p>Someone told me: &#8220;Go to the code.&#8221; Yes, I can do that. I should be able to do that. The code describes your rationale at a very low level and it&#8217;s not very helpful for a number of reasons including a) I need to stop you from doing something wrong before you start coding and b) a formal system is rather cryptic when it&#8217;s the only means of communication. Again, let me reiterate that I am interested in VERY large scale systems, not something which is a couple of thousand lines.</p>
<p>To maintain a high level of confidence, you must build strong confidence during requirements analysis (validation) and maintain it throughout the development life cycle. Because as your project manager I am the one who is responsible for it (see: lose the contract, being sued, etc.), then if your use case model is not validated I will not allow you to proceed to analysis. If your analysis model is not validated I will not allow you to proceed with architecture-design and if your architecture-design is not validated I will not allow you to map it to code. If your code is not correct (if tests fail etc.) or consistent, I will not allow you to consider the verification of requirements successful (for example, assume iterative process).</p>
<p>There is no such a thing as &#8220;documentation and source code.&#8221; I would love to eliminate the word &#8220;documentation&#8221; from our vocabulary. Let us talk about artifacts and models. With the exception of the magnetic 1s and 0s, everything else (installation scripts, user&#8217;s manual with screen shots, test suite, source code, supporting libraries, architectural-design model, analysis model, use case model &#8211; requirements) can be regarded as &#8220;documentation.&#8221; However, the problem is that many software engineering textbooks (and many instructors in many schools) place emphasis EITHER on requirements / analysis / architecture / design XOR (that&#8217;s an exclusive OR) on implementation.  I think this creates confusion (and frustration) among students. Especially in the first case (emphasis on early stages only), it is very frustrating to focus on formatting (and dissemination) of reports and other issues as if a model will be mapped to implementation by magic or as if it&#8217;s not our job to map it. Give me the design mode in pencil and paper, as long as it is correct. Show me that you can faithfully map it to implementation.</p>
<p>Because of the above and with all tradeoffs considered, then my view is that ALL artifacts are equal.  In fact, there are artifacts produced even after deployment (e.g. execution traces) which are valuable for post-deployment tasks (maintenance and evolution).</p>
<p>[...]</p>
<p>One last comment. There is a misconception (among us) that Software Engineering is that bureaucratic activity you do AFTER you build something to provide supporting documentation and explain what you did so that you can satisfy your instructor/ line manager/ boss, etc.. This is wrong. The adoption of UML as a common vocabulary helps us produce small documents and the advancement of modern (iterative) process methods helps us do the whole thing with confidence. Software Engineering is not about avoiding programming.  In fact you cannot be a good software engineer if you are not a very good programmer.</p>
</blockquote>
<p>Thanks again to Dr. Constantinides for allowing me to quote him here.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/04/09/formality-in-software-engineering/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>CS Games &#8211; A.I. Competition (Part 4)</title>
		<link>http://gangles.ca/2008/03/31/cs-games-ai-competition-part-4/</link>
		<comments>http://gangles.ca/2008/03/31/cs-games-ai-competition-part-4/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 04:58:29 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[A.I.]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[CS Games]]></category>
		<category><![CDATA[Snake]]></category>
		<category><![CDATA[Tron]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=100</guid>
		<description><![CDATA[I think I had best wrap up this series before I completely alienate my non-programmer readers. Firstly, I have an algorithm by fellow blogger and mathematician Tim Sell of Planet Nectarius. [A.I Competition - Tim's Algorithm] What I did was get 3 values for all the empty spaces to the left, right and in front [...]]]></description>
			<content:encoded><![CDATA[<p>I think I had best wrap up this series before I completely alienate my non-programmer readers. Firstly, I have an algorithm by fellow blogger and mathematician Tim Sell of <a href="http://nectarius.net/">Planet Nectarius</a>.</p>
<p align="center" class="center"><a href="http://gangles.ca/code/AICompetition/Tim'sAlgorithm.txt">[A.I Competition - Tim's Algorithm]</a></p>
<blockquote><p>What I did was get 3 values for all the empty spaces to the left, right and in front of the player. To be &#8220;in front&#8221; the empty spaces must be connected to the forward move square and it must be forward of the player. So each connected space is bounded by a rectangle to one side of the current cycle position. I then regard each rectangles emptiness value as half if the nemesis cycle is within that rectangle. Then I arbitrarily decide to move to the square which has the second highest empty space value associated with it. [...] Basically the idea is to cut of the nemesis cycle from the empty space without retreating into it.</p>
</blockquote>
<p>He later added:</p>
<blockquote><p>I made a slight mistake, best explained by example: If I am getting the space that is south, the GetSpace function gets each empty square that&#8217;s below it and to the left and right recursively. What I meant it to do was to do that, but also go up again if it is still below the player&#8217;s cycle, this would let it account for spaces that go down and then up again to one side.</p>
</blockquote>
<p>To reiterate, what Tim&#8217;s algorithm does is compare the amount of space connected to the three spaces adjacent to the cycle. However, it only counts the spaces contained in a rectangle defined by the cycle and the scanning direction. To illustrate:</p>
<p align="center" class="center"><img src="http://www.gangles.ca/images/tim'salgorithm.jpg"></p>
<p>The forward scanners will only scan within the forward box, the left ones within the left box, and so on. It&#8217;s an interesting approach, but I fear that it may suffer from the same weakness as <a href="http://www.gangles.ca/code/AICompetition/Algorithm3.txt">algorithm 3</a>: doing a bad job of <a href="http://gangles.ca/2008/03/23/cs-games-ai-competition-part-2/">filling empty space slowly</a>. Without real code to test, of course, this is mere speculation.</p>
<p>Lastly, I have a few wild and crazy algorithm ideas I came up with while trying to approach the problem sideways. I don&#8217;t think any of them would work particularly well, but they make good thought exercises.</p>
<ul>
<li><b>The Calculus Approach:</b> I thought of this algorithm while working on a Numerical Methods assignment. We could send out a 90 scanners, 30 in each direction. These scanners would have semi-random behavior; they would never run into a wall if they could avoid it but would make all other turning decisions randomly. These scanners would leave walls behind themselves on cloned maps as they moved, and return their path length upon death. Once they have all died, we could take the average of their path lengths and choose to turn in the direction with the highest average. We could increase the number of scanners for a better estimation at the cost of processing time.</li>
<li><b>The Cardinal Directions Approach:</b> We could send out four scanners from the cycle: one that can only turn North and West, another North and East, another South and West, etc. We could then calculate the free space value for each cardinal direction using the average of the two ordinal directions: (NW+NE)/2 = N. We decide in which direction to turn based on this information.</li>
<li><b>Average of BFS and DFS:</b> I mentioned in <a href="http://gangles.ca/2008/03/28/cs-games-ai-competition-part-3/">my last post</a> that a Breadth First Search and a Depth First Search estimated free space in a slightly different way. Perhaps the best solution would be to perform both and take the average, hoping that the strengths of one would cancel out the weaknesses of the other. It would involve twice as much calculation, but I think it might actually work reasonably well.</li>
</ul>
<p>In conclusion, I would like to quickly thank Sven and William (my CS games teammates), Alexei, Andrew and <a href="http://nectarius.net/">Tim</a> (for taking the time to discuss their algorithms with me), and <a href="http://www.zaknafein.hjcrusaders.com/">Renaud</a> and Thomas (for the lengthy algorithm discussions.) I learned a lot by writing this series, and am now exceptionally prepared for next year&#8217;s A.I. competition.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/03/31/cs-games-ai-competition-part-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CS Games &#8211; A.I. Competition (Part 3)</title>
		<link>http://gangles.ca/2008/03/28/cs-games-ai-competition-part-3/</link>
		<comments>http://gangles.ca/2008/03/28/cs-games-ai-competition-part-3/#comments</comments>
		<pubDate>Fri, 28 Mar 2008 05:25:26 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[A.I.]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[CS Games]]></category>
		<category><![CDATA[Snake]]></category>
		<category><![CDATA[Tron]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=99</guid>
		<description><![CDATA[Since I returned from the CS games a few weeks ago, I&#8217;ve been vigorously discussing the Tron A.I. problem with anyone who would listen. Much of this took place on the skrud.net forums, where I had a chance to debate with Alexei and Andrew of the other Concordia team. Their team tied for third place [...]]]></description>
			<content:encoded><![CDATA[<p>Since I returned from the CS games a few weeks ago, I&#8217;ve been vigorously discussing the Tron A.I. problem with anyone who would listen. Much of this took place on the <a href="http://forum.skrud.net/">skrud.net forums</a>, where I had a chance to debate with Alexei and Andrew of the other Concordia team. Their team tied for third place on the second day, and they had some really interesting ideas. I&#8217;ll be posting snippets of our discussion here, including the pseudocode for their algorithm.</p>
<p>In <a href="http://gangles.ca/2008/03/23/cs-games-ai-competition-part-2/">part 2 of this series</a>, I wrote about how the recursive <a href="http://www.gangles.ca/code/AICompetition/Algorithm4.txt">Algorithm 4</a> was memory intensive because it needed to clone the entire map at every step. Alexei, however, thought of a very clever way to get around this problem by implementing <a href="http://en.wikipedia.org/wiki/Backtracking">backtracking</a>.</p>
<p align="center" class="center"><a href="http://gangles.ca/code/AICompetition/Backtracking.txt">[A.I Competition - Backtracking Algorithm]</a></p>
<p>Using this algorithm, you would need to clone the map exactly once (assuming the original map cannot be modified.) In Alexei&#8217;s words:</p>
<blockquote><p>Nothing is being cloned, because you are always operating on the same state. As it recurses in, it marks the node, and then unmarks it as it recurses out.</p>
<p>So if you&#8217;re in a 10-level deep recursion, you have 10 nodes marks as visited (ie the &#8220;path&#8221; you&#8217;re currently looking at). Suppose that you&#8217;re in that state, and there&#8217;s 3 directions for you to take (a, b, or c).</p>
<p>You call yourself on [a], which gets marked as visited. Then [a], calls all of its adjacent nodes, one by one. Each one marks itself as visited, and before it returns, it marks it as unvisited. So after your call on [a], your array of booleans (which you didn&#8217;t clone ever!), is in the same state as it was before the call. But you now have the longest path starting at [a]. Then you do the same for b and c, and return (to your parent caller), the longest of those three, and unmark your node as visited. Your parent caller does the same thing for all the other nodes adjacent to it, and returns to its parent, and so forth. It works.</p>
</blockquote>
<p>However, even with this modification an exhaustive longest path search can be no more efficient than O(2<sup>n</sup>), making it unsuitable for anything but small maps. We must therefore find a way to estimate the longest path in quadratic (or linear, ideally) time. The other Concordia team accomplished this as follows:</p>
<p align="center" class="center"><a href="http://gangles.ca/code/AICompetition/Algorithm5.txt">[A.I Competition - Alexei/Andrew/Jason's Algorithm]</a></p>
<p>Alexei explains once more:</p>
<blockquote><p>On startup, we calculated the density of the map (how dense walls are vs. empty space.) Then we implemented two general purpose algorithms:</p>
<p>1. BFS: <a href="http://en.wikipedia.org/wiki/Breadth-first_search">Breadth First Search</a> to the enemy. Finds the shortest path to the enemy, and returns the first direction.</p>
<p>2. LongestPath (modified BFS): Finds which of the three directions would produce the largest open space. Essentially, 3 BFS searches are done, each one from scratch from each of the possible directions. However, instead of terminating when something is found, you instead count how many locations were traversed in total (the algorithm terminates when all reachable locations are traversed). Algorithm returns the direction that gives the highest such value.</p>
<p>In addition, the LongestPath was modified to not return a direction that would put us in a location to which the enemy could also move next turn, as otherwise this can cause a tie.</p>
<p>The idea is: At first, you want to advance the closest possible to the enemy, to &#8220;conquer&#8221; the most ground. After this, you want to take the direction that would produce the longest path.</p>
<p>Since we didn&#8217;t have time to code something that would detect when advancing BFS to the enemy would put us in a dead end path in the future (i.e. locking us and the enemy into a trap), the density check was necessary. On maps with lots of walls, like the chessboard &#8211; this situation could happen, so our AI just goes for LongestPath all the time there.</p>
</blockquote>
<p>I&#8217;m really not sure how to go about analyzing their enemy chasing intelligence, other than to say that it sounds like a very good idea. When the wall density is low, following the longest path is less critical and it makes sense to try and restrict the amount of free space that the enemy has. This feature may very well have been their team&#8217;s winning edge. What is also remarkable about their algorithm, however, is how they went about searching for free space.</p>
<p>To reiterate, their team used a Breadth First Search, which is O(n), to estimate the longest path. Why is this an estimate? Because it fails to return the longest path (and therefore the theoretical best move) in every situation. Consider the following:</p>
<p align="center" class="center"><img src="http://www.gangles.ca/images/algorithmfail.jpg" title="Breadth First Search Estimation Failure" alt="Breadth First Search Estimation Failure" /></p>
<p>In this case, is it advantageous to turn right and survive for 7 turns. However, a modified BFS would choose to turn left, since there are a total of 8 free spaces as opposed to 7 on the right. The cycle would die sub-optimally in 4 turns. The same weakness is true for a modified <a href="http://en.wikipedia.org/wiki/Depth-first_search">depth-first search</a>:</p>
<p align="center" class="center"><img src="http://www.gangles.ca/images/algorithmfail2.jpg" title="Depth First Search Estimation Failure" alt="Depth First Search Estimation Failure" /></p>
<p>In this situation, the longest possible move is to turn left for 8 moves before dying. However, the modified DFS would return 6 for the right path and 5 for the left one, resulting in a disadvantageous right turn. Therefore, we can find specific situations where both BFS and DFS fail as estimators for the longest path.</p>
<p>Despite the shortcomings, I believe that estimating the longest path in this way is truly the most effective solution in a real time system. Since performing the exhaustive longest path search within the time constraints is impossible on a medium or large sized map, we must settle for using reasonable estimators. The modified BFS and DFS both do a very good job of measuring free space, each in a slightly different way.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/03/28/cs-games-ai-competition-part-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CS Games &#8211; A.I. Competition (Part 2)</title>
		<link>http://gangles.ca/2008/03/23/cs-games-ai-competition-part-2/</link>
		<comments>http://gangles.ca/2008/03/23/cs-games-ai-competition-part-2/#comments</comments>
		<pubDate>Mon, 24 Mar 2008 01:26:31 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[A.I.]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[CS Games]]></category>
		<category><![CDATA[Snake]]></category>
		<category><![CDATA[Tron]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=98</guid>
		<description><![CDATA[In my last post I wrote about the simple yet functional algorithms we wrote on the first day of the A.I. Competition. Today I will discuss the two more complex algorithms we developed on the second day and why they were both beautiful failures. [A.I Competition - 3rd Iteration] This is where the pseudocode starts [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://gangles.ca/2008/03/20/cs-games-ai-competition-part-1/">my last post</a> I wrote about the simple yet functional algorithms we wrote on the first day of the A.I. Competition. Today I will discuss the two more complex algorithms we developed on the second day and why they were both beautiful failures.</p>
<p align="center" class="center"><a href="http://www.gangles.ca/code/AICompetition/Algorithm3.txt">[A.I Competition - 3rd Iteration]</a></p>
<p>This is where the pseudocode starts to become a little obscure. Essentially, this is a case of algorithm 2 where the scanners can turn exactly once. In other words, at every point along the straight line search we send a second set of scanners out perpendicularly left and right until they reach a wall. We find the maximum value of the sum of a straight and perpendicular scanner and turn in that direction.</p>
<p>In theory this algorithm is more powerful than the one from our second iteration. It looks further ahead, avoiding the situation that prematurely killed our cycle in the first competition. However, in execution, it actually dies a bit faster than the previous A.I. on some maps. The reason for this is that algorithm 3 will often turn faster when filling up an empty space. For instance, in the diagram below, algorithm 2 survives four turns longer in an empty rectangular space.</p>
<p align="center" class="center"><img src="/images/Algorithm3Error.jpg" alt="Algorithm 3 Error" title="Algorithm 3 Error" width="450" /></p>
<p>While the light cycle deathmatch was ostensibly a head to head fight, matches usually degenerated into a race to fill a separate space more slowly than the opponent. Needing to slowly fill empty space was actually much more common than the situation that exposed the flaw in algorithm 2. Algorithm 3 was therefore a bit of a flop.</p>
<p align="center" class="center"><a href="http://www.gangles.ca/code/AICompetition/Algorithm4.txt">[A.I Competition - 4th Iteration]</a></p>
<p>Where algorithm 3&#8242;s scanners could turn exactly once, these scanners search the map exhaustively and turn as many times as possible. This is achieved recursively, with each cell calling the check method on the left, right and forward cells. The result is a longest path value for each direction, and the cycle chooses to turn towards the maximum of the three.</p>
<p>However, the moment you allow the scanner to turn more than once you must allow for the possibility of visiting the same cell more than once. Algorithm 4 gets around this by cloning the map at every step. The scanners can leave walls behind themselves on these replicated maps without affecting the real one. Note that the map must be cloned at every recursion and that is is the modified clone that is passed as a parameter to the next step.</p>
<p>Unless some bug in the pseudocode has evaded me, there is no logical error in this algorithm. It will find the longest movement possible on any kind of map, which is exactly what we were looking for. However, there are two big problems with it in execution.</p>
<ol>
<li>If placed in the centre of an empty map with <i>n</i> cells, this algorithm would have a worst case time complexity of <i>O(2<sup>n</sup>)</i>* (see <a href="http://en.wikipedia.org/wiki/Big_oh">Big O Notation</a>.) The resulting calculation would take much longer than one second to process.</li>
<li>The entire map is cloned at every recursion, potentially using a tremendous amount of memory. We could slightly improve on this by instead keeping a list of visited nodes, but this list would also need to be cloned. There is a very clever way to get around this problem, but I&#8217;ll save it for my next post.</li>
</ol>
<p>*Finding the time complexity of a recursive algorithm without having real code to test is tricky. I&#8217;m basing my analysis on the fact that <a href="http://en.wikipedia.org/wiki/List_of_NP-complete_problems">the longest path problem is NP-complete</a>. Feel free to disagree in your comments, and enjoy the following nerdy song (thanks Skrud.)</p>
<p align="center" class="center"><b>Longest Path &#8211; Daniel Barrett</b> [<a href="http://valis.cs.uiuc.edu/~sariel/misc/funny/longestpath.mp3">download</a>]<br />
<br /><object type="application/x-shockwave-flash" data="http://gangles.ca/wp-content/plugins/audio-player/player.swf" width="290" height="24" id="audioplayer1"><param name="movie" value="http://gangles.ca/wp-content/plugins/audio-player/player.swf" /><param name="FlashVars" value="playerID=1&amp;bg=0xf8f8f8&amp;leftbg=0xeeeeee&amp;lefticon=0x666666&amp;rightbg=0xcccccc&amp;rightbghover=0x999999&amp;righticon=0x666666&amp;righticonhover=0xffffff&amp;text=0x666666&amp;slider=0x666666&amp;track=0xFFFFFF&amp;border=0x666666&amp;loader=0x9FFFB8&amp;soundFile=http%3A%2F%2Fvalis.cs.uiuc.edu%2F%7Esariel%2Fmisc%2Ffunny%2Flongestpath.mp3" /><param name="quality" value="high" /><param name="menu" value="false" /><param name="bgcolor" value="#FFFFFF" /></object></p>
<p>Were time and memory not factors, algorithm 4 would be sufficient to find the longest path at every step. In a real time system, however, it&#8217;s unfortunately completely useless. Since algorithms 3 and 4 were failures, we were forced to resubmit algorithm 2 for the final competition.</p>
<p>I&#8217;ve been discussing this problem with programmers smarter than myself (including the other Concordia team who came in 3rd on the second day) ever since I got back from the CS Games and have learned a great deal in the process. In my next post I&#8217;ll be discussing a few of their solutions.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/03/23/cs-games-ai-competition-part-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
<enclosure url="http://valis.cs.uiuc.edu/~sariel/misc/funny/longestpath.mp3" length="1975167" type="audio/mpeg" />
		</item>
		<item>
		<title>CS Games &#8211; A.I. Competition (Part 1)</title>
		<link>http://gangles.ca/2008/03/20/cs-games-ai-competition-part-1/</link>
		<comments>http://gangles.ca/2008/03/20/cs-games-ai-competition-part-1/#comments</comments>
		<pubDate>Thu, 20 Mar 2008 08:20:48 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[A.I.]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[CS Games]]></category>
		<category><![CDATA[Snake]]></category>
		<category><![CDATA[Tron]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=97</guid>
		<description><![CDATA[I had a chance to participate in a number of events at the CS games, but the most interesting by far was the A.I. competition. All I had been told about the event beforehand was that in past years they had programmed the A.I. for Pac-man ghosts (enough for me to know that I HAD [...]]]></description>
			<content:encoded><![CDATA[<p>I had a chance to participate in a number of events at the CS games, but the most interesting by far was the A.I. competition. All I had been told about the event beforehand was that in past years they had programmed the A.I. for Pac-man ghosts (enough for me to know that I HAD sign up.) Fortunately this year&#8217;s challenge also did not disappoint, as we were asked to program the A.I. of the Light Cycles from Tron.</p>
<p align="center" class="center"><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/eMY1FaOKF-0&#038;hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/eMY1FaOKF-0&#038;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
<p>The match was played on a roughly 30&#215;30 grid where each cell was either empty, a wall or a cycle. Each player was given one second every turn to decide whether to move forward, left or right, with each movement leaving a wall in place behind. The cycle that could survive longest without running into a wall or another cycle was deemed the winner.</p>
<p>The competition took place over two sessions, the first worth 25% and the second 75%. The A.I.s from all thirty schools went head to head in a round robin tournament at the end of each day. With this in mind, my teammates and I decided to apply what we were learning in Software Processes and grow the program iteratively. This was a wise decision; we had a simple yet effective working model ready for the first competition while many groups were still debugging their more complex algorithms. In the end, we tied for 6th on the first day and 10th on the second.</p>
<p>After the competition, however, I found myself still thinking about this problem. It&#8217;s a twist on pathfinding, as there&#8217;s no set destination, and could nearly be described as a longest path problem. The ideal solution has to be flexible enough to accommodate both narrow corridors and open spaces. Our algorithms didn&#8217;t even take into account the position of the enemy, mostly because we weren&#8217;t sure what to do with that data.</p>
<p>I&#8217;ve written from memory the pseudocode for our four iterations, as well as a little something about their performance, strengths and weaknesses. I present this in the hopes that you too will get this problem stuck in your brain, and will soon return to comment with your wild and crazy ideas about the best Tron A.I.</p>
<p><i>Note: I&#8217;ve tried to keep my pseudocode notation consistent and as close to plain English as possible. They looked ugly when embedded, so click through to read each txt.</i></p>
<p align="center" class="center"><a href="http://www.gangles.ca/code/AICompetition/Algorithm1.txt">[A.I Competition - 1st Iteration]</a></p>
<p>We began with a very simple algorithm that could look exactly one square ahead. It would therefore never run into a wall unless it was the only possible move. It&#8217;s simple and it works reasonably well, but with no foresight it quickly gets caught in traps that it should have avoided. There&#8217;s really not much else to say about it, it was a stepping stone to greater things.</p>
<p align="center" class="center"><a href="http://www.gangles.ca/code/AICompetition/Algorithm2.txt">[A.I Competition - 2nd Iteration]</a></p>
<p>Our next plan was to look in a straight line in every direction, and turn in the direction with the most empty space. Another simple yet solid algorithm, but with more foresight than the first. This was what we ended up submitting for the first day&#8217;s competition, so we have a glut of experimental data on it. Namely, we discovered one common situation that it handles very poorly.</p>
<p align="center" class="center"><img src="/images/Algorithm2Error.jpg" alt="Algorithm 2 Error" title="Algorithm 2 Error" /></p>
<p>We lost two of our first round matches getting caught in this scenario. Any human can see that the correct choice in the above situation is to turn left, but algorithm 2 only evaluates one block left and one block forward. Since we hard coded it to move forward in the event of a tie, it traps itself and dies in two turns. Clearly a robust A.I. would need to evaluate length around corners, a concept that we applied to our next iteration.</p>
<p>Since I got a little carried away with the diagram, I&#8217;ll finish writing about our two final iterations this weekend. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/03/20/cs-games-ai-competition-part-1/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>CS Games in Pictures</title>
		<link>http://gangles.ca/2008/03/12/cs-games-in-pictures/</link>
		<comments>http://gangles.ca/2008/03/12/cs-games-in-pictures/#comments</comments>
		<pubDate>Wed, 12 Mar 2008 21:26:07 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CS Games]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=96</guid>
		<description><![CDATA[I&#8217;ll write something a little more detailed later this week about the competitions themselves, but for now here&#8217;s a weekend in pictures Meeting up Friday morning at 100 Génies, L&#8217;École de Technologie Supérieure&#8217;s pub. Some of us start things off early with a Laurentide. The ETS team, with whom we shared the bus ride up, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll write something a little more detailed later this week about the competitions themselves, but for now here&#8217;s a weekend in pictures</p>
<p align="center" class="center"><img src="/images/CSgames/01departure.jpg" alt="Sharing a Laurentide at 100 Génies" title="Sharing a Laurentide at 100 Génies" width="450" /></p>
<p>Meeting up Friday morning at 100 Génies, L&#8217;École de Technologie Supérieure&#8217;s pub. Some of us start things off early with a Laurentide.</p>
<p align="center" class="center"><img src="/images/CSgames/02supplies.jpg" alt="Molson Ex and Red Bull" title="Molson Ex and Red Bull" width="450" /></p>
<p>The ETS team, with whom we shared the bus ride up, came well prepared.</p>
<p align="center" class="center"><img src="/images/CSgames/03arrival.jpg" alt="I had never seen so many Macbooks, EEEPCs and DSs before" title="I had never seen so many Macbooks, EEEPCs and DSs before" width="450" /></p>
<p>Nerds and laptops as far as the eye can see.</p>
<p align="center" class="center"><img src="/images/CSgames/04DS.jpg" alt="I can appreciate Tetris mathematically and conceptually, but find it no fun to play" title="I can appreciate Tetris mathematically and conceptually, but find it no fun to play" width="450" /></p>
<p>Tetris DS got a lot of playtime this weekend.</p>
<p align="center" class="center"><img src="/images/CSgames/05chocolate.jpg" title="The computer labs all had electrical engineering equipment in them for some reason" alt="The computer labs all had electrical engineering equipment in them for some reason" width="450" /></p>
<p>Alex and Jacob with Concordia&#8217;s secret chocolatey weapon.</p>
<p align="center" class="center"><img src="/images/CSgames/06ETS.jpg" title="C'est l'ETS qui rentre en place pour boire, pour boire..." alt="C'est l'ETS qui rentre en place pour boire, pour boire..." width="450" /></p>
<p>ETS rockin&#8217; the white shirts and red suspenders, they definitely had the coolest team outfits (and were just all around terrific people.)</p>
<p align="center" class="center"><img src="/images/CSgames/07snacks.jpg" title="Quebec Spring doesn't start for another month or two, eh?" alt="Quebec Spring doesn't start for another month or two, eh?" width="450" /></p>
<p>Braving the snow to get midnight snacks.</p>
<p align="center" class="center"><img src="/images/CSgames/08mural.jpg" title="I only got lost twice" alt="I only got lost twice" width="450" /></p>
<p>A Concordia University mural we found in the underground tunnels. Incidentally, L&#8217;Université de Sherbrooke is built like a labyrinth. We actually had the sports competition in the tunnels because of the weather.</p>
<p>Finally, here&#8217;s <a href="http://www.harleyjcooper.com/gifs.html">our entire CS games team rocking out to 8-bit DragonForce</a>. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/03/12/cs-games-in-pictures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;m Off To Sherbrooke</title>
		<link>http://gangles.ca/2008/03/07/im-off-to-sherbrooke/</link>
		<comments>http://gangles.ca/2008/03/07/im-off-to-sherbrooke/#comments</comments>
		<pubDate>Fri, 07 Mar 2008 06:40:27 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CS Games]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=95</guid>
		<description><![CDATA[You may think that the &#8220;big event&#8221; this weekend is happening down in Austin, Texas. However, the hippest of the hip know that the REAL place to be is scenic Sherbrooke, Quebec. This year the Université de Sherbrooke is hosting the 2008 Computer Science Games, where programming nerds from all over Canada and the U.S. [...]]]></description>
			<content:encoded><![CDATA[<p>You may think that the &#8220;big event&#8221; this weekend is happening down in Austin, Texas. However, the hippest of the hip know that the REAL place to be is scenic Sherbrooke, Quebec.</p>
<p align="center" class="center"><img src="/images/SherbrookePostcard.jpg" alt="It certainly is Sherbrooke" title="It certainly is Sherbrooke" /></p>
<p>This year the Université de Sherbrooke is hosting the <a href="http://www.csgames.org/2008/">2008 Computer Science Games</a>, where programming nerds from all over Canada and the U.S. gather to do battle on the field of code. The events include (descriptions copied from the CS games website):</p>
<ul>
<li><b>Debugging</b> &#8211; &#8220;The creator of this competition gave a new meaning to “strong coupling”, “obfuscated code” and “spaghetti code” and refuses to believe that some programmers can live without GOTOs. The “/” and “#” keys of his keyboard are as shiny as they were when they were assembled. So many bugs and so little time to solve them all.&#8221;</li>
<li><b>Extreme Programming</b> &#8211; &#8220;Two programmers, one computer. This is the basic principle of this competition, but of course, we added a twist or two! Participants will get a unique occasion to test their coding skills with a buddy and enjoy this unique bonding experience under extreme circumstances! Remember, what happens in XP stays in XP… or on the Internet.&#8221; </li>
<li><b>Relay Programming</b> &#8211; &#8220;This is our new home brewed competition. 3 competitors will have 3 hours to code 3 different applications. Seems easy? Well, each of them will only be able to work one hour per application before having to relay it to another team member. WHAT, no comments!!! &#038;*%*$!&#8221;</li>
<li><b>Team Software Engineering</b> &#8211; &#8220;We sure hope competitors have good design skills, because this time, there’s no going back to the drawing board! After a short planning period, team members are isolated for implementation. At the end, the team get a short period of time to stick the pieces of the puzzle together. It better fit well!&#8221;</li>
<li><b>Many more</b></li>
</ul>
<p>This is my first year attending the CS games so I&#8217;m not quite sure what to expect, but from what I hear it&#8217;s a three day whirlwind of nerdy fun, code and beer. We&#8217;re heading up tomorrow afternoon with the ETS team, who I&#8217;m sure will drink us under the table at the dégrise. Wish us luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/03/07/im-off-to-sherbrooke/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Montreal Girl Geek Dinners</title>
		<link>http://gangles.ca/2008/02/27/montreal-girl-geek-dinners/</link>
		<comments>http://gangles.ca/2008/02/27/montreal-girl-geek-dinners/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 05:34:40 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Montreal]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Girl Geek Dinners]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=93</guid>
		<description><![CDATA[This evening I was graciously invited by a friend to attend the 3rd Montreal Girl Geek Dinner. Boy geeks such as myself were welcome as the guest of a girl geek. The goal of the event is described as follows: Montreal Girl Geek Dinners are an offshoot of the London Girl Geek Dinners, started by [...]]]></description>
			<content:encoded><![CDATA[<p>This evening I was graciously invited by a friend to attend the 3rd <a href="http://www.montrealgirlgeekdinners.blogspot.com/">Montreal Girl Geek Dinner</a>. Boy geeks such as myself were welcome as the guest of a girl geek. The goal of the event is described as follows:</p>
<blockquote><p><img src="/images/GirlGeekDinners.png" style="float:right;margin:0 0 10px 10px;" alt="Girl Geek Dinners" title="Girl Geek Dinners" border="0" />Montreal Girl Geek Dinners are an offshoot of the London Girl Geek Dinners, started by Sarah Blow. The goal of these get-togethers is to make technology accessible and interesting to all age groups and all people, particularly women.</p>
<p>These monthly events are aimed at providing a welcoming atmosphere and a platform for learning in an informal environment. They are always held in pubs, bars or restos and there is usually a speaker (or several) who talk for a short while on a chosen subject for the evening.</p>
</blockquote>
<p>The event lasted 3-4 hours, a large part of which was spent eating and networking. I had a chance to speak with the organizer Tanya McGinnity as well as Peter Yang, a designer at Ubisoft Montreal. The attendees came from many different backgrounds; some were programmers and web designers, others were just self-described geeks. In the spirit of making these events accessible, the speakers avoid getting too technical.</p>
<p>This evening&#8217;s talk by Aleece Germano was about self-employment. Ms. Germano encouraged us to adopt the mindset that everyone, even nine-to-fivers, are really self-employed. She spoke of her own experience as a consultant, how to develop professional relationships with clients, and how to protect yourself legally and financially in these situations.</p>
<p>Though I have no personal interest in being self-employed, a lot of what she said was just good general career advice. The other Girl Geek Dinner topics chosen so far sounded great too. Last month Angela Byron did a talk on Open Source development, and Heather Kelley of <a href="http://www.kokoromi.org/">Kokoromi</a> spoke in December.</p>
<p>These dinners are a fantastic initiative, and if one is <a href="http://girlgeekdinners.com/">being hosted in your area</a> I strongly urge you to check it out. Kudos to the organizers, great job.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/02/27/montreal-girl-geek-dinners/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CUSEC 2008</title>
		<link>http://gangles.ca/2008/01/20/cusec-2008/</link>
		<comments>http://gangles.ca/2008/01/20/cusec-2008/#comments</comments>
		<pubDate>Sun, 20 Jan 2008 18:23:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Montreal]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[CUSEC]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=81</guid>
		<description><![CDATA[Yesterday marked the end of CUSEC 2008, a three day software engineering conference for Canadian university students. While the conference has been going annually since 2002, this was my first year attending. I had initially planned to be quasi-live blogging the whole thing, but I hadn&#8217;t realized how busy the three days were going to [...]]]></description>
			<content:encoded><![CDATA[<p align="center" class="center"><img src="http://bp1.blogger.com/_hO-sQLbz_Co/R5OTwSLvlCI/AAAAAAAAAHs/W_BQzPFOP6w/s400/CUSEC.JPG" border="0" alt="CUSEC 2008" /></p>
<p>Yesterday marked the end of CUSEC 2008, a three day software engineering conference for Canadian university students. While the conference has been going annually since 2002, this was my first year attending. I had initially planned to be quasi-live blogging the whole thing, but I hadn&#8217;t realized how busy the three days were going to be. Instead, here&#8217;s a quick recap of some of the terrific people I heard from at CUSEC.</p>
<ul>
<li><b>Day One</b>
<ul>
<li><a href="http://www.tbray.org/ongoing/When/200x/2008/01/18/CUSEC-2008">Tim Bray</a> &#8211; Hard Problems in Network Computing<br />
One of the co-editors of XML, he gave a great talk about some of the difficult problems that programmers are having little success in solving. I don&#8217;t remember the exact words he used (relying on my brain was a bad idea, I plan to take better notes next year), but the main problems were communication between different programming languages and taking advantage of parallel processing.</li>
<li>Dr. Marsha Chechik &#8211; Guarding Against Software Accidents</li>
<li><a href="http://www.zedshaw.com/blog/index.html">Zed Shaw</a> &#8211; The ACL is Dead<br />
Author of the Mongrel web server and notorious blogger, he talked about staying creative in the face of bureaucracy and corporate greed. The part of his keynote that really struck a chord with me was that &#8220;managers want all of your creativity, but trust none of your judgement.&#8221; I had a chance to talk to Zed later at Brutopia and a little throughout the conference, he was a really cool guy with a lot to say. Here&#8217;s hoping he comes again next year.
</li>
<li>Bruce Miner &#8211; Taking Risk</li>
</ul>
</li>
<li><b>Day Two</b>
<ul>
<li><a href="http://www.afroginthevalley.com/2008/01/18/vive-le-feu.html">Sylvain Carle</a> &#8211; We Didn&#8217;t Start The Fire<br />
A self-described &#8220;venture technologist&#8221;, he talked about why we should consider founding or working for startup companies.</li>
<li>Michel Martin &#8211; The Evolution of Large Scale Business Software</li>
<li>Dr. Peter Grogono &#8211; Living with Concurrency<br />
This talk was a bit over my head, but it really made me appreciate what a problem concurrency is and will be in the coming years. Dr. Grogono is one of the most loved computer science teachers at Concordia, and after hearing him speak I can understand why.</li>
<li><a href="http://en.wikipedia.org/wiki/Jeffrey_D._Ullman">Dr. Jeffrey Ullman</a> &#8211; When Theory Matters<br />
Prolific textbook writer and Ph.D. advisor of Sergey Brin (co-founder of Google), Dr. Ullman spoke about the theory of how Google&#8217;s PageRank system works, as well as variations such as minhashing and locality-sensitive hashing.</li>
<li>Jeff Bailey (Google Corporate Speaker) &#8211; Hacking on Open Source After Graduation<br />
He talked about the history of OSS and why major companies like Google and IBM invest millions to develop it. I had always been interested in contributing to an open source project, but after hearing his talk I feel compelled to begin doing so within the next few months.</li>
</ul>
</li>
<li><b>Day Three</b>
<ul>
<li>Zed Shaw &#8211; <a href="http://en.wikipedia.org/wiki/Factor_%28programming_language%29">Factor</a> Tutorial</li>
<li>Dr. Jeremy Cooperstock &#8211; Music &amp; Games: How Fun Applications Stimulate Core Technologies<br />
I really enjoyed this presentation, he began by talking about how the video game industry has been accelerating technological progress, which included some of his own research into the &#8220;next step&#8221; of virtual reality. The meat of his talk, however, was about his research into ways of overcoming network latency to allow people in separate parts of the world to play music and talk together naturally.</li>
<li><a href="http://blog.jonudell.net/">Jon Udell</a> &#8211; Hacking the Noosphere<br />
Another talk that was a bit over my head, he spoke about keeping the focus of Web 2.0 and information sciences on people, and how we can gather information in a human-centric way.</li>
<li><a href="http://www.codinghorror.com/blog/archives/001039.html">Jeff Atwood</a> &#8211; Is Writing More Important than Programming?<br />
As a big fan of <a href="http://www.codinghorror.com/">Coding Horror</a>, I had been looking forward to this talk from the beginning. In his keynote, he argued that writing for people was in many ways more important than writing for machines, and that it is crucial to &#8220;convince other people that your code, in a world positively overflowing with free code, is worth looking at in the first place.&#8221; His talk provided a counterpoint to some of the more technical presentations, and was a fantastic way to close the conference. Better yet, his talk inspired my friend Malini to pick up <a href="http://nakedn00b.blogspot.com/">her abandoned blog</a> again!</li>
</ul>
</li>
</ul>
<p>I can&#8217;t believe how much I learned in three days. Hearing from passionate people and being in a community full of fellow coding geeks has really inspired me to be creative, take chances and really explore the world of software engineering. I&#8217;ll definitely be attending CUSEC 2009!</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/01/20/cusec-2008/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Case of the Mystery Operator</title>
		<link>http://gangles.ca/2008/01/08/the-case-of-the-mystery-operator/</link>
		<comments>http://gangles.ca/2008/01/08/the-case-of-the-mystery-operator/#comments</comments>
		<pubDate>Tue, 08 Jan 2008 04:47:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=78</guid>
		<description><![CDATA[Inspired partially by xkcd and partially by testimony from other programmers, I&#8217;ve decided to take up learning Python in my spare time. I&#8217;ve been using the free e-book Dive Into Python as a reference, and it&#8217;s been an interesting experience so far (whitespace for code blocks!?) I was showing the Python Shell to my friend [...]]]></description>
			<content:encoded><![CDATA[<div align="justify">
<img style="float:right;margin:0 0 10px 10px;" src="http://bp1.blogger.com/_hO-sQLbz_Co/R4L28iLvk7I/AAAAAAAAAG4/fcg1S_MvEf4/s400/PythonLogo.png" border="0" width="200" alt="Python" /></p>
<p>Inspired partially by <a href="http://xkcd.com/353/">xkcd</a> and partially by testimony from other programmers, I&#8217;ve decided to take up learning <a href="http://www.python.org/">Python</a> in my spare time. I&#8217;ve been using the free e-book <a href="http://www.diveintopython.org/">Dive Into Python</a> as a reference, and it&#8217;s been an interesting experience so far (whitespace for code blocks!?)</p>
<p>I was showing the Python Shell to my friend Thomas the other day, and he typed in a few equations to try it out. While &#8220;2+2&#8243; and &#8220;3*8&#8243; resolved normally, &#8220;2^3&#8243;, which is a standard notation for two raised to the third power, returned &#8220;1&#8243;. We were a bit confused, but decided that the caret symbol &#8220;^&#8221; must mean something else in Python. We entered a few more formulas in an attempt to discover what the symbol meant, and here are the results:</p>
<ul>
<li><tt>1^0 = 1</tt></li>
<li><tt>1^2 = 3</tt></li>
<li><tt>2^0 = 2</tt></li>
<li><tt>2^2 = 0</tt></li>
<li><tt>2^3 = 1</tt></li>
<li><tt>3^2 = 1</tt></li>
<li><tt>3^4 = 7</tt></li>
<li><tt>4^1 = 5</tt></li>
</ul>
<p>Try as we might, we just couldn&#8217;t figure out what this operator did. I had a theory that it had something to do with modular arithmetic, but some cases just didn&#8217;t fit. Despite our combined brain power, we just couldn&#8217;t crack it, and after twenty minutes consented to Googling it.</p>
<p>I would challenge you to try and figure it out yourself! For cheaters, the answer is below.</p>
<h4>***********ANSWER***********</h4>
<p>In Python, two multiplication symbols &#8220;**&#8221; are used to indicate exponents, while the caret symbol in this context is used to indicate XOR (exclusive or). Since I was comparing two integers, the computer was doing bitwise XOR on the two numbers and returning the result as an integer. For instance:</p>
<p><tt>2 = 010 (binary), 3 = 011 (binary), 010 XOR 011 = 001 = 1</tt><br />
<tt>3 = 011 (binary), 4 = 100 (binary), 011 XOR 100 = 111 = 7</tt></p>
<p>It was obvious in retrospect, but my mind was so focused on the usual mathematical operators that I hadn&#8217;t even considered the basic computer operations. However, as it is with most lessons learned the hard way, I&#8217;ll remember for the rest of my life how to do an exclusive or in Python.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2008/01/08/the-case-of-the-mystery-operator/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Scruffy Programmers</title>
		<link>http://gangles.ca/2007/12/30/scruffy-programmers/</link>
		<comments>http://gangles.ca/2007/12/30/scruffy-programmers/#comments</comments>
		<pubDate>Sun, 30 Dec 2007 21:37:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=76</guid>
		<description><![CDATA[It&#8217;s a well known fact that programmers are generally unkempt, hairy and scruffy-looking fellows. Some believe this is due to the fact that, without a beard to rub, we would be unable to think. Justin Etheredge, however, suggests that we are merely emulating our computer science heroes, burly men such as Dijkstra, Stallman and Knuth. [...]]]></description>
			<content:encoded><![CDATA[<div align="center"><img style="display:block;text-align:center;margin:0 auto 10px;" src="http://bp3.blogger.com/_hO-sQLbz_Co/R3gP2iLvk3I/AAAAAAAAAGY/hPPYULp7ZMA/s400/FamousComputerGuys.jpg" border="0" alt="Scruffy Programmers" /></div>
<p>It&#8217;s a well known fact that programmers are generally unkempt, hairy and scruffy-looking fellows. Some believe this is due to the fact that, without a beard to rub, we would be unable to think. <a href="http://www.codethinked.com/">Justin Etheredge</a>, however, suggests that we are merely emulating our computer science heroes, burly men such as Dijkstra, Stallman and Knuth. His gallery of scruffiness is well worth a click and a read.</p>
<p>Fear not clean-shaven programmers, you can always say that your well-groomed face is a tribute to <a href="http://en.wikipedia.org/wiki/Alan_turing">Alan Turing</a>.</p>
<p>[<a href="http://www.codethinked.com/post/2007/12/The-Programmer-Dress-Code.aspx">The Programmer Dress Code</a> - CodeThinked]</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2007/12/30/scruffy-programmers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sunday Reading</title>
		<link>http://gangles.ca/2007/12/09/sunday-reading/</link>
		<comments>http://gangles.ca/2007/12/09/sunday-reading/#comments</comments>
		<pubDate>Sun, 09 Dec 2007 20:10:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Video Games]]></category>
		<category><![CDATA[Game Industry]]></category>
		<category><![CDATA[MMORPG]]></category>
		<category><![CDATA[Team Fortress 2]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=70</guid>
		<description><![CDATA[December is a busy time of year. Busy cramming for the exams next week? Caught up in the holiday rush? Either way, you&#8217;re probably online looking for an excuse to procrastinate for another hour or so. Here&#8217;s some recommended reading to help you do just that. First up is an article over at CGSociety about [...]]]></description>
			<content:encoded><![CDATA[<p>December is a busy time of year. Busy cramming for the exams next week? Caught up in the holiday rush? Either way, you&#8217;re probably online looking for an excuse to procrastinate for another hour or so. Here&#8217;s some recommended reading to help you do just that.</p>
<p>First up is an article over at CGSociety about <a href="http://features.cgsociety.org/story_custom.php?story_id=4338">the visual design of Team Fortress 2</a>. I&#8217;ve <a href="http://gangles.ca/2007/09/12/meet-the-engineer/">geeked out more than once</a> about how much I love this particular aspect of the game, but reading this article has given me a new found respect for the team of animators at Valve. Among the piles of great concept art (including an early build of the Heavy with a mullet), the article explores how well-designed characters and maps can enhance the gameplay experience. Consider the following excerpt:</p>
<p><img src="http://bp1.blogger.com/_hO-sQLbz_Co/R1wzfO0LdvI/AAAAAAAAAFY/eTSW7XWkG4g/s320/heavymullet.JPG" style="margin: 0pt 10px 10px 0pt; float: left" alt="TF2 Heavy with Mullet" border="0" /></p>
<blockquote><p>Due to the importance of the nine character classes to the gameplay, the team focused on them first. They established a &#8220;read hierarchy&#8221;, a prioritized list of the information that players needed to extract from the character model. From most to least important, this was: the player&#8217;s team, the player&#8217;s class, and the player&#8217;s current weapon, which usually implies the player&#8217;s intent in our game.</p>
<p>They used the model color palette to represent the team, a somewhat suboptimal solution for varying lighting conditions, but a good tradeoff given the technology constraints. “We found that silhouette and animation were better long-range identification characteristics than texture detail or color,” says Jamaal Bradley, “so we used those for class identification. Finally, we tackled the weapon by using contrast and color gradients to draw the player&#8217;s eye to the chest area, where the weapons are held.</p></blockquote>
<p>What a powerfully simple idea: using colour, shading and silhouettes to draw the player&#8217;s eye towards important information. It&#8217;s this level of attention to detail that has garnered Valve so much critical acclaim and fan loyalty. For more TF2 reading, consider the <a href="http://www.steampowered.com/status/tf2/tf2_stats.php">recently released Steam statistics</a>, which include heatmaps and other interesting tidbits (such as the fact that the Medic class is criminally underplayed.)</p>
<p>Secondly is a <a href="http://www.eweek.com/article2/0,1895,1245602,00.asp">fascinating look at the Morris worm</a>, a 99 line program that ended up infecting 10% of the Internet back in 1988. The creator, Robert T. Morris, was a grad student working at Cornell University who simply wanted to prove that it was possible to propagate a program by exploiting vulnerabilities in sendmail and Finger. However, due to a flaw in the reproduction algorithm, the benign worm ended up reproducing itself many times on the same computer, eventually tying up the CPU. While the Morris Worm has been overshadowed by some of the <a href="http://en.wikipedia.org/wiki/Notable_computer_viruses_and_worms">modern malignant worms</a>, I highly recommend this article to anyone involved in software security as a case study from a time when the web was much more homogeneous.</p>
<p><img src="http://bp1.blogger.com/_hO-sQLbz_Co/R1xFdO0LdxI/AAAAAAAAAFo/htdAlIq0F5w/s400/theprize.bmp" style="margin: 0pt 0pt 10px 10px; float: right" alt="EVE Online Heist" /></p>
<p>Finally, a short article about <a href="http://eve.klaki.net/heist/">one of the most famous and successful heists</a> in MMORPG history, one that left the victim&#8217;s character frozen dead in space and relieved of virtual goods worth an estimated $16,500 USD. It&#8217;s a fascinating look into the world of EVE Online, a game that seems to be as much about political intrigue and skulduggery as it is about spaceships and mining. The story reads like a virtual Ocean&#8217;s Eleven, and is an interesting commentary on the consequences of meeting people semi-anonymously in online worlds.</p>
<p>Have a great weekend, and best of luck in all your procrastinating.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2007/12/09/sunday-reading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Databases Final Project</title>
		<link>http://gangles.ca/2007/08/23/databases-final-project/</link>
		<comments>http://gangles.ca/2007/08/23/databases-final-project/#comments</comments>
		<pubDate>Thu, 23 Aug 2007 00:12:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[School]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=32</guid>
		<description><![CDATA[&#8230;and that concludes a very busy four day programming marathon. The final project for my Databases class involved creating a database and web interface for a hospital. We were a five person group, and I was responsible for designing the interface for the doctors, nurses and residents. Elaine wrote the interface for Administrators and Directors, [...]]]></description>
			<content:encoded><![CDATA[<div align="justify">
<p>&#8230;and that concludes a very busy four day programming marathon. The final project for my Databases class involved creating a database and web interface for a hospital. We were a five person group, and I was responsible for designing the interface for the doctors, nurses and residents. Elaine wrote the interface for Administrators and Directors, Sven and Fadhl were in charge of the MySQL database and Alex used Dreamweaver to make a great looking site.</p>
<p>All in all this was a great learning experience. Fortunately for me, Elaine was quite familiar with PHP/Javascript and sent me over lots of code that I could use as a template for my own work. I was already familiar with Perl and Html, so PHP wasn&#8217;t especially foreign. I managed to write ~18 interactive pages that allowed doctors to view their patient list, add/modify/delete patients, view their schedules and paystubs, etc.</p>
<p>Unfortunately, our project demo today didn&#8217;t go as well as planned. Databases was a rather involved four credit class, and taking it in ~5 weeks really didn&#8217;t allow us to invest as much time into our final project as we would have liked. Due to inadequate testing, our demo was full of errors and bugs. I&#8217;m not expecting a very high mark, which is ashame because we put lots of work into it.</p>
<p>At the very least, this project has taught me a great deal about group programming dynamics and the importance of code testing. It&#8217;s very likely I&#8217;ll work with the same group of people again in the future.</p>
<p>I was going to write a big post Monday about the Bioshock demo, but I was unfortunately too busy programming. I&#8217;ve now decided to wait and and just write a review of the whole game in the near future.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2007/08/23/databases-final-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Image Header &amp; Favicon</title>
		<link>http://gangles.ca/2007/07/30/new-image-header-favicon/</link>
		<comments>http://gangles.ca/2007/07/30/new-image-header-favicon/#comments</comments>
		<pubDate>Mon, 30 Jul 2007 05:10:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Blogger]]></category>
		<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=24</guid>
		<description><![CDATA[New header/favicon today, and a renewed appreciation for the hard work of graphic artists. While the Blogger template I had before did look a little more professional, I think I did pretty well for an amateur (go go MS Paint!). I figured out how to make these modifications using a combination of guides and trial [...]]]></description>
			<content:encoded><![CDATA[<p class="center" align="center"><img src="http://img.photobucket.com/albums/v410/Tolbi/new_header.jpg" alt="A Selection of Great Books, Movies &amp; Games" width="420" border="0" /></p>
<p>New header/favicon today, and a renewed appreciation for the hard work of graphic artists. While the Blogger template I had before did look a little more professional, I think I did pretty well for an amateur (go go MS Paint!). I figured out how to make these modifications using a combination of guides and trial &amp; error. I&#8217;ve compiled the information I found into the small guide below, I hope you find it useful.</p>
<p><strong>Using an Image as a Header</strong></p>
<p>I found most of the information on how to make this modification <a href="http://tips-for-new-bloggers.blogspot.com/2007/03/add-picture-banner-link-to-blogger.html" target="_blank">here</a>. The first step is to remove the old header. Blogger doesn&#8217;t allow you to remove it as a page element normally, so we&#8217;ll have to change the template html first. From the Blogger dashboard go to Template &gt; Edit HTML. <a href="http://dummies-guide-to-google-blogger.blogspot.com/2007/03/how-to-backup-your-new-blogger-template.html" target="_blank">Back up your template</a> and then look for the following code:</p>
<p><textarea rows="2" cols="53">&lt;b:widget id='Header1' locked='true' title='YOURBLOG (Header)' type='Header'/&gt;</textarea></p>
<p>Replace the word <i>true</i> with <i>false</i> and save your template. You can now remove your old header as you would any other page element. We will now replace it with the image header, which I recommend you use <a href="http://photobucket.com" target="_blank">Photobucket</a> to host. Go to Template &gt; Page Elements, and create a new Javascript/html page element, then insert the following code:</p>
<p><textarea rows="2" cols="53"><a href="YOUR BLOG'S URL"><img src="YOUR NEW IMAGE HEADER'S URL" /></a></textarea></p>
<p>Move this new Page Element over to where your old header used to be and hit the &#8220;Save&#8221; button. However, depending on your template, you may notice that you still have a small piece of your old header above your image. To remove this, delete the following line of code from your template&#8217;s html:</p>
<p><textarea rows="3" cols="53">&lt;div id='header-wrapper'&gt;&lt;b:section class='header' id='header' maxwidgets='1' showaddelement='no'/&gt;&lt;/div&gt;</textarea></p>
<p><strong>Using a Favicon with Blogger</strong></p>
<p>See that little picture next to the &#8220;http&#8221; in the address bar? That&#8217;s called a Favicon, and by default Blogger gives you an orange one with a letter B. If you&#8217;d like to change this to your own icon, first head on over to <a href="http://tools.dynamicdrive.com/favicon/" target="_blank">FavIcon Generator</a> and save the .ico file it generates. Usually, a webamaster would host this on their own site, but since you can&#8217;t do this on Blogger we&#8217;ll have to host it externally. Since Photobucket doesn&#8217;t let you upload .ico files, so I recommend you use <a href="http://imagedip.com/index.php" target="_blank">ImageDip</a>. Next we&#8217;re going to edit the html template, so once again remember to <a href="http://dummies-guide-to-google-blogger.blogspot.com/2007/03/how-to-backup-your-new-blogger-template.html" target="_blank">back up your template</a> before modifying it. Look for the following line:</p>
<p><textarea rows="1" cols="53">&lt;title&gt;&lt;/title&gt;</textarea></p>
<p>Once you&#8217;ve found this line, add the following code one line above it:</p>
<p><textarea rows="2" cols="53">&lt;link rel="shortcut icon" href="Your .ico file's URL" /&gt;</textarea></p>
<p>Save your template and you&#8217;re done. Thanks to <a href="http://tips-for-new-bloggers.blogspot.com/2007/02/adding-favicon-icon-to-blogger-url.html" target="_blank">Tips for New Bloggers</a> and <a href="http://techmake.blogspot.com/2007/06/just-launched-new-favicon-today.html" target="_blank">My Tech Life</a> for information on how to do this.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2007/07/30/new-image-header-favicon/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Blogger, Feedburner and Sitemaps</title>
		<link>http://gangles.ca/2007/07/17/blogger-feedburner-and-sitemaps/</link>
		<comments>http://gangles.ca/2007/07/17/blogger-feedburner-and-sitemaps/#comments</comments>
		<pubDate>Tue, 17 Jul 2007 05:53:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Blogger]]></category>
		<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Feedburner]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[Sitemap]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=17</guid>
		<description><![CDATA[I had announced last Friday that I was being an eager beaver and taking advantage of the improved Feedburner integration for Blogger. However, like all early adapters, I&#8217;ve had been unfortunately burdened with the unresolved issues of the new technology. Specifically: Once enabled, Google will redirect your Atom feed subscribers to Feedburner. However, Blogger also [...]]]></description>
			<content:encoded><![CDATA[<p><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px" src="http://img.photobucket.com/albums/v410/Tolbi/feedburner.gif" alt="Feedburner Logo">I had announced <a href="http://gangles.ca/2007/07/13/minor-update-feedburner/">last Friday</a> that I was being an eager beaver and taking advantage of the <a href="http://blogs.feedburner.com/feedburner/archives/2007/07/feedburner_integration_for_blo.php" target="_blank">improved Feedburner integration for Blogger</a>. However, like all early adapters, I&#8217;ve had been unfortunately burdened with the unresolved issues of the new technology. Specifically:</p>
<ul>
<li>Once enabled, Google will redirect your Atom feed subscribers to Feedburner. However, Blogger also publishes a second feed (in RSS format) which for some reason it does not redirect. Feedburner won&#8217;t be able to collect statistics about people who subscribe to the non-redirected feed, making your efforts fairly moot.</li>
<li>Bloggers who use their Atom feed as a sitemap for Google will receive errors due to their Feedburner feed being in a different domain than the rest of their blog.</li>
</ul>
<p>Using a bit of creativity, however, I do believe I&#8217;ve found a suitable workaround that should allow motivated Blogger users to integrate Feedburner and Google sitemap without these problems.</p>
<hr width="80%" size="3" align=CENTER />
<p><b>UPDATE: Easier Method</b><br />
Commenter <a href="http://v-kostin.blogspot.com/" target="_blank">Lamer</a> came up with an even simpler way to integrate both feedburner and Google sitemaps. Turn on the Feedburner redirection (Dashboard > Settings > Site Feed) and then use <b>http://YOURBLOG.blogspot.com/rss.xml?orderby=updated</b> as a sitemap (for whatever reason Blogger does not redirect this XML file). Simple and efficient, thanks <a href="http://v-kostin.blogspot.com/" target="_blank">Lamer</a>! The rest of this post goes on to describe the old, more complicated method, which may be useful if you want to modify your autodiscovery tags.</p>
<hr width="80%" size="3" align=CENTER />
<p><small>Note: I do not recommend the trick explained below if you already have a sizeable number of subscribers to your Atom feed that you want to redirect to your Feedburner feed, since they will no longer be redirected afterwards. Use the updated trick above instead.</small></p>
<p><b>Preparation:</b><br />
Set up a <a href="http://www.feedburner.com/" target="_blank">Feedburner account</a>. When it asks you for your Feed URL, type in &#8220;<i>YOURBLOG</i>.blogspot.com/atom.xml&#8221;.</p>
<p>Next, under the Blogger dashboard, go to Settings &gt; Site Feed and clear the &#8220;Post Feed Redirect URL&#8221; field. This will stop Blogger from redirecting people who try to access your Atom feed.</p>
<p><b>Step One: Modify Your Autodiscovery Tags:</b><br />
To credit my sources properly, I learned how to do this from a <a href="http://forums.feedburner.com/viewtopic.php?t=3377" target="_blank">post by matt</a> in the <a href="http://forums.feedburner.com/index.php" target="_blank">Feedburner forums</a> that has since had its contents removed.</p>
<p>With your blog open, <a href="http://support.microsoft.com/kb/176222" target="_blank">view the html source</a> of your page. Look for a block of code similar to the following:</p>
<p><textarea rows="4" cols="53">&lt;link rel="alternate" type="application/atom+xml" title="YOURBLOG &#8211; Atom" href="http://YOURBLOG.blogspot.com/feeds/posts/default" /&gt;
&lt;link rel="alternate" type="application/rss+xml" title="YOURBLOG &#8211; RSS" href="http://YOURBLOG.blogspot.com/feeds/posts/default?alt=rss" /&gt;
&lt;link rel="service.post" type="application/atom+xml" title="YOURBLOG &#8211; Atom" href="http://www.blogger.com/feeds/9501038560806028465/posts/default" /&gt;
&lt;link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www.blogger.com/rsd.g?blogID=9501038560806028465&#8243; /&gt;</textarea></p>
<p>Copy the similar looking block from your blog&#8217;s html source code and paste it in a temporary .txt document. You may now close your Blog&#8217;s html source.</p>
<p>We&#8217;re now going to modify what you just pasted into the .txt document. Replace these two lines:</p>
<p><textarea rows="4" cols="53">&lt;link rel="alternate" type="application/atom+xml" title="YOURBLOG &#8211; Atom" href="http://YOURBLOG.blogspot.com/feeds/posts/default" /&gt;
&lt;link rel="alternate" type="application/rss+xml" title="YOURBLOG &#8211; RSS" href="http://YOURBLOG.blogspot.com/feeds/posts/default?alt=rss" /&gt;</textarea>
<p>with the following:</p>
<p><textarea rows="3" cols="53">&lt;link rel="alternate" type="application/atom+xml" title="YOURBLOG &#8211; Feedburner" href="http://feeds.feedburner.com/YOURFEEDNAME" /&gt;</textarea></p>
<p>This next step will involve modifying your Blogger template. I <i>strongly</i> urge you to <a href="http://dummies-guide-to-google-blogger.blogspot.com/2007/03/how-to-backup-your-new-blogger-template.html" target="_blank">backup your Blogger template</a> beforehand in case you make a mistake. From the Blogger dashboard, go to Template &gt; Edit html. Look for the following line in your template&#8217;s html:</p>
<p><textarea rows="1" cols="53">&lt;b:data='blog' name='all-head-content'&gt;</textarea></p>
<p>Delete this line and replace it with the contents of the .txt file you saved earlier, then click &#8220;Save Template&#8221;. You have now successfully modified the autodiscovery tags, and browsers that auto-detect RSS feeds will now be directed to your Feedburner feed only.</p>
<p><b>Step Two: Use Your Atom Feed as a Sitemap</b><br />
If you have Google&#8217;d your own site, you may have noticed that not all of your individual Blog posts have been indexed. One way to help this along is to provide the <a href="http://www.googleguide.com/google_works.html" target="_blank">Google webcrawler</a> with a sitemap. A sitemap is an XML document that tells the crawler how to properly index all the pages on your site. As Blogger users, we cannot write our own sitemap file, but we can use our Atom Feed as a sitemap.</p>
<p>To begin, sign into <a href="http://www.google.com/webmasters/sitemaps/" target="_blank">Google Webmaster Tools</a> using the same Google account that you use for Blogger. Follow the on screen instructions to verify your Blog. Once you&#8217;ve finished that, click on the &#8220;Sitemaps&#8221; tab, then the &#8220;Add Sitemap&#8221; button. Select &#8220;Add General Web Sitemap&#8221; from the pulldown menu, type in &#8220;atom.xml&#8221; for Step 3 and click &#8220;Add Sitemap&#8221;. Google will now be able to use this information to index your site properly.</p>
<p><b>Current Issues</b><br />
<strike>I so far have not been able to figure out is how to redirect the &#8220;Subscribe to Posts&#8221; link at the bottom of the page to Feedburner.</strike><br />
<b>UPDATE:</b> Fellow blogger <a href="http://blogdejuls.blogspot.com/" target="_blank" title="El Super Blog de Juls">Juls</a> came up with this excellent way to redirect your main page Feed footer while preserving your comment feed! Locate this block of code:</p>
<p><textarea rows="8" cols="53">&lt;b:includable id='feedLinksBody' var='links'&gt;
&lt;div class='feed-links'&gt;
&lt;data:feedLinksMsg/&gt;
&lt;b:loop values='data:links' var='f'&gt;
&lt;a class='feed-link' expr:href='data:f.url' expr:type='data:f.mimeType' target='_blank'&gt;&lt;data:f.name/&gt; (&lt;data:f.feedType/&gt;)&lt;/a&gt;
&lt;/b:loop&gt;
&lt;/div&gt;
&lt;/b:includable&gt;</textarea></p>
<p>And replace it with:</p>
<p><textarea rows="8" cols="53">&lt;b:includable id='feedLinksBody' var='links'&gt;
&lt;b:if cond='data:blog.pageType == "item"'&gt;
&lt;div class='feed-links'&gt;
&lt;data:feedLinksMsg/&gt;
&lt;b:loop values='data:links' var='f'&gt;
&lt;a class='feed-link' expr:href='data:f.url' expr:type='data:f.mimeType' target='_blank'&gt;&lt;data:f.name/&gt; (&lt;data:f.feedType/&gt;)&lt;/a&gt;
&lt;/b:loop&gt;
&lt;/div&gt;
&lt;b:else/&gt;
&lt;div class='feed-links'&gt;
&lt;data:feedLinksMsg/&gt;
&lt;b:loop values='data:links' var='f'&gt;
&lt;a href='http://feeds.feedburner.com/YOURBLOG/' target='_blank'&gt;Posts (Feedburner)&lt;/a&gt;
&lt;/b:loop&gt;
&lt;/div&gt;
&lt;/b:if&gt;
&lt;/b:includable&gt;
</textarea></p>
<p><b>Conclusion</b><br />
This is by no means a perfect trick, but I think it&#8217;s a decent way to work around the current Feedburner integration problems and still make use of Feedburner and a Google Sitemap. If you have suggestions, problems or ideas, please feel free to leave a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2007/07/17/blogger-feedburner-and-sitemaps/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>iTunes Album List in Perl</title>
		<link>http://gangles.ca/2007/07/16/itunes-album-list-in-perl/</link>
		<comments>http://gangles.ca/2007/07/16/itunes-album-list-in-perl/#comments</comments>
		<pubDate>Mon, 16 Jul 2007 04:59:00 +0000</pubDate>
		<dc:creator>Matthew Gallant</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://gangles.ca/?p=16</guid>
		<description><![CDATA[This winter I took a course called System Software. In it, we learned a neat programming language called Perl. Perl was handy for that class because it happens to be very good at parsing text, and we used it to write a simple compiler. Being the pragmatic kind of person that I am, I immediately [...]]]></description>
			<content:encoded><![CDATA[<div align="justify"><img style="float:right;margin:0 0 10px 10px;" alt="Perl 6 for Wankers by Jakov Grafki" src="http://img.photobucket.com/albums/v410/Tolbi/perl_for_wankers2.gif" border="0">
<p>This winter I took a course called System Software. In it, we learned a neat programming language called Perl. Perl was handy for that class because it happens to be very good at parsing text, and we used it to write a simple compiler. Being the pragmatic kind of person that I am, I immediately began to think of <a href="http://xkcd.com/c208.html" target="_blank">ways to use this new found skill</a>, and the opportunity arose in a rather roundabout way.</p>
<p>You see, I have what I&#8217;d describe as a fairly large collection of music (roughly 18.6 days worth according to iTunes). This sometimes causes problems when I&#8217;m out shopping for CDs and I can&#8217;t quite recall which ones I already own. iTunes is able to export a list of your music as an XML document, but you end up with a large unwieldy file with roughly 15 lines per <i>song</i>.</p>
<p>The solution: create a small Perl script to go through every line of this gigantic XML document and create a list of albums matched with artists. The result of my code monkeying is in the box below. Is the script terribly well written? Not especially. Did my album problem really need solving that badly? Not particularly. Was this a good excuse to play around with Perl a bit? Damn right. Enjoy.</p>
</div>
<p><textarea rows="10" cols="53">#!/usr/bin/perl
#===========================================
#Script written by Matthew Gallant
#===========================================

$filename = $ARGV[0];
print("Extracting album list from $filename&#8230; ");
open(READ, "$filename") ||
die("\nError: $filename not found or cannot be opened.");
my %albums;
my $artist;
while(my $line = &lt;READ&gt;)
{
  if($line =~ m/&lt;key&gt;Artist&lt;\/key&amp;gt/)
  {
    chomp($line);
    $line =~ s/^\s+&lt;key&gt;Artist&lt;\/key&amp;gt&lt;string&gt;//;
    $line =~ s/&#38;/&amp;/;
    $line =~ s/&lt;\/string&gt;//;
    if($line =~ m/^The /)
    {
      $line =~ s/^The //;
      $line = $line . ", The";
    }
    $artist = $line;
  }
  elsif($line =~ m/&lt;key&gt;Album&lt;\/key&gt;/)
  {
    chomp($line);
    $line =~ s/^\s+&lt;key&gt;Album&lt;\/key&gt;&lt;string&gt;//;
    $line =~ s/&#38;/&amp;/;
    $line =~ s/ \(Disc \d\)//;
    $line =~ s/&lt;\/string&gt;//;
    if($line ne "N/A")
    {
      my %artistalbums;
      if(exists $albums{$artist})
      {
        my $albumsref = $albums{$artist};
        %artistalbums = %$albumsref;
      }
      $artistalbums{$line} = "";
      $albums{$artist} = \%artistalbums;
    }
  }
}
close(READ);
print("Complete.\n");
print("Writing album list to Album List.txt&#8230; ");
open(WRITE, "&gt;Album List.txt") ||
die("\nError: Album List.txt cannot be written to.\n");
for my $key (sort(keys %albums))
{
  $tempkey = $key;
  if($tempkey =~ m/, The$/)
  {
    $tempkey =~ s/, The//;
    $tempkey = "The " . $tempkey;
  }
  printf WRITE ("%-40.39s", $tempkey);
  my $valuesref = $albums{$key};
  my %values = %$valuesref;
  foreach my $album (sort(keys %values))
  {
    print WRITE ("$album\n\t\t\t\t\t");
  }
  print WRITE ("\n");
}
close(WRITE);
print("Complete.");
exit(0);</textarea></p>
<div align="justify">
<p>The result should look something like <a href="http://img.photobucket.com/albums/v410/Tolbi/albumlist.jpg" target="_blank">this</a>. If you&#8217;d like to try this program out, but don&#8217;t have the experience to run it in the command prompt, here&#8217;s a summarized guide with some helpful links:
<ul>
<li>If you&#8217;re running Windows, you&#8217;ll need to download a Perl interpreter such as <a href="http://aspn.activestate.com/ASPN/Downloads/ActivePerl/" target="_blank">ActivePerl</a>. If you&#8217;re running Linux, it&#8217;s built in.</li>
<li>Open up a simple text editor (NodePad, WordPad, TextPad), then save the code from the above box as &#8220;albumlister.pl&#8221;. Open iTunes, go to File &gt; Export Library and save it as &#8220;library.xml&#8221; in the same directory as the Perl code.</li>
<li>Open up the command prompt and switch over to the directory where you saved the Perl code (<a href="http://www.pcstats.com/articleview.cfm?articleid=1723&amp;page=3" target="_blank">helpful guide here</a>).</li>
<li>Type in the following to run the program: &#8220;<font face="courier new">perl albumlister.pl library.xml</font>&#8220;. Your album list will be stored in a file called &#8220;Album List.txt&#8221; in the same directory.</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://gangles.ca/2007/07/16/itunes-album-list-in-perl/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

