<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Prashanth Ellina</title><link href="http://blog.prashanthellina.com/" rel="alternate"></link><link href="http://blog.prashanthellina.com/feeds/atom.xml" rel="self"></link><id>http://blog.prashanthellina.com/</id><updated>2017-07-02T11:58:00-07:00</updated><entry><title>Tutorials TODO</title><link href="http://blog.prashanthellina.com/tutorials-todo.html" rel="alternate"></link><updated>2017-07-02T11:58:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2017-07-02:tutorials-todo.html</id><summary type="html">&lt;h1&gt;Basics&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;How does a browser work?&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;,&amp;nbsp;Server&lt;/li&gt;
&lt;li&gt;Web&amp;nbsp;Server&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;TCP&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Telnet&lt;/li&gt;
&lt;li&gt;Ping&lt;/li&gt;
&lt;li&gt;Tracepath /&amp;nbsp;Traceroute&lt;/li&gt;
&lt;li&gt;Structure of an &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;address&lt;/li&gt;
&lt;li&gt;netstat&lt;/li&gt;
&lt;/ul&gt;</summary><category term="howto"></category><category term="learning"></category><category term="tutorial"></category></entry><entry><title>All your aliases are belong to you</title><link href="http://blog.prashanthellina.com/all-your-aliases-are-belong-to-you.html" rel="alternate"></link><updated>2009-08-28T08:05:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-08-28:all-your-aliases-are-belong-to-you.html</id><summary type="html">&lt;p&gt;I like setting up shortcuts to frequently used commands whether I used
Windows or Linux. I use the terminal often and create shortcuts to
frequently used commands using &amp;#8220;alias&amp;#8221; feature of &lt;span class="caps"&gt;BASH&lt;/span&gt;. This has saved
me considerable time in the past. However, I recently felt that if I
could have a helper tool to monitor my usage of commands and
automatically suggest candidates for aliasing, that would be useful. The
output of that is&amp;nbsp;Aliaser.&lt;/p&gt;
&lt;p&gt;Aliaser works by monitoring your bash history. It analyses command
frequency and suggests candidates for aliasing. It manages aliases so
created. The feature I like most in Aliaser is that it reminds you to
use the aliases you created by showing tips on opening a new terminal&amp;nbsp;session.&lt;/p&gt;
&lt;p&gt;Download Aliaser from &lt;a href="http://aliaser.googlecode.com"&gt;http://aliaser.googlecode.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://aliaser.googlecode.com"&gt;
&lt;img alt="" src="http://aliaser.googlecode.com/files/aliaser_tips.png" /&gt;&lt;/a&gt;&lt;/p&gt;</summary><category term="bash"></category><category term="linux"></category><category term="productivity"></category><category term="python"></category><category term="script"></category></entry><entry><title>Query Wikipedia from your terminal</title><link href="http://blog.prashanthellina.com/query-wikipedia-from-your-terminal.html" rel="alternate"></link><updated>2009-08-23T10:52:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-08-23:query-wikipedia-from-your-terminal.html</id><summary type="html">&lt;p&gt;I refer Wikipedia frequently. I use this &lt;span class="caps"&gt;BASH&lt;/span&gt; function to help me do
that from the terminal. For explanation of how this works head over
&lt;a href="http://www.commandlinefu.com/commands/view/2829/query-wikipedia-via-console-over-dns"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;BASH&lt;/span&gt;&amp;nbsp;function&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# wiki&lt;/span&gt;
&lt;span class="c"&gt;# eg: wiki India&lt;/span&gt;
&lt;span class="c"&gt;#     wiki Apple_Inc&lt;/span&gt;
&lt;span class="c"&gt;#     wiki Anglo_Saxon&lt;/span&gt;
wiki&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    dig +short txt &lt;span class="nv"&gt;$1&lt;/span&gt;.wp.dg.cx
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Example&amp;nbsp;usage&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;prashanth@prashanth-desktop:~&lt;span class="nv"&gt;$ &lt;/span&gt;wiki India
&lt;span class="s2"&gt;&amp;quot;India, officially the Republic of India ( &amp;#39;\; see also other Indian languages), is a country in South Asia.&lt;/span&gt;
&lt;span class="s2"&gt;It is the seventh-largest country by geographical area, the second-most populous country, and the most&lt;/span&gt;
&lt;span class="s2"&gt;populous democracy in the world. Bounded by t&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;he Indian Ocean on the south, the Arabian Sea on&lt;/span&gt;
&lt;span class="s2"&gt;the west, and the Bay of Bengal on the east, India has a coastline of ... http://a.vu/w:India&amp;quot;&lt;/span&gt;

prashanth@prashanth-desktop:~&lt;span class="nv"&gt;$ &lt;/span&gt;wiki Anglo_Saxon
&lt;span class="s2"&gt;&amp;quot;Anglo-Saxons (or Anglo-Saxon) is the term usually used to describe the invading tribes in the south&lt;/span&gt;
&lt;span class="s2"&gt;and east of Great Britain starting from the early 5th century AD, and their creation of the English&lt;/span&gt;
&lt;span class="s2"&gt;nation, lasting until the Norman conquest of 1066. The &amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Benedictine monk, Bede, identified&lt;/span&gt;
&lt;span class="s2"&gt;them as the descendants of three Germanic tribes: http://a.vu/w:Anglo-Saxons&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary><category term="bash"></category><category term="code"></category><category term="function"></category><category term="productivity"></category><category term="terminal"></category><category term="wikipedia"></category></entry><entry><title>Command-line language translation</title><link href="http://blog.prashanthellina.com/command-line-language-translation.html" rel="alternate"></link><updated>2009-08-18T19:33:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-08-18:command-line-language-translation.html</id><summary type="html">&lt;p&gt;Here is a simple utility created using Python for translating text from
various languages into English. It uses the Google &lt;span class="caps"&gt;AJAX&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; to do&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;prashanth@prashanth-desktop:~&lt;span class="nv"&gt;$ &lt;/span&gt;translate bonjour
hello
prashanth@prashanth-desktop:~&lt;span class="nv"&gt;$ &lt;/span&gt;translate guten morgen
Good morning
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;Translates text into english using Google Translate.&lt;/span&gt;
&lt;span class="sd"&gt;Usage: python translate.py&lt;/span&gt;
&lt;span class="sd"&gt;        (or)&lt;/span&gt;
&lt;span class="sd"&gt;       echo  | python translate.py&lt;/span&gt;

&lt;span class="sd"&gt;For convenience, make a symlink to this file from /usr/bin/translate.&lt;/span&gt;
&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="c"&gt;# derived from : http://code.google.com/p/py-gtranslate/source/browse/trunk/gtrans.py&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urllib2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;simplejson&lt;/span&gt; &lt;span class="kn"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;FROM_LANGUAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;TO_LANGUAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;http://ajax.googleapis.com/ajax/services/language/translate&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;langpair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_language&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;v&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;langpair&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;langpair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;q&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quote_plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;amp;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()]))&lt;/span&gt;

    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;responseData&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;translatedText&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FROM_LANGUAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TO_LANGUAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FROM_LANGUAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TO_LANGUAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;[&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;]&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary><category term="google"></category><category term="language"></category><category term="python"></category><category term="script"></category><category term="tool"></category><category term="translation"></category></entry><entry><title>On setting up USB RAID</title><link href="http://blog.prashanthellina.com/on-setting-up-usb-raid.html" rel="alternate"></link><updated>2009-08-07T17:27:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-08-07:on-setting-up-usb-raid.html</id><summary type="html">&lt;p&gt;I bought two Dane-Elec &lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;USB&lt;/span&gt; drives recently. Flash memory (as opposed
to Hard disk storage) has faster &amp;#8220;seek&amp;#8221; capability. This is inherent in
the design as flash memory is solid state whereas hard disks are
electro-mechanical with a &amp;#8220;head&amp;#8221; that needs to be moved around using a
&amp;#8220;drive&amp;#8221; mechanism. Since seek times are better on flash drives, they are
faster when you are reading or writing a lot of small&amp;nbsp;files.&lt;/p&gt;
&lt;p&gt;However flash drives do not have sustained data transfer rates that hard
disks have (i.e throughput). My thought process what that the throughput
can be made up by slapping together two or more &lt;span class="caps"&gt;USB&lt;/span&gt; drives and applying
software &lt;span class="caps"&gt;RAID&lt;/span&gt; 0 over them. Below are some performance results and they
look&amp;nbsp;encouraging.&lt;/p&gt;
&lt;p&gt;Note that the timings are in&amp;nbsp;seconds.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Single &lt;span class="caps"&gt;8GB&lt;/span&gt; Dane-Elec &lt;span class="caps"&gt;USB&lt;/span&gt; drive&lt;/strong&gt;
131.11 for &lt;span class="caps"&gt;683MB&lt;/span&gt; (write)
44.62 for &lt;span class="caps"&gt;683MB&lt;/span&gt;&amp;nbsp;(read)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Single &lt;span class="caps"&gt;2GB&lt;/span&gt; Transcend &lt;span class="caps"&gt;USB&lt;/span&gt; drive&lt;/strong&gt;
204.50 for &lt;span class="caps"&gt;683MB&lt;/span&gt; (write)
63.26 for &lt;span class="caps"&gt;683MB&lt;/span&gt;&amp;nbsp;(read)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Single &lt;span class="caps"&gt;8GB&lt;/span&gt; Sandisk drive&lt;/strong&gt;
197.61 for &lt;span class="caps"&gt;683MB&lt;/span&gt; (write)
29.73 for &lt;span class="caps"&gt;683MB&lt;/span&gt;&amp;nbsp;(read)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAID0&lt;/span&gt; (two Dane-Elec &lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;USB&lt;/span&gt; drives)&lt;/strong&gt;
61.177 for &lt;span class="caps"&gt;683MB&lt;/span&gt; (write)
17.9 for &lt;span class="caps"&gt;683MB&lt;/span&gt;&amp;nbsp;(read)&lt;/p&gt;
&lt;p&gt;I created a test file with 683 &lt;span class="caps"&gt;MB&lt;/span&gt; of data by funnelling /dev/urandom
into it and then copied it to the &lt;span class="caps"&gt;USB&lt;/span&gt; drive(s) to measure write
performance. Then I unmounted the &lt;span class="caps"&gt;USB&lt;/span&gt; drive(s) to make sure the buffer
cache is emptied. On remounting I measured read performance by copying
the test file back to the harddisk. The hard disk used was a Seagate
Barracuda &lt;span class="caps"&gt;320GB&lt;/span&gt;&amp;nbsp;(7200rpm).&lt;/p&gt;
&lt;p&gt;If four &lt;span class="caps"&gt;USB&lt;/span&gt; drives (say Sandisk &lt;span class="caps"&gt;8GB&lt;/span&gt;) can be &lt;span class="caps"&gt;RAID&lt;/span&gt;&amp;#8217;ed together on level 0
we would have a cheap &lt;span class="caps"&gt;SSD&lt;/span&gt;. One thing that prevents me from trying this
out is the question of reliability. I have not used this setup long
enough or stressed it hard enough to be comfortable using this for
normal&amp;nbsp;use.&lt;/p&gt;
&lt;p&gt;To rig something like this yourself, read this
&lt;a href="http://linuxgazette.net/151/weiner.html"&gt;article&lt;/a&gt;.&lt;/p&gt;</summary></entry><entry><title>Extracting relevant text from HTML pages</title><link href="http://blog.prashanthellina.com/extracting-relevant-text-from-html-pages.html" rel="alternate"></link><updated>2009-07-27T16:46:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-07-27:extracting-relevant-text-from-html-pages.html</id><summary type="html">&lt;p&gt;Some time back I had done some work on &lt;a href="http://blog.prashanthellina.com/2007/12/21/topic-extraction-using-wikipedia-data/"&gt;extracting
topics&lt;/a&gt;
from an arbitrary piece of text using Wikipedia data. Recently I thought
of a concept to put that algorithm to work. As a part of this project, I
need to extract &lt;strong&gt;relevant&lt;/strong&gt; text from an arbitrary &lt;span class="caps"&gt;HTML&lt;/span&gt; page. By
relevant I mean the &amp;#8220;meat&amp;#8221; of the page devoid of navigation links and&amp;nbsp;side-content.&lt;/p&gt;
&lt;p&gt;This algorithm has the following &lt;strong&gt;steps&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;make doc from html data (clean&amp;nbsp;html)&lt;/li&gt;
&lt;li&gt;identify content nodes (nodes having substantial&amp;nbsp;content)&lt;/li&gt;
&lt;li&gt;prune xml tree to remove irrelevant&amp;nbsp;nodes&lt;/li&gt;
&lt;li&gt;get the most linked node from pruned tree (subtree contains relevant&amp;nbsp;text)&lt;/li&gt;
&lt;li&gt;make the dot&amp;nbsp;graph&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;ve pasted the relevant python module below for easy reading. However,
if you want to download the code and hack it, you can get all the files
from &lt;a href="http://code.prashanthellina.com/code/content_extraction"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code&amp;nbsp;files&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;content_extract.py - actual work gets done here (file pasted&amp;nbsp;below)&lt;/li&gt;
&lt;li&gt;cextract.py - cgi front-end which fetched url content and feeds to
    above&amp;nbsp;script.&lt;/li&gt;
&lt;li&gt;cextract_config.py - cgi script configuration file. You have to
    adjust this to your&amp;nbsp;environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Try it right here and right&amp;nbsp;now&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;url:   &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some&amp;nbsp;samples&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="{filename}cextract_data/510fbe51d89334aecb70d9b1d1635711.html"&gt;http://news.bbc.co.uk/sport2/hi/motorsport/formula_one/8169436.stm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;lt;{filename}/cextract_data/640ca0b7c6e818b2b1bf952a206a6388.html&amp;gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="{filename}cextract_data/8408efd51b4f1f6b91650d4ea3ce8924.html"&gt;http://www.telegraph.co.uk/news/worldnews/europe/france/5913494/Nicolas-Sarkozy-to-slow-down-after-collapsing-while-jogging.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please let me know if you find cases for which the algorithm does not
work. Even better would be to download the code and hack it up and post
back. I am eager to see what you can come up&amp;nbsp;with.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cStringIO&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt; &lt;span class="c"&gt;#http://codespeak.net/lxml/&lt;/span&gt;

&lt;span class="n"&gt;IGNORABLE_TAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;MIN_TEXT_LEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Given a XML node, extract all the text it contains.&lt;/span&gt;
&lt;span class="sd"&gt;    (does not recurse into children)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cnode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getchildren&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cnode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cnode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_xml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Convert the sub-tree from node downwards&lt;/span&gt;
&lt;span class="sd"&gt;    into string XML representation.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Construct XML tree datastructure from xml string representation.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTMLParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_content_nodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Identify nodes in the XML document that&lt;/span&gt;
&lt;span class="sd"&gt;    have substantial text.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;//*&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;IGNORABLE_TAGS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MIN_TEXT_LEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_pruned_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_nodes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Prune the whole XML tree by remnoving nodes&lt;/span&gt;
&lt;span class="sd"&gt;    other than content nodes and their ancestors.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content_nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;

        &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getparent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;anode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iterancestors&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getparent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anode&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_inlink_counts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Given the inter-node links, find out which&lt;/span&gt;
&lt;span class="sd"&gt;    node has maximum number of links coming into it.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;from_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteritems&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;to_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;counts&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_most_linked_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Identify the node which is most linked.&lt;/span&gt;
&lt;span class="sd"&gt;    (i,e) has most number of inlinks.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;inlink_counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_inlink_counts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;mcount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;([(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;inlink_counts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteritems&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_dot_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chosen_node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Construct the dot format graph representation&lt;/span&gt;
&lt;span class="sd"&gt;    so that graphviz can render the tree for visualization.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;

    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;digraph G {&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteritems&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

        &lt;span class="n"&gt;tlen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tlen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;)&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tlen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;chosen_node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;style=filled color=lightblue&amp;#39;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;

        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; [label=&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;];&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;fid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteritems&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;}&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c"&gt;# make doc from html data (cleans html)&lt;/span&gt;
    &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c"&gt;# identify content nodes&lt;/span&gt;
    &lt;span class="n"&gt;content_nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_content_nodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# prune xml tree to remove irrelevant nodes&lt;/span&gt;
    &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_pruned_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_nodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# get the most linked node from pruned tree&lt;/span&gt;
    &lt;span class="n"&gt;mnode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_most_linked_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# make the dot graph&lt;/span&gt;
    &lt;span class="n"&gt;make_dot_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mnode&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c"&gt;#Eg: wget &amp;quot;http://blog.prashanthellina.com&amp;quot; -O - | python thisscript.py | dot -Tpng -o /tmp/test.png ; eog /tmp/test.png&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary></entry><entry><title>Clustering Data using Python</title><link href="http://blog.prashanthellina.com/clustering-data-using-python.html" rel="alternate"></link><updated>2009-07-25T09:24:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-07-25:clustering-data-using-python.html</id><summary type="html">&lt;p&gt;As a part of a project I am working on, I had to cluster urls on a page.
After some light googling I found,
&lt;a href="http://python-cluster.sourceforge.net/"&gt;python-cluster&lt;/a&gt;. You can find
below a simple python script to illustrate the usage of python-cluster&amp;nbsp;library.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pprint&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;difflib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SequenceMatcher&lt;/span&gt;

&lt;span class="c"&gt;# http://python-cluster.sourceforge.net/&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cluster&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HierarchicalClustering&lt;/span&gt;

&lt;span class="c"&gt;# input urls to be clustered&lt;/span&gt;
&lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814385&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;#articles&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814335&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://yro.slashdot.org/~drDugan/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://web.sourceforge.com/privacy.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28815123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//slashdot.org/~Darkness404&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//radio.slashdot.org&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;op=Reply&amp;amp;threshold=1&amp;amp;commentsort=0&amp;amp;mode=thread&amp;amp;pid=28814429&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;op=Reply&amp;amp;threshold=1&amp;amp;commentsort=0&amp;amp;mode=thread&amp;amp;pid=28814457&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//slashdot.org/article.pl?sid=09/07/24/1545238&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//slashdot.org/comments.pl?sid=09/07/24/1545238&amp;amp;cid=28810581&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28815269&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814657&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://web.sourceforge.com/terms.php&amp;#39;&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/search&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814581&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://xkcd.com/612/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://web.sourceforge.com/advertising&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;op=Reply&amp;amp;threshold=1&amp;amp;commentsort=0&amp;amp;mode=thread&amp;amp;pid=28814785&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;# distance function compares two urls and finds the distance&lt;/span&gt;
&lt;span class="c"&gt;# uses SequenceMatcher from python standard module difflib&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ratio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SequenceMatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ratio&lt;/span&gt;

&lt;span class="c"&gt;# Perform clustering&lt;/span&gt;
&lt;span class="n"&gt;hc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HierarchicalClustering&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;clusters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getlevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clusters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;#articles&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://xkcd.com/612/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://web.sourceforge.com/privacy.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://web.sourceforge.com/advertising&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://web.sourceforge.com/terms.phphttp://slashdot.org//it.slashdot.org/search&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://yro.slashdot.org/~drDugan/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://slashdot.org//slashdot.org/~Darkness404&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://slashdot.org//radio.slashdot.org&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;op=Reply&amp;amp;threshold=1&amp;amp;commentsort=0&amp;amp;mode=thread&amp;amp;pid=28814785&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;op=Reply&amp;amp;threshold=1&amp;amp;commentsort=0&amp;amp;mode=thread&amp;amp;pid=28814429&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;op=Reply&amp;amp;threshold=1&amp;amp;commentsort=0&amp;amp;mode=thread&amp;amp;pid=28814457&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://slashdot.org//slashdot.org/article.pl?sid=09/07/24/1545238&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//slashdot.org/comments.pl?sid=09/07/24/1545238&amp;amp;cid=28810581&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28815123&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28815269&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814385&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814335&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814657&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;&amp;#39;http://slashdot.org//it.slashdot.org/comments.pl?sid=1314601&amp;amp;cid=28814581&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary><category term="clustering"></category><category term="python"></category><category term="script"></category></entry><entry><title>XMonad: A Window Manager for “real” people :)</title><link href="http://blog.prashanthellina.com/xmonad.html" rel="alternate"></link><updated>2009-04-26T21:34:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-04-26:xmonad.html</id><summary type="html">&lt;p&gt;&lt;img alt="XMonad in Gnome" src="http://blog.prashanthellina.com/images/xmonad_1.png" /&gt; I
have been a happy Gnome user for many years now and only recently
started thinking about switching to &lt;span class="caps"&gt;KDE&lt;/span&gt; 4.2 when Ubuntu 9.04 (Jaunty
Jackalope) comes out. However, it so happened that I bought two new
widescreen monitors and setup a dual-monitor environment. This is when I
started realizing the Gnome was clumsy at best when it comes to managing
windows across&amp;nbsp;monitors.&lt;/p&gt;
&lt;p&gt;The reason I bought multiple monitors is to maximize my work area so I
do not have to keep switching between overlapping windows. Gnome it
seems is ill-suited to effectively and effortlessly managing&amp;nbsp;space.&lt;/p&gt;
&lt;p&gt;When I maximize a window on a widescreen monitor, the window takes up
the entire space on the screen. Although this is the expected behavior,
I could not rest looking at the huge amount of space being wasted. What
I would like better is having two windows occupying the height of the
screen but sitting right next to each other (i.e. tiled). This way less
space is wasted and you get to see both windows at the same time. I
could do this in gnome, but with considerable effort, as closing a
window and re-opening another requires another round of frantic window&amp;nbsp;arrangement.&lt;/p&gt;
&lt;p&gt;In comes a tiling window manager &amp;#8230; Tiling window managers do not allow
overlapping windows (except for dialogs). They are a good solution when
you need to tile windows to occupy all available screen space. Also,
most tiling window managers emphasize keyboard control over mouse
control. If you are productivity freak you will love the keyboard
shortcuts that do away with a painful context switch required in
navigating with the&amp;nbsp;mouse.&lt;/p&gt;
&lt;p&gt;There are many Tiling Window Managers out there. Rat Poison, Stump &lt;span class="caps"&gt;WM&lt;/span&gt;,
Ion, dwm, wmii and XMonad are a few. I chose XMonad because I was able
to figure how to integrate XMonad into the Gnome desktop environment.
Most of these window managers don&amp;#8217;t play well with Gnome. I use a number
of Gnome apps and I would hate to not be able to use&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;Okay, here is how you &lt;strong&gt;Install XMonad on Ubuntu to work within Gnome&lt;/strong&gt;&amp;nbsp;&amp;#8230;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mkdir ~/.xmonad
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.xmonad
vim xmonad.hs
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then paste the following into the xmonad.hs file and save&amp;nbsp;it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;XMonad&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;XMonad.Config.Gnome&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;XMonad.ManageHook&lt;/span&gt;

&lt;span class="nf"&gt;myManageHook&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;ManageHook&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;myManageHook&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;  &lt;span class="o"&gt;=?&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Do&amp;quot;&lt;/span&gt;   &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;doIgnore&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmonad&lt;/span&gt; &lt;span class="n"&gt;gnomeConfig&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;manageHook&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manageHook&lt;/span&gt; &lt;span class="n"&gt;gnomeConfig&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;composeAll&lt;/span&gt; &lt;span class="n"&gt;myManageHook&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install xmonad libghc6-xmonad-dev
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note that libghc6-xmonad-dev is a &lt;span class="caps"&gt;200MB&lt;/span&gt;&amp;nbsp;dependency!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;vim ~/.gnomerc
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Add this line .gnomerc file and&amp;nbsp;save.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;WINDOW_MANAGER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xmonad
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The installation is done. Now to experience your new Window Manager, log
out and then log back in. You will see your usual desktop with Gnome&amp;nbsp;panels.&lt;/p&gt;
&lt;p&gt;To learn more about XMonad and how to use it, follow these&amp;nbsp;links:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ubuntu-snippets.blogspot.com/2008/08/xmonad-tiling-window-manager.html"&gt;http://ubuntu-snippets.blogspot.com/2008/08/xmonad-tiling-window-manager.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://tombuntu.com/index.php/2009/03/17/introduction-to-the-xmonad-tiling-window-manager/"&gt;http://tombuntu.com/index.php/2009/03/17/introduction-to-the-xmonad-tiling-window-manager/&lt;/a&gt;
&lt;a href="https://www.haskell.org/haskellwiki/Xmonad/Using_xmonad_in_Gnome/0.5"&gt;https://www.haskell.org/haskellwiki/Xmonad/Using_xmonad_in_Gnome/0.5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="XMonad in Gnome" src="http://blog.prashanthellina.com/images/xmonad_2.jpg" /&gt;&lt;/p&gt;</summary><category term="gnome"></category><category term="gui"></category><category term="linux"></category><category term="tiling window manager"></category><category term="ubuntu"></category><category term="xmonad"></category></entry><entry><title>Microsoft Surface: Some Videos</title><link href="http://blog.prashanthellina.com/microsoft-surface-some-videos.html" rel="alternate"></link><updated>2009-04-22T20:33:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-04-22:microsoft-surface-some-videos.html</id><summary type="html">&lt;p&gt;I had written earlier about &lt;a href="/2008/12/30/microsoft-surface-unboxing/"&gt;my experience with Microsoft
Surface&lt;/a&gt;. I&amp;#8217;ve captured some
videos of me using it. Here they are&amp;nbsp;&amp;#8230;&lt;/p&gt;</summary><category term="microsoft"></category><category term="surface"></category><category term="touch"></category></entry><entry><title>My Dual Monitor Setup</title><link href="http://blog.prashanthellina.com/my-dual-monitor-setup.html" rel="alternate"></link><updated>2009-04-21T22:48:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2009-04-21:my-dual-monitor-setup.html</id><summary type="html">&lt;p&gt;Greetings webizen, I tried hard to get back to my blogging schedule but
my laziness got the better of me. I am back truly with a new batch of
posts which I will publish over the next few&amp;nbsp;days.&lt;/p&gt;
&lt;p&gt;Recently, I went to Veveo&amp;#8217;s main office near Boston, &lt;span class="caps"&gt;USA&lt;/span&gt; and had the
privilege of experiencing a finger freezing winter! (Not to mention a
three day power-cut which I spent under multiple layers of&amp;nbsp;blankets).&lt;/p&gt;
&lt;p&gt;A few weeks before I was going to return to India, I started shopping.
One of things I bought was a Refurbished NVidia GeForce 9800 &lt;span class="caps"&gt;GTX&lt;/span&gt;+ by
&lt;span class="caps"&gt;EVGA&lt;/span&gt;. It was the best deal I could find on NewEgg in terms of value for
money. I bought it primarily to have a betterr experience when flying
over Paris &amp;#8230; in Google&amp;nbsp;Earth.  &lt;/p&gt;
&lt;p&gt;This is the first graphics card I bought ever and was very excited when
I received it. I was surprised to see how big graphics cards have become
nowadays (compared to S3 cards of the decade gone past). While oggling
at the card I noticed that it had two video outputs. I had heard of
dual-head setups but always considered them a distant reality
considering my cash-strappedness as a college student. This sparked off
&lt;a href="http://jafrenkejnshtein.ru"&gt;more&amp;nbsp;info&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;an urge to finally setup my own Dual monitor setup back in&amp;nbsp;Bangalore.&lt;/p&gt;
&lt;p&gt;I got back to India and promptly headed to &lt;span class="caps"&gt;SP&lt;/span&gt; Road in Bangalore. After
some asking around, I figured that the best choice at the moment was two
Samsung SyncMaster &lt;span class="caps"&gt;2233SW&lt;/span&gt;&amp;#8217;s each capable of 1920x1080 (Yes, &lt;span class="caps"&gt;HD&lt;/span&gt;). I
bought both for about 22,000 Rupees (about &lt;span class="caps"&gt;USD&lt;/span&gt;&amp;nbsp;420).&lt;/p&gt;
&lt;p&gt;I set them up in Linux and upgraded to the latest (at the time) Nvidia
drivers (180.x). I spent a few hours trying to hide a satisfied smile
lest people thing I had gone&amp;nbsp;nuts.&lt;/p&gt;
&lt;p&gt;Dual monitors give you more screen space to work with. They will help
you reduce Window-Switching and Workspace-Switching which does save time
as I have observed. Now that I have experience the dual-head setup, I am
&lt;strong&gt;never&lt;/strong&gt; going back to using a single monitor. It is painful ;) So much
did I feel this that I bought a low-end Nvidia GeForce card (7200) with
dual-head support and stuck it into my computer at work&amp;nbsp;:)&lt;/p&gt;
&lt;p&gt;If you do not already have a dual-head setup, definitely consider an
upgrade. You are worth&amp;nbsp;it:)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/prashanthellina/sets/72157617045645747/"&gt;Go to flickr set for&amp;nbsp;this&lt;/a&gt;  &lt;/p&gt;</summary><category term="dual monitor"></category><category term="dual-head"></category><category term="geforce"></category><category term="nvidia"></category><category term="samsung"></category><category term="syncmaster"></category></entry><entry><title>Microsoft Surface Unboxing</title><link href="http://blog.prashanthellina.com/microsoft-surface-unboxing.html" rel="alternate"></link><updated>2008-12-30T05:16:00-08:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-12-30:microsoft-surface-unboxing.html</id><summary type="html">&lt;p&gt;Today, we received the shipment from Microsoft at Veveo. If you have not
heard of Microsoft Surface before, It is a touch screen based computer
embedded in a table. The surface of table is illuminated from underneath
by a projector (rear-projection) and touch input is implemented by
reflecting &lt;span class="caps"&gt;IR&lt;/span&gt; radiation off the fingers and then being captured by five
&lt;span class="caps"&gt;IR&lt;/span&gt; camera hidden inside the&amp;nbsp;unit.&lt;/p&gt;
&lt;p&gt;To learn more about Microsoft Surface head over&amp;nbsp;to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.microsoft.com/SURFACE/index.html"&gt;Microsoft&amp;#8217;s page on&amp;nbsp;Surface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Microsoft_Surface"&gt;Wikipedia article on Microsoft&amp;nbsp;Surface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=rP5y7yp06n0"&gt;Watch a Youtube video on Microsoft&amp;nbsp;Surface&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Unboxing&amp;nbsp;Pictures&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/prashanthellina/sets/72157611858989460/"&gt;flickr set on microsoft surface&amp;nbsp;unboxing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some&amp;nbsp;observations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is very&amp;nbsp;heavy!&lt;/li&gt;
&lt;li&gt;and expensive (around&amp;nbsp;$15,000)&lt;/li&gt;
&lt;li&gt;The power socket is hidden underneath and is very difficult to
    access. The power button is equally well hidden and difficult to&amp;nbsp;find.&lt;/li&gt;
&lt;li&gt;Installation was non-trivial. The touch input did not start working
    out of the box. We had to use the bundled mouse to initial
    installation&amp;nbsp;steps.&lt;/li&gt;
&lt;li&gt;The &amp;#8220;surface shell&amp;#8221; with the ripples in the water is a great way to
    understand the potential of this device. It feels like you are
    touching water! and your brain expects that water will drip when you
    lift your fingers up. I think it is more realistic (compared to
    devices with smaller touch screens) because of the size of the
    display and the fact that it is aligned horizontally making it more&amp;nbsp;natural.&lt;/li&gt;
&lt;li&gt;Since rear-projection is used for the display, the viewing angle is
    very wide (nearly 180&amp;nbsp;degrees)&lt;/li&gt;
&lt;li&gt;The matte finish on the touch surface as a good feel (almost like&amp;nbsp;paper).&lt;/li&gt;
&lt;/ul&gt;</summary><category term="computer"></category><category term="gadget"></category><category term="interface"></category><category term="microsoft"></category><category term="surface"></category><category term="touch"></category><category term="unboxing"></category></entry><entry><title>Determining the difficulty of Arithmetic Operations</title><link href="http://blog.prashanthellina.com/determining-the-difficulty-of-arithmetic-operations.html" rel="alternate"></link><updated>2008-07-27T22:09:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-07-27:determining-the-difficulty-of-arithmetic-operations.html</id><summary type="html">&lt;p&gt;&lt;img alt="kid math
problem" src="http://blog.prashanthellina.com/images/kid_math_problem.gif" /&gt;I am
trying to write a program to test my arithmetic skills. The program
should pose arithmetic problems involving the four basic operations -
addition, subtraction, multiplication and division. When the testing
session starts, the program should issue problems of less difficulty and
the difficulty should be ramped up gradually. A score should be computed
based on number of questions and the difficulty of questions. The hope
is that if I keep using this program for a little time every day, I&amp;#8217;ll
be able to improve my abysmal arithmetic performance&amp;nbsp;:)&lt;/p&gt;
&lt;p&gt;Note that you will need to have &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt;
installed to try out the script and the examples in this article. I
believe that the code is simple enough to be understood with minimal or
no understanding of the Python language. If any part of the article is
not clear, feel free to point it out to me. Thank&amp;nbsp;you.&lt;/p&gt;
&lt;h2&gt;Estimating&amp;nbsp;difficulty&lt;/h2&gt;
&lt;p&gt;Let us take a look at the following&amp;nbsp;problems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem&amp;nbsp;1&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Problem&amp;nbsp;2&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="mi"&gt;99999&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="mi"&gt;12345&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now, which problem is more difficult? It is quite obvious that Problem 2
is more difficult. But why? One answer would be - &amp;#8220;because Problem 2
involves the addition of two large numbers&amp;#8221;. Fine. Consider this now&amp;nbsp;&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem&amp;nbsp;3&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="mi"&gt;1000001&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Is Problem 3 more difficult than Problem 2 because the numbers
undergoing addition are bigger? The intuitive answer is &amp;#8220;No&amp;#8221;. But why?
Because the time it takes to compute the result is lesser. Why? Because
the number of operations performed during the course of solving Problem
3 are lesser than those of Problem 2?&amp;nbsp;No.&lt;/p&gt;
&lt;p&gt;Problem 3 is easier than Problem 2 because the nature of the operations
performed in Problem 3. The operations there are&amp;nbsp;simpler.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;are arguably simpler operations&amp;nbsp;than&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I&amp;#8217;ve attempted to capture the basic operations we perform while doing
arithmetic and assign a level of difficulty to each. I&amp;#8217;ve then emulated
the algorithms we follow to compute solutions to such problems. By doing
the following, it becomes possible to estimate the &amp;#8220;difficulty&amp;#8221; of an
arithmetic problem (involving the basic&amp;nbsp;operations).&lt;/p&gt;
&lt;p&gt;&lt;img alt="math cartoon yesterday
x" src="http://blog.prashanthellina.com/images/math_cartoon_yesterday_x.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;Operation&amp;nbsp;difficulties&lt;/h2&gt;
&lt;h3&gt;Addition&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;addition_difficulties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;digit_zero&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c"&gt;# any digit added to zero&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;even_even&amp;#39;&lt;/span&gt;  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c"&gt;# sum of even digits&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;odd_odd&amp;#39;&lt;/span&gt;    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c"&gt;# sum of odd digits&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;even_odd&amp;#39;&lt;/span&gt;   &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c"&gt;# sum of even and odd digits&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;carry&amp;#39;&lt;/span&gt;      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;    &lt;span class="c"&gt;# difficulty of carry (for remembering and then adding)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Here is the function which computes the addition difficulty. It is a
recursive function that can compute the addition difficulty for n
numbers. It computes the sum and difficulty of the first two numbers and
then inserts the sum at the head of the list of n numbers in place of
the two numbers just summed. It then calls itself with the modified&amp;nbsp;list.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_addition_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Generates a difficulty number and sum for given&lt;/span&gt;
&lt;span class="sd"&gt;    list of numbers for the addition operation&lt;/span&gt;
&lt;span class="sd"&gt;    *args - integers&lt;/span&gt;
&lt;span class="sd"&gt;    returns: (sum, difficulty)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_addition_difficulty(0, 0)&lt;/span&gt;
&lt;span class="sd"&gt;    (0, 1)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_addition_difficulty(0, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (1, 1)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_addition_difficulty(1, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (2, 2)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_addition_difficulty(1, 2)&lt;/span&gt;
&lt;span class="sd"&gt;    (3, 3)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_addition_difficulty(2, 2)&lt;/span&gt;
&lt;span class="sd"&gt;    (4, 2)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_addition_difficulty(19, 9)&lt;/span&gt;
&lt;span class="sd"&gt;    (28, 5)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_addition_difficulty(99999, 12345)&lt;/span&gt;
&lt;span class="sd"&gt;    (112344, 22)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;


    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;max_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rjust&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rjust&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;reversed&lt;/span&gt;
    &lt;span class="n"&gt;ad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addition_difficulties&lt;/span&gt;
    &lt;span class="nb"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;izip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;d2_is_even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;digit_zero&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;d2_is_even&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;even_even&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d2_is_even&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;odd_odd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;d2_is_even&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;even_odd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;dsum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;dsum&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;carry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dsum&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sub_difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_addition_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sub_difficulty&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Subtraction&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;subtraction_difficulties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;digit_zero&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;# difference of zero and any digit&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;same_digits&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;# difference of same values digits&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;even_even&amp;#39;&lt;/span&gt;  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;# difference of even digits&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;odd_odd&amp;#39;&lt;/span&gt;    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;# difference of odd digits&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;even_odd&amp;#39;&lt;/span&gt;   &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;# difference of even and odd digits&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;borrow&amp;#39;&lt;/span&gt;     &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;# doing a borrow&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;twodigit_digit&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="c"&gt;# difference of two-digit number and digit&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The subtraction function is also recursive and operates similar to
addition in that respect. Before looking at the subtraction algorithm,
take a look at how &amp;#8220;borrowing&amp;#8221; is implemented. Let us say we are trying
to perform the&amp;nbsp;following,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="mi"&gt;200005&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;
     &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After borrowing the number would be, 19999(1)5. We would then subtract 6
from 15 and proceed. The do_borrow() function captures this aspect of&amp;nbsp;substraction.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_borrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cannot perform borrow&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;num_borrows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;next_digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;next_digit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_digit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;num_borrows&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;do_borrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;num_borrows&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This implementation is a bit confusing so check out this example
(do_borrow() applied to the problem mentioned&amp;nbsp;above).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;200005&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;do_borrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s"&gt;&amp;#39;509991&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note that do_borrow returned 4, which indicates that the difficulty of
performing this borrow operation is 4. Also note that do_borrow takes a
list of digits in reversed order. It takes a list because the result is
provided in-place (remember that Python strings are immutable). Now that
you have seen how the borrowing works, all introduce the subtraction&amp;nbsp;function.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_subtraction_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Generates a difficulty number and result for given&lt;/span&gt;
&lt;span class="sd"&gt;    list of numbers for the subtraction operation&lt;/span&gt;
&lt;span class="sd"&gt;    *args (tuple) - integers&lt;/span&gt;
&lt;span class="sd"&gt;    returns: (difference, difficulty)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(0,0)&lt;/span&gt;
&lt;span class="sd"&gt;    (0, 1)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(1,0)&lt;/span&gt;
&lt;span class="sd"&gt;    (1, 1)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(1,1)&lt;/span&gt;
&lt;span class="sd"&gt;    (0, 1)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(2,1)&lt;/span&gt;
&lt;span class="sd"&gt;    (1, 3)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(4,2)&lt;/span&gt;
&lt;span class="sd"&gt;    (2, 2)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(4,3)&lt;/span&gt;
&lt;span class="sd"&gt;    (1, 3)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(100,1)&lt;/span&gt;
&lt;span class="sd"&gt;    (99, 10)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_subtraction_difficulty(5000007,9)&lt;/span&gt;
&lt;span class="sd"&gt;    (4999998, 22)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt;

    &lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;max_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rjust&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rjust&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;borrow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;sd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subtraction_difficulties&lt;/span&gt;
    &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;izip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;d2_is_even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;digit_zero&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;d2_is_even&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;even_even&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d1_is_even&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;odd_odd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;d1_is_even&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;d2_is_even&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;even_odd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;ddiff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;num_borrows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;do_borrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;borrow&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;num_borrows&lt;/span&gt;
            &lt;span class="n"&gt;ddiff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;
            &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;twodigit_digit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;same_digits&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;ddiff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ddiff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sub_difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_subtraction_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sub_difficulty&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Multiplication&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;multiplication_difficulties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;carry&amp;#39;&lt;/span&gt;  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c"&gt;# carry operation, summation difficulty is seperate&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;offset&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The basic operation of multiplying big numbers is one digit by one digit
multiplication. I&amp;#8217;ve tried to capture the difficulty of this operation
as&amp;nbsp;follows&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_single_digit_multiplication_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Max value of multiplication of two digits is 81 (9*9).&lt;/span&gt;
&lt;span class="sd"&gt;    Difficulty of d1*d2 increases as the resulting value&lt;/span&gt;
&lt;span class="sd"&gt;    of the multiplication increases. thereby 9*9=81 is most difficult&lt;/span&gt;
&lt;span class="sd"&gt;    and 0*0 is least difficult.&lt;/span&gt;

&lt;span class="sd"&gt;    We will represent this difficult with value from 1-4 (inclusive)&lt;/span&gt;

&lt;span class="sd"&gt;    Note that the difficulty will be incremented by 1 for presence&lt;/span&gt;
&lt;span class="sd"&gt;    of odd digit in the operands (except for 1 and 5 because it is arguably&lt;/span&gt;
&lt;span class="sd"&gt;    easier to multiply)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; get_single_digit_multiplication_difficulty(0, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (0, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; get_single_digit_multiplication_difficulty(1, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (1, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; get_single_digit_multiplication_difficulty(2, 5)&lt;/span&gt;
&lt;span class="sd"&gt;    (10, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; get_single_digit_multiplication_difficulty(2, 7)&lt;/span&gt;
&lt;span class="sd"&gt;    (14, 2)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; get_single_digit_multiplication_difficulty(2, 6)&lt;/span&gt;
&lt;span class="sd"&gt;    (12, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; get_single_digit_multiplication_difficulty(8, 9)&lt;/span&gt;
&lt;span class="sd"&gt;    (72, 5)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; get_single_digit_multiplication_difficulty(8, 8)&lt;/span&gt;
&lt;span class="sd"&gt;    (64, 4)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;
    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;81.&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# odd numbers are harder to multiply except 1 and 5&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;is_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;difficulty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;At the next level, the operation would be multiplying a multi-digit
number by a single digit, which I call simple multiplication. Over here
I take into account the difficulty of carry. I hope the following code
is self&amp;nbsp;explanatory.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_simple_multiplication_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_simple_multiplication_difficulty(1, 0)&lt;/span&gt;
&lt;span class="sd"&gt;    (0, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_simple_multiplication_difficulty(1, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (1, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_simple_multiplication_difficulty(2, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (2, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_simple_multiplication_difficulty(10, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (10, 2)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_simple_multiplication_difficulty(15, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (15, 2)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_simple_multiplication_difficulty(15, 5)&lt;/span&gt;
&lt;span class="sd"&gt;    (75, 7)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_simple_multiplication_difficulty(999, 7)&lt;/span&gt;
&lt;span class="sd"&gt;    (6993, 25)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiplication_difficulties&lt;/span&gt;
    &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s_diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_single_digit_multiplication_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;s_diff&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;carry_sum_difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_addition_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;carry_sum_difficulty&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;carry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="n"&gt;result_digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Simple multiplication is a basic operation of complex multiplication
(multi-digit multiplied by multi-digit). Let us see an example of
&amp;#8220;complex multiplication&amp;#8221; which the multiplication code&amp;nbsp;follows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;    &lt;span class="mi"&gt;345&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="mi"&gt;123&lt;/span&gt;
  &lt;span class="o"&gt;-----&lt;/span&gt;
   &lt;span class="mi"&gt;1035&lt;/span&gt;
   &lt;span class="mi"&gt;690&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;  &lt;span class="c"&gt;# result is &amp;quot;offset&amp;quot; or multiplied by 10&lt;/span&gt;
  &lt;span class="mi"&gt;345&lt;/span&gt;&lt;span class="n"&gt;xx&lt;/span&gt;  &lt;span class="c"&gt;# result if &amp;quot;offset&amp;quot; or multiplied by 100&lt;/span&gt;
  &lt;span class="o"&gt;-----&lt;/span&gt;
  &lt;span class="mi"&gt;42435&lt;/span&gt;  &lt;span class="c"&gt;# result of summation of above numbers&lt;/span&gt;
  &lt;span class="o"&gt;-----&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first part of the multiplication is to perform simple
multiplications - 345x3, 345x2, 345x1 and to offset the numbers
accordingly. The second part of the operation is to sum the numbers. I
used the addition algorithm to achieve the second part. Check out the
multiplication&amp;nbsp;function.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_multiplication_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Generates a difficulty number and result for given&lt;/span&gt;
&lt;span class="sd"&gt;    list of numbers for the multiplication operation&lt;/span&gt;
&lt;span class="sd"&gt;    *args (tuple) - integers&lt;/span&gt;
&lt;span class="sd"&gt;    returns: (product, difficulty)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(0,0)&lt;/span&gt;
&lt;span class="sd"&gt;    (0, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(1,0)&lt;/span&gt;
&lt;span class="sd"&gt;    (0, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(1,1)&lt;/span&gt;
&lt;span class="sd"&gt;    (1, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(2,1)&lt;/span&gt;
&lt;span class="sd"&gt;    (2, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(5,1)&lt;/span&gt;
&lt;span class="sd"&gt;    (5, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(5,2)&lt;/span&gt;
&lt;span class="sd"&gt;    (10, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(17,2)&lt;/span&gt;
&lt;span class="sd"&gt;    (34, 7)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(17,29)&lt;/span&gt;
&lt;span class="sd"&gt;    (493, 20)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(17,29,3)&lt;/span&gt;
&lt;span class="sd"&gt;    (1479, 31)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_multiplication_difficulty(1776,29,3)&lt;/span&gt;
&lt;span class="sd"&gt;    (154512, 77)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num1&lt;/span&gt;

    &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;borrow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiplication_difficulties&lt;/span&gt;
    &lt;span class="n"&gt;m_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;

        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;m_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_simple_multiplication_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;m_diff&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;m_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;offset&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;m_numbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;m_numbers_sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_numbers_diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_addition_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;m_numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;m_numbers_diff&lt;/span&gt;

    &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m_numbers_sum&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_multiplication_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;m_diff&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Division&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;division_difficulties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;# long division&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;use_digit&amp;#39;&lt;/span&gt;       &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c"&gt;# brinding down digit from dividend&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;multiple_lookup&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c"&gt;# looking up precomputed multiple of divisor&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;quotient_update&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c"&gt;# updating quotient with digit or period&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Implementing long division posed a problem because my understanding of
the mechanics behind the long division algorithm was minimal if not
inexistent. I spent some time trying to &amp;#8220;reverse-engineer&amp;#8221; it. I came
across &amp;#8220;Egyptian Division&amp;#8221; which made things clearer. With a little
help, I managed to implement the following division algorithm. Please
let me know, if you come up with a better&amp;nbsp;approach.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_division_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    Generates a difficulty number, quotient and remainder&lt;/span&gt;
&lt;span class="sd"&gt;    for dividend / divisor&lt;/span&gt;
&lt;span class="sd"&gt;    @precision (int) -- max required number of digits after decimal point in quotient&lt;/span&gt;
&lt;span class="sd"&gt;    returns: (quotient, remainder, difficulty)&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_division_difficulty(54, 5, 0)&lt;/span&gt;
&lt;span class="sd"&gt;    (10.0, 4, 6)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_division_difficulty(50, 5, 0)&lt;/span&gt;
&lt;span class="sd"&gt;    (10.0, 0, 6)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_division_difficulty(575, 6, 0)&lt;/span&gt;
&lt;span class="sd"&gt;    (95.0, 5, 60)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_division_difficulty(575, 6, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (95.829999999999998, 20, 112)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_division_difficulty(6, 9, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (0.66000000000000003, 60, 50)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; compute_division_difficulty(410, 2, 1)&lt;/span&gt;
&lt;span class="sd"&gt;    (205.0, 0, 54)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Division by Zero&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="n"&gt;dividend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;divisor&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;previous_multiples_difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;precision_reached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;decimal_point_used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;dd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;division_difficulties&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;quotient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;use_digit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;q_digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;multiple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiple_difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_multiples_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;q_digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fabs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiple_difficulty&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;previous_multiples_difficulty&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;previous_multiples_difficulty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;multiple_lookup&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;previous_multiples_difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiple_difficulty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;previous_multiples_difficulty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;quotient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q_digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;quotient_update&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decimal_point_used&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;precision_reached&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sub_difficulty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_subtraction_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sub_difficulty&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;precision&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="n"&gt;quotient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;quotient_update&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;decimal_point_used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;decimal_point_used&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;

        &lt;span class="n"&gt;difficulty&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;use_digit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;precision_reached&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;precision&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;quotient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quotient&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;quotient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;difficulty&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You must&amp;#8217;ve noticed the usage of compute_multiples_difficulty(). In
long division, at every step, you will try to find the largest multiple
of the divisor less than or equal to the number in hand to proceed
further. During the process of division, if you&amp;#8217;ve computed the 5th
(say) multiple of the divisor with difficulty N. The computation of 6th
multiple at a later point in the division is difficulty(lookup of 5th
multiple) + difficulty(6-5th&amp;nbsp;multiple).&lt;/p&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#Problem 1&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;compute_addition_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;#Problem 2&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;compute_addition_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;112344&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;#Problem 3&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;compute_addition_difficulty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Problem 1: &lt;strong&gt;2&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Problem 2: &lt;strong&gt;22&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Problem 3: &lt;strong&gt;8&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The&amp;nbsp;End&lt;/h2&gt;
&lt;p&gt;I wish I could have written a more detailed explanation instead of
sprinkling this article with code. Time however prevents me from doing
so :(. It is some relief that Python is a &lt;a href="http://blog.prashanthellina.com/even-a-python-can-be-abused.html"&gt;wonderful language for
readability&lt;/a&gt; and the code
samples above are pretty close to&amp;nbsp;pseudo-code.&lt;/p&gt;
&lt;p&gt;I will post back when I complete the program to generate arithmetic
problems by order of difficulty. Until then, Adios amigos. Almost
forgot! Here is the
&lt;a href="http://code.prashanthellina.com/code/atrainer.py"&gt;code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="meaning of life math
cartoon" src="http://blog.prashanthellina.com/images/meaningoflife.gif" /&gt;&lt;/p&gt;</summary><category term="arithmetic"></category><category term="arithmetic algorithms"></category><category term="borrow"></category><category term="carry"></category><category term="long division"></category><category term="math"></category><category term="problem difficulty"></category><category term="problem generator"></category><category term="python"></category></entry><entry><title>Even a python can be abused</title><link href="http://blog.prashanthellina.com/even-a-python-can-be-abused.html" rel="alternate"></link><updated>2008-07-11T08:34:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-07-11:even-a-python-can-be-abused.html</id><summary type="html">&lt;p&gt;&lt;img alt="python
abuse" src="http://blog.prashanthellina.com/images/python_abuse.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The first
programming language I coded in is &lt;strong&gt;QuickBasic&lt;/strong&gt;. I loved the
simplicity and especially the &lt;span class="caps"&gt;IDE&lt;/span&gt;. It made things simple for a starter.
Later I discovered &lt;strong&gt;Visual Basic&lt;/strong&gt; which extended the same simplicity
and added the &amp;#8220;Visual&amp;#8221; element with a splendid editor for &lt;span class="caps"&gt;GUI&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;In between I did some projects using Java, C#, C, C++. None of these
impressed me too much. I hated Java&amp;#8217;s imposition of stiff rules and it&amp;#8217;s
dogged adherence to &amp;#8220;everything in a class&amp;#8221; attitude. C# was better.
C++ just turned me off because of the monster it is. I did not like C at
all because of its total lack of automated memory handling (like &lt;span class="caps"&gt;GC&lt;/span&gt;).
I&amp;#8217;ve been doing a lot of coding in C now-a-days as part of my job and I
must admit that I like it a lot for its simplicity in primitives and
promise of &amp;#8220;closeness to hardware&amp;#8221; and hence the predictability and&amp;nbsp;performance.&lt;/p&gt;
&lt;p&gt;I did a small part of my final year project using Python. However, for
some unfathomable reason, Python did not impress me at all then. When I
started working at Veveo I used Python for a project and got hooked.
It&amp;#8217;s simplicity and &amp;#8220;readability&amp;#8221; got me. The power of wielding this
tool got me drunk&amp;nbsp;:)&lt;/p&gt;
&lt;p&gt;Python was designed from the beginning to be a &amp;#8220;easy to read&amp;#8221; language.
Most, if not all, of the syntax is intuitive. The indentation adds to
the readability aspect. The policy of &amp;#8220;only one way to do a thing&amp;#8221; does
wonders for readability. Everyone does a certain thing only the &amp;#8220;one&amp;#8221;
way. If you are wondering why the heck I am talking so much about
readability, you should consider the fact that an average programmer
spends &lt;strong&gt;most&lt;/strong&gt; of his time &amp;#8220;reading&amp;#8221; code. You have to read your code
after you&amp;#8217;ve just written it. You&amp;#8217;ve to read your code the next day when
you resume work. You&amp;#8217;ve to read your code the moment a bug is found. You
have to read your code when someone asks you how some aspect of it works
a couple of months later. You&amp;#8217;ve have to read your code when making a
teeny-weeny feature addition. I just cannot emphasize enough how much
time is spent is just reading. There have been times when I would spend
a whole day just reading code and finally making &amp;#8220;a single line of code
change&amp;#8221; at the end of the&amp;nbsp;day!&lt;/p&gt;
&lt;p&gt;So there it is. Python makes it possible to write readable code and that
does wonders to programmer productivity. Maintaining your code becomes
easier. Understanding your collegues code becomes easier and most of all
understanding code written by someone across the world becomes easier -
so you can start reusing components more quickly and with more
confidence than ever&amp;nbsp;before.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I simply love&amp;nbsp;Python.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You must be wondering where I am taking this discussion&amp;#8230; because the
title says something about a Python being abused. Who is abusing the
Python&amp;nbsp;anyway?&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve noticed how newbies code in Python and found it particulary
intriguing. What is interesting here is that every person comes from a
certain programming background and are used to doing things in a certain
way. When they are thrown into a situation where they have to learn a
new language and write some code in it, they invariably apply the vast
experience they have in their language of choice&amp;nbsp;:)&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve had the oppurtunity of observing people from Java, C, Perl, &lt;span class="caps"&gt;VB&lt;/span&gt;
(yes, Perl) backgrounds writing code in Python. The Java guys stress
test multiple inhertitance in Python and bring the much cherished
&amp;#8220;everything in a class&amp;#8221; practice to the Python. The C guys who are more
often than not obsessed with performace and optimization put their
brains to work and implement a strcpy using a &amp;#8220;for loop&amp;#8221; and insist on
doing a &amp;#8220;shift&amp;#8221; instead of &amp;#8220;division/multiplication&amp;#8221;. The Perl guys just
don&amp;#8217;t seem to like the alphanumerals. They craft Python code with
ingenious application making it look very concise. The more characters
in one line the better the code. The more non-alphanumerals the better
coder you are. That&amp;#8217;s the way of the &amp;#8220;Perl&amp;#8217;ies&amp;#8221;. The &lt;span class="caps"&gt;VB&lt;/span&gt; guys languish
for a while complaining constantly about the lack of a proper &lt;span class="caps"&gt;IDE&lt;/span&gt; and
after trying out various Python editors, decide to call it quits and go
home to comfortable &lt;span class="caps"&gt;VB&lt;/span&gt;. I know, I know &amp;#8230;.. I was a &lt;span class="caps"&gt;VB&lt;/span&gt; guy too and I
did search for &lt;span class="caps"&gt;IDE&lt;/span&gt;&amp;#8217;s too &amp;#8230; But then I found &lt;span class="caps"&gt;VIM&lt;/span&gt; and everything was
good&amp;nbsp;:)&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve had the good (snigger) fortune of maintaining some of these
brilliant artifacts and had my share of nightmares and laugh-outs. I
thought I had seen it all, until I saw something today. I told myself
&amp;#8212;- &amp;#8220;Never underestimate a brilliant C programmer who has found exec and
eval in Python&amp;#8221; &amp;#8230; Yes, you can quote me on this&amp;nbsp;:)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;    &lt;span class="n"&gt;guido&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;is speechless&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;larry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;went nuts&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;sergey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;has seen it all now&amp;quot;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;guido&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;larry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;sergey&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;idxv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;idxv&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="n"&gt;idxv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="k"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idxv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;No&amp;#8230;.. I don&amp;#8217;t think I&amp;#8217;ve seen it all&amp;#8230;.&amp;nbsp;;)&lt;/strong&gt;&lt;/p&gt;</summary><category term="C"></category><category term="coding"></category><category term="java"></category><category term="perl"></category><category term="programming"></category><category term="python"></category><category term="readability"></category><category term="VB"></category><category term="visual basic"></category></entry><entry><title>Nose - TDD - Python</title><link href="http://blog.prashanthellina.com/nose-tdd-python.html" rel="alternate"></link><updated>2008-05-22T20:20:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-05-22:nose-tdd-python.html</id><summary type="html">&lt;h3&gt;What,&amp;nbsp;why&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;ve been reading up on
&lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt;&lt;/a&gt; and it has
struck me as particularly useful methodology to achieve &amp;#8220;clean code that
works&amp;#8221;. &lt;span class="caps"&gt;TDD&lt;/span&gt; encourages writing unit tests to cover all the code (because
by definition, you write a test before a line of code is written).
Because all your code is covered you are freed from the fear of breakage
due to change and can instantly be more confident and productive. Also,
the test cases act as a specification in code - very&amp;nbsp;useful.&lt;/p&gt;
&lt;p&gt;Python has standard modules,
&lt;a href="http://docs.python.org/lib/module-unittest.html"&gt;unittest&lt;/a&gt; and
&lt;a href="http://docs.python.org/lib/module-doctest.html"&gt;doctest&lt;/a&gt; to help you
write test cases. I simply love doctest. It alleviates much of the pain
of writing a test case (setup and all) besides acting as &amp;#8220;executable
documentation&amp;#8221;. The unittest module has a Java legacy and is not to my
taste. Also, I wanted to find a solution that would help in automated
test enumeration (discovery) in my source directories without having to
write any &amp;#8220;infrastructure&amp;#8221; code. One more thing I was looking for was a
way to run both unit tests and doc tests&amp;nbsp;together.&lt;/p&gt;
&lt;p&gt;After a bit of searching, I found
&amp;#8220;&lt;a href="http://somethingaboutorange.com/mrl/projects/nose/"&gt;Nose&lt;/a&gt;&amp;#8220;. Nose is a
clone of &amp;#8220;&lt;a href="http://codespeak.net/py/dist/test.html"&gt;py.test&lt;/a&gt;&amp;#8221; which I
liked better than the original (subjectively). To get a feel of &amp;#8220;Nose&amp;#8221;,
I set up some python test&amp;nbsp;files.&lt;/p&gt;
&lt;p&gt;The following is the directory structure and the contents of the files.
I&amp;#8217;ve put in both unit tests and doc tests in the files to see how &amp;#8220;Nose&amp;#8221;
handles them. Also, the tests are spread across directories. Note that I
had to put an &amp;#8220;__init__.py&amp;#8221; to allow &amp;#8220;Nose&amp;#8221; to import tests in a&amp;nbsp;subdirectory.&lt;/p&gt;
&lt;h3&gt;The&amp;nbsp;setup&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The directory&amp;nbsp;structure&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;prashanth@prashanth-desktop:~/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;tree
.
&lt;span class="p"&gt;|&lt;/span&gt;-- bingo.py
&lt;span class="p"&gt;|&lt;/span&gt;-- somedir
&lt;span class="p"&gt;|&lt;/span&gt;   &lt;span class="p"&gt;|&lt;/span&gt;-- __init__.py
&lt;span class="p"&gt;|&lt;/span&gt;   &lt;span class="sb"&gt;`&lt;/span&gt;-- test_another.py
&lt;span class="sb"&gt;`&lt;/span&gt;-- test_prashanth.py

&lt;span class="m"&gt;1&lt;/span&gt; directory, &lt;span class="m"&gt;4&lt;/span&gt; files
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;bingo.py&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;boing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; boing(10, 20)&lt;/span&gt;
&lt;span class="sd"&gt;    30&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;boing1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;gt;&amp;gt;&amp;gt; boing1(10, 20)&lt;/span&gt;
&lt;span class="sd"&gt;    40&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;test_prashanth.py&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_a&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_b&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;somedir/test_another.py&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_bingo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;hgello&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Installing&amp;nbsp;&amp;#8220;Nose&amp;#8221;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo easy_install nose
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you don&amp;#8217;t have easy_install, head over
&lt;a href="http://somethingaboutorange.com/mrl/projects/nose/"&gt;here&lt;/a&gt; to get
information on&amp;nbsp;installation.&lt;/p&gt;
&lt;h3&gt;Running the&amp;nbsp;tests&lt;/h3&gt;
&lt;p&gt;Now that &amp;#8220;Nose&amp;#8221; is installed, let us run the&amp;nbsp;tests,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;nosetests --with-doctest
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The output&amp;nbsp;is&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;..E.F
&lt;span class="o"&gt;======================================================================&lt;/span&gt;
ERROR: somedir.test_another.test_bingo
----------------------------------------------------------------------
Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
  File &lt;span class="s2"&gt;&amp;quot;/usr/lib/python2.5/site-packages/nose-0.10.2-py2.5.egg/nose/case.py&amp;quot;&lt;/span&gt;, line 182, in runTest
    self.test&lt;span class="o"&gt;(&lt;/span&gt;*self.arg&lt;span class="o"&gt;)&lt;/span&gt;
  File &lt;span class="s2"&gt;&amp;quot;/home/prashanth/tmp/somedir/test_another.py&amp;quot;&lt;/span&gt;, line 2, in test_bingo
    raise Exception&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hgello&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
Exception: &lt;span class="nv"&gt;hgello&lt;/span&gt;

&lt;span class="o"&gt;======================================================================&lt;/span&gt;
FAIL: test_prashanth.test_b
----------------------------------------------------------------------
Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
  File &lt;span class="s2"&gt;&amp;quot;/usr/lib/python2.5/site-packages/nose-0.10.2-py2.5.egg/nose/case.py&amp;quot;&lt;/span&gt;, line 182, in runTest
    self.test&lt;span class="o"&gt;(&lt;/span&gt;*self.arg&lt;span class="o"&gt;)&lt;/span&gt;
  File &lt;span class="s2"&gt;&amp;quot;/home/prashanth/tmp/test_prashanth.py&amp;quot;&lt;/span&gt;, line 7, in test_b
    assert 0
AssertionError:
-------------------- &amp;gt;&amp;gt; begin captured stdout &amp;lt;&amp;lt; ---------------------
hello

--------------------- &amp;gt;&amp;gt; end captured stdout &amp;lt;&amp;lt; ----------------------

----------------------------------------------------------------------
Ran &lt;span class="m"&gt;5&lt;/span&gt; tests in 0.057s

FAILED &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1, &lt;span class="nv"&gt;failures&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first line in the output is the &amp;#8220;test progress&amp;#8221; indication (..E.F) .
When a test succeeds, a &amp;#8216;.&amp;#8217; is written. When a test fails, an &amp;#8216;F&amp;#8217; is
written. When a test throws an Exception, an &amp;#8216;E&amp;#8217; is written. Very useful
to get a sense of progress as a huge test suite being&amp;nbsp;executed.&lt;/p&gt;
&lt;p&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Nose&amp;#8221; captures the stdout and stderr when a test case fails to help you
debug the issue. To &lt;a href="http://ivory.idyll.org/articles/nose-intro.html"&gt;learn more about using &amp;#8220;Nose&amp;#8221; go
here&lt;/a&gt;.&lt;/p&gt;</summary><category term="linux"></category><category term="nose"></category><category term="programming"></category><category term="python"></category><category term="tdd"></category><category term="testing"></category><category term="tools"></category></entry><entry><title>Wordza - A Smart Word Quizzer</title><link href="http://blog.prashanthellina.com/wordza-a-smart-word-quizzer.html" rel="alternate"></link><updated>2008-04-27T13:54:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-04-27:wordza-a-smart-word-quizzer.html</id><summary type="html">&lt;p&gt;I&amp;#8217;d thought of making a word quizzer as a web application to improve my
vocabulary when I took the &lt;span class="caps"&gt;GRE&lt;/span&gt; test a couple of years back. I&amp;#8217;d written
one in Visual Basic 6 when I wrote &lt;span class="caps"&gt;SAT&lt;/span&gt; :), but desktop applications are&amp;nbsp;boring!&lt;/p&gt;
&lt;p&gt;I got inspired to bring my long standing idea to fruition and the
outcome is &lt;a href="http://www.wordza.com"&gt;Wordza&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.wordza.com"&gt;&lt;img alt="wordza" src="http://blog.prashanthellina.com/images/wordza_logo.gif" /&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Wordza is a smart word quizzing service designed to help you rapidly
learn new words. It adapts to your level and continually challenges
you to get better. Preparing for &lt;span class="caps"&gt;GRE&lt;/span&gt;/&lt;span class="caps"&gt;SAT&lt;/span&gt;/&lt;span class="caps"&gt;CAT&lt;/span&gt;? Use Wordza 15 minutes a&amp;nbsp;day.&lt;/p&gt;
&lt;p&gt;Questions have difficulty ratings ranging between 1 and 100. The
ratings are derived from user activity. A question is easy if a lot of
people get it right and difficult when very few&amp;nbsp;do!&lt;/p&gt;
&lt;p&gt;You start at difficulty level 50. If you get three questions right in
a row, you drive up the difficulty level a notch. On the other hand,
answering a question wrong will reduce the difficulty level by&amp;nbsp;one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="wordza
screenshot" src="http://blog.prashanthellina.com/images/wordza_screenshot.gif" /&gt;&lt;/p&gt;
&lt;p&gt;If you are interested in the implementation &amp;#8230; I used Python, MySQL
behind Apache to get this up. When I started making it, I wanted to keep
it simple and make it work fast. I hope I&amp;#8217;ve met both these
requirements. Do give it a try and let me know what you&amp;nbsp;think.&lt;/p&gt;</summary><category term="quiz"></category><category term="vocabulary"></category><category term="web"></category><category term="word"></category><category term="wordza"></category></entry><entry><title>Selecting a random row from a table in mysql</title><link href="http://blog.prashanthellina.com/selecting-a-random-row-from-a-table-in-mysql.html" rel="alternate"></link><updated>2008-04-08T21:30:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-04-08:selecting-a-random-row-from-a-table-in-mysql.html</id><summary type="html">&lt;p&gt;&lt;img alt="database" src="http://blog.prashanthellina.com/images/database_symbol.png" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I have come across more than one instance when I had to select a
random record from a table in a MySQL database. Here is how to do&amp;nbsp;it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;The simple but slow&amp;nbsp;method&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mytable&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;RAND&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Although simple, the above query can be very slow on tables which have a
large number of records. This happens because MySQL makes a temporary
table with a random number assigned to each row. It then sorts the table
and returns the one record from the sorted&amp;nbsp;list.&lt;/p&gt;
&lt;h2&gt;Random record selection by id generation : A better and faster&amp;nbsp;method&lt;/h2&gt;
&lt;p&gt;The table will need to have an &amp;#8216;id&amp;#8217; field which is an auto-incrementing
integer. The approach is to generate a random number which falls in the
range of the values of the &amp;#8216;id&amp;#8217; field. MySQL &lt;span class="caps"&gt;MAX&lt;/span&gt;() and &lt;span class="caps"&gt;MIN&lt;/span&gt;() grouping
functions allow you to choose the maximum and minimum values of a&amp;nbsp;field.&lt;/p&gt;
&lt;h3&gt;The python&amp;nbsp;approach&lt;/h3&gt;
&lt;p&gt;Sample python code to do the random record&amp;nbsp;selection&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;SELECT MIN(id) FROM mytable&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;min_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;SELECT MAX(id) FROM mytable&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;max_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;random_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;SELECT * FROM mytable WHERE id = &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random_id&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
&lt;span class="n"&gt;random_record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Pure &lt;span class="caps"&gt;SQL&lt;/span&gt;&amp;nbsp;approach&lt;/h3&gt;
&lt;p&gt;MySQL offers a &lt;span class="caps"&gt;RAND&lt;/span&gt;() function which generates a random floating point
number between 0.0 and 1.0. We will use this value and scale it to fit
into the max - min value range of the id&amp;nbsp;field.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mytable&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;MIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;FLOOR&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;RAND&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mytable&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So next time you have to select a random record, you know what to do&amp;nbsp;:)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Additional&amp;nbsp;information&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.phptoys.com/e107_plugins/content/content.php?content.28"&gt;http://www.phptoys.com/e107_plugins/content/content.php?content.28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.carlj.ca/2007/12/16/selecting-random-records-with-sql/"&gt;http://www.carlj.ca/2007/12/16/selecting-random-records-with-sql/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://akinas.com/pages/en/blog/mysql_random_row/"&gt;http://akinas.com/pages/en/blog/mysql_random_row/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><category term="database"></category><category term="mysql"></category><category term="query"></category><category term="random record"></category><category term="tip"></category></entry><entry><title>How to generate domain names, place names … product names ?</title><link href="http://blog.prashanthellina.com/how-to-generate-domain-names-place-names-product-names.html" rel="alternate"></link><updated>2008-04-03T22:35:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-04-03:how-to-generate-domain-names-place-names-product-names.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;&lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One of the trickiest and enjoyable parts of starting something new (be
it a website, project, band) is naming it! Sometimes a good name can
be quite elusive and cause more than the deserved share of brain ache.
Here is a list of automated services around the internet that will
help you get name&amp;nbsp;suggestions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Let us name a&amp;nbsp;domain!&lt;/h2&gt;
&lt;p&gt;&lt;img alt="domain tools" src="http://img.domaintools.com/logo_2.png" /&gt;&lt;br /&gt;
&lt;a href="http://www.domaintools.com/"&gt;http://www.domaintools.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;DomainTools takes a concept as input and comes up with domain name
suggestions. Let us say you are starting a website about &amp;#8220;Vacations in
Mexico&amp;#8221;. Go to their website and type in &amp;#8220;Mexico Vacations&amp;#8221; in the text
box and click on the button to get&amp;nbsp;suggestions.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://domain-suggestions.domaintools.com/?q=Mexico+Vacations"&gt;Domain name suggestions for &amp;#8220;Mexico&amp;nbsp;Vacations&amp;#8221;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;MexicoFreeTours.com&lt;br /&gt;
 GreatMexicoTrips.com&lt;br /&gt;
 MexicoGreatBreaks.com&lt;br /&gt;
 MyMexTrips.com&lt;br /&gt;&amp;nbsp;FunMexVacations.com&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not bad at all. I like&amp;nbsp;GreatMexicoTrips.com.&lt;/p&gt;
&lt;p&gt;Another tool out there is &lt;strong&gt;&lt;a href="http://arf.noemata.net/dings/"&gt;Noemata Domain name
generator&lt;/a&gt;&lt;/strong&gt;. This one gives random
domain name suggestions. Not very&amp;nbsp;impressive.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;kawlant.com&lt;br /&gt;
 phobolapa.com&lt;br /&gt;
 jupidox.com&lt;br /&gt;&amp;nbsp;nitrurth.com&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Doing a web2.0 start-up? Don&amp;#8217;t sweat over the&amp;nbsp;name&lt;/h2&gt;
&lt;p&gt;Flickr, tumblr, zoho - all taken up? Find&amp;nbsp;more!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.lightsphere.com/dev/web20.html"&gt;The Web2.0 name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Gedel&lt;br /&gt;
 Eavu&lt;br /&gt;
 Plamba&lt;br /&gt;
 Trilith&lt;br /&gt;&amp;nbsp;Zooveo&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://www.hackslash.net/?page_id=48"&gt;&lt;br /&gt;
Another Web2.0 name&amp;nbsp;generator&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;65pages&lt;br /&gt;
 inclicks&lt;br /&gt;
 type17&lt;br /&gt;&amp;nbsp;bubbledesks&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.webscriptlab.com/domainnamegenerator.php"&gt;Another one!&lt;/a&gt;&lt;/strong&gt;
- This one checks domain availability too.&amp;nbsp;sweet.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Skiplounge&lt;br /&gt;&amp;nbsp;Mivee&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://what.was.the.question.whyblog.org/buzz/"&gt;Web2.0 buzz&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;2.0 is the new New. It&amp;#8217;s all changing. Label what defies
categorization. &amp;#8220;&lt;span class="caps"&gt;ASL&lt;/span&gt;&amp;#8221; is geezer speak. Podcasts. The words aren&amp;#8217;t what
they were. Clear that. Hack it. Faster. Faster! Float this. Roll your
own roll-your-own. &lt;span class="caps"&gt;MSM&lt;/span&gt; just doesn&amp;#8217;t get it. Always be launching. The
buzz is loud and clear. You need someone who gets it. On-demand
streams. Splog is an aggregate noun. We are on the brink of a new age.
This will change everything. We&amp;#8217;re about what Web 2.0 is about.
Single. Word. Sentences! News clouds. An &lt;span class="caps"&gt;AJAX&lt;/span&gt;-driven &lt;span class="caps"&gt;GUI&lt;/span&gt;. Cry out,
blogosphere! This is newer media. The new is old. Tag me. We shall
transcend borders. Clustering. It&amp;#8217;s all about community. Social is the
new push.&amp;nbsp;Folksonomy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Starting a band? Check out the band name&amp;nbsp;generator&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class="caps"&gt;B.A.N.&lt;/span&gt;G - Band automatic name generator!&lt;br /&gt;
 Subtle Alphabet&lt;br /&gt;
 Uncommon Elasticity&lt;br /&gt;
 Notorious Sand&lt;br /&gt;
 Crass&amp;nbsp;Ink&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Play Civ3? Want a name for your new&amp;nbsp;city?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://nine.frenchboys.net/country.php"&gt;The place name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Agea&lt;br /&gt;
 Byzernova&lt;br /&gt;
 Genesini&lt;br /&gt;
 Mercentia&lt;br /&gt;&amp;nbsp;Myruaror&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://nine.frenchboys.net/fantasyplace.php"&gt;The fantasy place name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Aldmeadow&lt;br /&gt;
 Blacklake&lt;br /&gt;
 Southshore&lt;br /&gt;
 Wildecoast&lt;br /&gt;&amp;nbsp;Witchmead&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.generatorland.com/generators/british_town_gl.php"&gt;The British town name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cuddleballabridge, Cambridgeshire&lt;br /&gt;
 Buttercanter Gate up the Snotty, Wiltshire&lt;br /&gt;
 Old Chippingbeck, Shropshire&lt;br /&gt;
 Dorkstrathsack in the Gloaming,&amp;nbsp;Somerset&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Game name&amp;nbsp;generators&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.seventhsanctum.com/generate.php?Genname=rpgnamer"&gt;&lt;span class="caps"&gt;RPG&lt;/span&gt; Name&amp;nbsp;Generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Gilder&amp;#8217;s Airship&lt;br /&gt;
 Ruby Law V&lt;br /&gt;
 Sad Guardian&lt;br /&gt;
 Star: Ghost of the Interstellar Air&lt;br /&gt;
 Unnamed Peace &lt;span class="caps"&gt;XI&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://naminator.planets.gamespy.com/superhero2.html?"&gt;The Ultimate game name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Aqua Badger&lt;br /&gt;
 Nuclear&amp;nbsp;Dazzler&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.djork.net/castlevania/"&gt;Castlevania - game name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Surf Saxophone of Dog Poo&lt;br /&gt;
 Minuet of Skunky Beer&lt;br /&gt;
 Bathroom Break of Stubbed&amp;nbsp;Toes&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://norefuge.net/vgng/vgng.html"&gt;The Video game name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Intelligent Kangaroo Park&lt;br /&gt;
 Spectacular Dentist All-Stars&lt;br /&gt;
 Master Chief&amp;#8217;s Fantasy&amp;nbsp;Rocket&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.rinkworks.com/namegen/fnames.cgi?d=checked&amp;amp;f=0"&gt;Character name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ageroth&lt;br /&gt;
 Cheon&lt;br /&gt;
 Hagiti&lt;br /&gt;&amp;nbsp;Roddareld&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Name your dream&amp;nbsp;gadget!&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.seventhsanctum.com/generate.php?Genname=jokegadget"&gt;Wacky gadget name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Atomic Chronostinker&lt;br /&gt;
 Computerized Golfing Zapperion&lt;br /&gt;
 Configurable Barfer&lt;br /&gt;
 Configurable Electromagnetic Lithowhiner&lt;br /&gt;
 Dimension&amp;nbsp;Whiner&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Name a corporation or&amp;nbsp;government&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.seventhsanctum.com/generate.php?Genname=corporationname"&gt;Corporation name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Boyd Science Logistics Holdings&lt;br /&gt;
 Cosmotechnics&lt;br /&gt;
 Estrada Medical Transportation&lt;br /&gt;
 Genetics Cosmosystems&lt;br /&gt;
 Gold Informational&amp;nbsp;Solutions&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.seventhsanctum.com/generate.php?Genname=government"&gt;Government&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ancient Imperial Unity&lt;br /&gt;
 Constitutional Brotherhood&lt;br /&gt;
 Dominion of States&lt;br /&gt;
 Provincial Authority of&amp;nbsp;Territories&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Name the&amp;nbsp;pub&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.mybeerpix.com/pub_name_generator.php"&gt;Pub name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The tenrec &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; indian&lt;br /&gt;
 The boa constrictor &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; bar&lt;br /&gt;
 The kudu &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; deal&lt;br /&gt;
 The serval &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;guide&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Cook up a research topic for your thesis :)&amp;nbsp;!&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.cs.purdue.edu/homes/dec/essay.topic.generator.html"&gt;A research topic&amp;nbsp;generator!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A virtual high-speed agent embedded in a collaborative digital
interface&lt;br /&gt;
 An active mobile display embedded in a meta-level programmable
solution&lt;br /&gt;
 A high-level logical preprocessor related to an interactive
concurrent theorem prover&lt;br /&gt;
 A responsive high-speed preprocessor applied to an active proxy&amp;nbsp;network&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Throw some insults&amp;nbsp;around!&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.rinkworks.com/namegen/fnames.cgi?d=checked&amp;amp;f=11"&gt;An insult&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sneezefinger&lt;br /&gt;
 Muckfoot&lt;br /&gt;
 Bumface&lt;br /&gt;&amp;nbsp;Wadface&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;People&amp;nbsp;names!&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.rinkworks.com/namegen/fnames.cgi"&gt;Greek&amp;nbsp;names&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Turatia&lt;br /&gt;
 Dodius&lt;br /&gt;
 Struinaus&lt;br /&gt;&amp;nbsp;Kymius&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.rinkworks.com/namegen/fnames.cgi"&gt;Japanese&amp;nbsp;names&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Omira&lt;br /&gt;
 Ayuro&lt;br /&gt;
 Ekochiyu&lt;br /&gt;&amp;nbsp;Hetamuri&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Cook up some&amp;nbsp;colors&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://nine.frenchboys.net/color.php"&gt;Color name&amp;nbsp;generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cobalt Mesa&lt;br /&gt;
 French Latte&lt;br /&gt;
 Slate&lt;br /&gt;
 Southern Maroon&lt;br /&gt;
 Swirl&amp;nbsp;Purple&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I am sure there are many more around the web that I missed. &lt;strong&gt;If you
find anything interesting, comment about&amp;nbsp;it!&lt;/strong&gt;&lt;/p&gt;</summary><category term="domain names"></category><category term="name generator"></category><category term="name suggestions"></category><category term="product names"></category><category term="web2.0 names"></category></entry><entry><title>Visualizing mpeg4 motion compensation vectors using mplayer</title><link href="http://blog.prashanthellina.com/visualizing-mpeg4-motion-compensation-vectors-using-mplayer.html" rel="alternate"></link><updated>2008-03-30T00:17:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-03-30:visualizing-mpeg4-motion-compensation-vectors-using-mplayer.html</id><summary type="html">&lt;p&gt;The &lt;span class="caps"&gt;MPEG4&lt;/span&gt; video encoding process makes use of &lt;strong&gt;block motion
compensation&lt;/strong&gt; to achieve compression. The motion compensation process
serves to produce the intra frames which are the frames between
keyframes. I&amp;#8217;ve always been fascinated by this process and was delighted
to find out that my favorite video player, &lt;strong&gt;mplayer&lt;/strong&gt;, allows one to
visualize this process. I tried it and it is&amp;nbsp;wonderful!&lt;/p&gt;
&lt;p&gt;This is the video I tried the process on:
&lt;a href="http://blog.prashanthellina.com/images/motion_vector_video.avi"&gt;&lt;strong&gt;download&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;img alt="motion compensation vector
visualization" src="http://blog.prashanthellina.com/images/motion_vector_a_0.jpg" /&gt;
&lt;img alt="motion compensation vector
visualization" src="http://blog.prashanthellina.com/images/motion_vector_a_1.jpg" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;img alt="motion compensation vector
visualization" src="http://blog.prashanthellina.com/images/motion_vector_b_0.jpg" /&gt;
&lt;img alt="motion compensation vector
visualization" src="http://blog.prashanthellina.com/images/motion_vector_b_1.jpg" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;img alt="motion compensation vector
visualization" src="http://blog.prashanthellina.com/images/motion_vector_c_0.jpg" /&gt;
&lt;img alt="motion compensation vector
visualization" src="http://blog.prashanthellina.com/images/motion_vector_c_1.jpg" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;img alt="motion compensation vector
visualization" src="http://blog.prashanthellina.com/images/motion_vector_d_0.jpg" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;To try this out yourself, you will first need to have
&lt;a href="http://www.mplayerhq.hu/design7/news.html"&gt;mplayer&lt;/a&gt; installed. If you
are running Debian/Ubuntu, do&amp;nbsp;this,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install mplayer
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After this, download the video using the link provided above. Run this&amp;nbsp;command,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mplayer -lavdopts &lt;span class="nv"&gt;vismv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; -vo x11 motion_vector_video.avi
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To learn more about &lt;strong&gt;motion compensation&lt;/strong&gt;, go
&lt;a href="http://en.wikipedia.org/wiki/Motion_compensation"&gt;&lt;strong&gt;here&lt;/strong&gt;.&lt;/a&gt;
&lt;strong&gt;Enjoy!&lt;/strong&gt;&lt;/p&gt;</summary><category term="linux"></category><category term="motion compensation"></category><category term="mpeg4"></category><category term="mplayer"></category><category term="video"></category><category term="video compression"></category><category term="visualization"></category></entry><entry><title>Creating video thumbnails using ffmpeg</title><link href="http://blog.prashanthellina.com/creating-video-thumbnails-using-ffmpeg.html" rel="alternate"></link><updated>2008-03-29T00:28:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-03-29:creating-video-thumbnails-using-ffmpeg.html</id><summary type="html">&lt;p&gt;Generating thumbnails/screenshots of a video is useful in many ways.
Youtube and many other video sites use this to show a preview of the
video as a small thumbnail. Google video captures a series of thumbnails
from a video at various time intervals to show a better video&amp;nbsp;preview.&lt;/p&gt;
&lt;p&gt;There is a simple way to generate thumbnails in Linux using ffmpeg, a
very very useful tool for processing videos. Let us generate a thumbnail
for this
&lt;a href="http://blog.prashanthellina.com/images/motion_vector_video.avi"&gt;video&lt;/a&gt;.
Download the video and rename it to&amp;nbsp;test.avi.&lt;/p&gt;
&lt;p&gt;Then, run this&amp;nbsp;command,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;ffmpeg  -itsoffset -4  -i test.avi -vcodec mjpeg -vframes &lt;span class="m"&gt;1&lt;/span&gt; -an -f rawvideo -s 320x240 test.jpg
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This command generates a 320x240 sized &lt;span class="caps"&gt;PNG&lt;/span&gt; thumbnail at the 4th second
in the video. The output looks like this.
&lt;img alt="video thumbnail" src="http://blog.prashanthellina.com/images/vid_thumb.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;If you do not have ffmpeg installed and are using Debian/Ubuntu,&amp;nbsp;do,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install ffmpeg
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;A series of thumbnails, at 4, 8, 12 and 16 seconds.
&lt;img alt="video
thumbnail" src="http://blog.prashanthellina.com/images/vid_thumb.jpg" /&gt;
&lt;img alt="video
thumbnail" src="http://blog.prashanthellina.com/images/vid_thumb_8.jpg" /&gt;
&lt;img alt="video
thumbnail" src="http://blog.prashanthellina.com/images/vid_thumb_12.jpg" /&gt;
&lt;img alt="video
thumbnail" src="http://blog.prashanthellina.com/images/vid_thumb_16.jpg" /&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;ffmpeg  -itsoffset -4  -i test.avi -vcodec mjpeg -vframes &lt;span class="m"&gt;1&lt;/span&gt; -an -f rawvideo -s 320x240 test.jpg
ffmpeg  -itsoffset -8  -i test.avi -vcodec mjpeg -vframes &lt;span class="m"&gt;1&lt;/span&gt; -an -f rawvideo -s 320x240 test.jpg
ffmpeg  -itsoffset -12  -i test.avi -vcodec mjpeg -vframes &lt;span class="m"&gt;1&lt;/span&gt; -an -f rawvideo -s 320x240 test.jpg
ffmpeg  -itsoffset -16  -i test.avi -vcodec mjpeg -vframes &lt;span class="m"&gt;1&lt;/span&gt; -an -f rawvideo -s 320x240 test.jpg
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;useful&amp;nbsp;links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.amnuts.com/2007/06/22/create-a-random-thumbnail-of-a-video-file/"&gt;Create a random thumbnail of a video&amp;nbsp;file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.danielfischer.com/2007/06/27/how-to-use-ffmpeg-to-convert-video-via-ruby-on-rails/"&gt;http://www.danielfischer.com/2007/06/27/how-to-use-ffmpeg-to-convert-video-via-ruby-on-rails/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy&amp;nbsp;thumbnailing!&lt;/p&gt;</summary><category term="ffmpeg"></category><category term="linux"></category><category term="thumbnail"></category><category term="video"></category></entry><entry><title>Songza - music search engine and jukebox</title><link href="http://blog.prashanthellina.com/songza-music-search-engine-and-jukebox.html" rel="alternate"></link><updated>2008-03-27T23:17:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-03-27:songza-music-search-engine-and-jukebox.html</id><summary type="html">&lt;p&gt;&lt;a href="http://songza.com/"&gt;&lt;img alt="songza" src="http://blog.prashanthellina.com/images/songza.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Every once in a while, someone comes up with a way of doing things in an
extremely obvious and simple way. When this happens, a zillion others
say, &amp;#8220;of course that&amp;#8217;s the way to do it!&amp;#8221;. Songza is a music search
engine and jukebox that is dead simple to use. You should try it to
really grok how simple the interface&amp;nbsp;is.  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Songza is the single best place to search for and listen to music on
the Web. Find a song and listen immediately, in one&amp;nbsp;place.&lt;/p&gt;
&lt;p&gt;Unlike KaZaa or Bit Torrent, Songza users can only listen to songs,
not download them. And unlike Last.fm or Rhapsody, Songza permits
users to choose exactly the song or artist they want to hear, and does
not require them to subscribe or pay for its&amp;nbsp;services.&lt;/p&gt;
&lt;p&gt;Songza is the brainchild of 24-year-old Aza Raskin — the son of Apple
Macintosh founder Jef Raskin. He and Scott Robbin worked feverishly to
bring the idea to life. The site launched on November 8, 2007, and
instantly generated significant buzz around the world. Hundreds of
bloggers and news writers have praised its elegant user interface,
beautiful design, and all-around utility. Like all good ideas, both
the concept and design came to Aza while he was in the&amp;nbsp;shower.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The thing I liked most about songza is the &amp;#8220;pie-menu&amp;#8221;.&lt;br /&gt;
&lt;img alt="songza pie
menu" src="http://blog.prashanthellina.com/images/songza-share.jpg" /&gt;&lt;/p&gt;
&lt;h3&gt;useful&amp;nbsp;links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;http://ajaxian.com/archives/songza-would-you-like-a-habituatable-pie-menus-with-your-social-music&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.downloadsquad.com/2008/03/04/songza-adds-new-features/"&gt;http://www.downloadsquad.com/2008/03/04/songza-adds-new-features/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://humanized.com/weblog/2007/11/13/songza-launch/"&gt;http://humanized.com/weblog/2007/11/13/songza-launch/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.wired.com/music/2007/11/songza-turns-yo.html"&gt;http://blog.wired.com/music/2007/11/songza-turns-yo.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://lifehacker.com/software/music/listen-to-music-on+demand-with-songza-321638.php"&gt;http://lifehacker.com/software/music/listen-to-music-on+demand-with-songza-321638.php&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><category term="music"></category><category term="search"></category><category term="songza"></category><category term="web"></category></entry><entry><title>Rendezvous with Rama - Goodbye Mr. Clarke</title><link href="http://blog.prashanthellina.com/rendezvous-with-rama-goodbye-mr-clarke.html" rel="alternate"></link><updated>2008-03-25T22:36:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-03-25:rendezvous-with-rama-goodbye-mr-clarke.html</id><summary type="html">&lt;p&gt;I am a huge fan of the science fiction genre. &lt;strong&gt;Arthur C Clarke&lt;/strong&gt; is one
of my favorite science fiction writers after Isaac Asimov. It saddens me
to have learnt that he has passed away. Most people get reminded of
&amp;#8220;&lt;strong&gt;2001: A Space Odyssey&lt;/strong&gt;&amp;#8221; when they hear the name Arthur C Clarke. I
get reminded of &amp;#8220;&lt;strong&gt;Rendezvouz with Rama&lt;/strong&gt;&amp;#8220;, a brilliantly conceived
novel that set my imagination on fire. For all the Clarke fans out
there, &amp;#8220;&lt;a href="http://en.wikipedia.org/wiki/Rendezvous_with_Rama"&gt;Rendezvouz with
Rama&lt;/a&gt;&amp;#8220;.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rendezvous with Rama&lt;/strong&gt;&lt;br /&gt;
&lt;img alt="Rendezvous with
Rama" src="http://blog.prashanthellina.com/images/rama.jpg" /&gt;  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rama interior - somewhat&amp;nbsp;inaccurate&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A short&amp;nbsp;film&lt;/strong&gt;  &lt;/p&gt;
&lt;h3&gt;links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://oneneatthingaday.wordpress.com/2008/03/18/3-18-08-rendezvous-with-rama/"&gt;http://oneneatthingaday.wordpress.com/2008/03/18/3-18-08-rendezvous-with-rama/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://infocult.typepad.com/infocult/2008/03/thank-you-arthu.html"&gt;http://infocult.typepad.com/infocult/2008/03/thank-you-arthu.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ultrabrown.com/posts/rendezvous-with-rama-updated"&gt;http://www.ultrabrown.com/posts/rendezvous-with-rama-updated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://roicopy.com/2008/03/19/sf-legend-clarke-has-rendezvous-with-rama/"&gt;http://roicopy.com/2008/03/19/sf-legend-clarke-has-rendezvous-with-rama/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ramans always do things in&amp;nbsp;threes!&lt;/p&gt;</summary><category term="arthur c clarke"></category><category term="novel"></category><category term="rendezvous with rama"></category><category term="science fiction"></category></entry><entry><title>Watching Television on Linux: setting up a TV Tuner card</title><link href="http://blog.prashanthellina.com/watching-television-on-linux-setting-up-a-tv-tuner-card.html" rel="alternate"></link><updated>2008-03-23T18:37:00-07:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-03-23:watching-television-on-linux-setting-up-a-tv-tuner-card.html</id><summary type="html">&lt;p&gt;A couple of weeks back, I went shopping looking for a &lt;span class="caps"&gt;TV&lt;/span&gt; tuner card that
is compatible with Linux. Googling had told me that &amp;#8220;Hauppauge&amp;#8221; card was
known to be compatible. However, I could not find it anywhere in the
market (&lt;span class="caps"&gt;SP&lt;/span&gt; Road, Bangalore, India). On going to one of the shops, I
found a &amp;#8220;&lt;strong&gt;&lt;a href="http://www.pinnaclesys.com/PublicSite/uk/Products/Consumer+Products/PCTV+Tuners/PCTV+Analog+PVR+(cable_antenna)/PCTV+50i.htm"&gt;Pinnacle &lt;span class="caps"&gt;PCTV&lt;/span&gt;
50i&lt;/a&gt;&lt;/strong&gt;&amp;#8221;
card. I had heard from many people before that Pinnacle was a good card
for Windows both in terms of quality of decoding and software provided.
I checked in google to ensure that Pinnacle card would work on Linux. I
found that the card uses Philips&amp;#8217; &lt;span class="caps"&gt;SAA7134&lt;/span&gt; chipset for which drivers are
available in Linux. I went on and bought the card for Rs 2000&amp;nbsp;(\$50).&lt;/p&gt;
&lt;p&gt;The card is available through Amazon.com.
&lt;a href="http://www.amazon.com/gp/product/B000FKP2TY?ie=UTF8&amp;amp;tag=prashellin-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=B000FKP2TY"&gt;Pinnacle &lt;span class="caps"&gt;PCTV&lt;/span&gt; Analog &lt;span class="caps"&gt;PCI&lt;/span&gt; 50i - &lt;span class="caps"&gt;TV&lt;/span&gt; / radio tuner / video input adapter
- &lt;span class="caps"&gt;PCI&lt;/span&gt; - &lt;span class="caps"&gt;SECAM&lt;/span&gt;,
&lt;span class="caps"&gt;PAL&lt;/span&gt;&lt;/a&gt;&lt;img alt="" src="http://www.assoc-amazon.com/e/ir?t=prashellin-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=B000FKP2TY" /&gt;&lt;/p&gt;
&lt;h3&gt;Setting up the card in&amp;nbsp;Linux&lt;/h3&gt;
&lt;p&gt;I have Ubuntu Gutsy installed (7.10) and followed this
&lt;a href="http://www.cyberciti.biz/tips/debian-ubuntu-linux-configure-pinnacle-pctv-tuner.html"&gt;guide&lt;/a&gt;
to setup the card and the instructions worked like a charm. A gist of
the&amp;nbsp;procedure.&lt;/p&gt;
&lt;p&gt;Ubuntu Gutsy recognizes the card automatically, the following commands
help to check if the recognition happened or not. Both commands should
give atleast one line of output&amp;nbsp;each.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo update-pciids
lspci &lt;span class="p"&gt;|&lt;/span&gt; grep -i saa713
dmesg &lt;span class="p"&gt;|&lt;/span&gt; grep saa713
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Watching &lt;span class="caps"&gt;TV&lt;/span&gt; -&amp;nbsp;tvtime&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.google.co.in/url?sa=t&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Ftvtime.sourceforge.net%2F&amp;amp;ei=klfmR6P-B4KS6gOAlPG7CA&amp;amp;usg=AFQjCNGRL5Fj7JAjfXMzgie-hp7wt7zDrA&amp;amp;sig2=RCYG_ORJgTwlDYRmxgXc2A"&gt;&lt;strong&gt;tvtime&lt;/strong&gt;&lt;/a&gt;
is a simple to use application for watching &lt;span class="caps"&gt;TV&lt;/span&gt; on Linux. Here is how you
configure&amp;nbsp;it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install tvtime
tvtime &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Right click to open a setup menu. You can also hit [F1] or [tab] key
to show configuration menu:
 Linux Tvtime configuration hit [F1] or [tab] key to show
configuration menu
 (Fig. 01: Linux tvtime application configuration menu)
 First, you need to setup video source, frequencies and channels&amp;nbsp;etc.&lt;/p&gt;
&lt;h5&gt;Setup video&amp;nbsp;source&lt;/h5&gt;
&lt;p&gt;Visit Input Configuration &gt; Change Video Source &gt; Setup source as
per your&amp;nbsp;setup.&lt;/p&gt;
&lt;h5&gt;Setup frequencies&amp;nbsp;table&lt;/h5&gt;
&lt;p&gt;You need to setup the channels you are receiving with the tuner. Here
we use europe frequencies table. Visit Channel management &gt; Change
Frequency table &gt; Select new table
Scan&amp;nbsp;Channel&lt;/p&gt;
&lt;p&gt;Finally, you need to scan for channels by visiting Channel management
&gt; Change Frequency table &gt; Scan channels for signal &gt; Back &gt; Exit&lt;/p&gt;
&lt;h5&gt;Sound&amp;nbsp;configuration&lt;/h5&gt;
&lt;p&gt;You need to attach internal cables to get sound out of &lt;span class="caps"&gt;TV&lt;/span&gt; tuner card.
Use driver saa7134-oss or saa7134-alsa to get sound out of card. This
driver get loaded automatically. Open terminal and type the following
command to hear the audio through &lt;span class="caps"&gt;ALSA&lt;/span&gt; using tvtime (or other programs
that don’t support it&amp;nbsp;directly):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sox -c &lt;span class="m"&gt;2&lt;/span&gt; -s -w -r &lt;span class="m"&gt;32000&lt;/span&gt; -t ossdsp /dev/dsp1 -t ossdsp -w -r &lt;span class="m"&gt;32000&lt;/span&gt; /dev/dsp
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Recording &lt;span class="caps"&gt;TV&lt;/span&gt; using&amp;nbsp;mencoder&lt;/h3&gt;
&lt;p&gt;if you do not already have mencoder, you can install it (on
Debian/Ubuntu) by&amp;nbsp;doing&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install mencoder mplayer
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note that the above command will also install mplayer which is useful for
viewing video files and tv channels. If you are the command line kind of
person, you can do away with tvtime and use&amp;nbsp;mplayer!&lt;/p&gt;
&lt;p&gt;To record a &lt;span class="caps"&gt;TV&lt;/span&gt; channel, you will first need to figure out the frequency of
the channel. For this I found scantv useful. This command will scan channels
in the specified range and print out the found channels. After figuring out
the frequency of the channel to record, use this mencoder command to record
the video in a compressed&amp;nbsp;format.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mencoder tv:// -tv &lt;span class="nv"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v4l2:input&lt;span class="o"&gt;=&lt;/span&gt;0:norm&lt;span class="o"&gt;=&lt;/span&gt;pal:width&lt;span class="o"&gt;=&lt;/span&gt;640:height&lt;span class="o"&gt;=&lt;/span&gt;480:device&lt;span class="o"&gt;=&lt;/span&gt;/dev/video0:&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;freq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;775.25:adevice&lt;span class="o"&gt;=&lt;/span&gt;/dev/dsp1:forceaudio:audiorate&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;32000&lt;/span&gt; &lt;span class="nv"&gt;buffersize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64&lt;span class="se"&gt;\&lt;/span&gt;
 -ovc lavc -lavcopts &lt;span class="nv"&gt;vcodec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mpeg4:vbitrate&lt;span class="o"&gt;=&lt;/span&gt;400:keyint&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt; -oac mp3lame&lt;span class="se"&gt;\&lt;/span&gt;
-lameopts &lt;span class="nv"&gt;br&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;32:cbr:mode&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; -ffourcc divx -o &lt;span class="s2"&gt;&amp;quot;test.avi&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To use &lt;strong&gt;mplayer to view &lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/strong&gt; directly (without using tvtime),do&amp;nbsp;this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mplayer tv:// -tv driver=v4l2:input=0:norm=pal:width=640:height=480:device=/dev/video0:
freq=775.25:adevice=/dev/dsp1:forceaudio:audiorate=32000
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I&amp;#8217;ve been using this card without a glitch and recommend for &lt;span class="caps"&gt;HTPC&lt;/span&gt;
attempts on&amp;nbsp;Linux.&lt;/p&gt;</summary><category term="home theatre pc"></category><category term="HTPC"></category><category term="linux"></category><category term="mencoder"></category><category term="pinnacle pctv 50i"></category><category term="television"></category><category term="tv tuner card"></category><category term="tvtime"></category></entry><entry><title>All NCERT text books!</title><link href="http://blog.prashanthellina.com/all-ncert-text-books.html" rel="alternate"></link><updated>2008-02-06T21:01:00-08:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-02-06:all-ncert-text-books.html</id><summary type="html">&lt;p&gt;I recently came to know that
&lt;a href="http://en.wikipedia.org/wiki/National_Council_of_Educational_Research_and_Training"&gt;&lt;span class="caps"&gt;NCERT&lt;/span&gt;&lt;/a&gt;
was providing all the text books (class 1 - 12) for
&lt;a href="http://ncert.nic.in/textbooks/backup/Index.htm"&gt;download&lt;/a&gt;. However, I
found their interface hard to use for browsing through. So I wrote a
crawler in python to get all the books to my&amp;nbsp;webserver.&lt;/p&gt;
&lt;p&gt;Along with storing the books, I generated thumbnails for every chapter.
Navigation pages have also been generated to help browse through the
books easily. You can access this dump
&lt;a href="http://ncertbooks.prashanthellina.com"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ncertbooks.prashanthellina.com"&gt;ncertbooks.prashanthellina.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The crawler code is
&lt;a href="http://code.prashanthellina.com/code/ncert_books_crawler/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are the steps to run it&amp;nbsp;yourself.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# scrape ncert site to get details about book pdf urls&lt;/span&gt;
python get_ncert_books_data.py &amp;gt; ncert_books_data

&lt;span class="c"&gt;# create a directory to store all downloaded files&lt;/span&gt;
mkdir ncert_books

&lt;span class="c"&gt;# download all the pdfs and cover page images&lt;/span&gt;
cat ncert_books_data &lt;span class="p"&gt;|&lt;/span&gt; python download_ncert_books.py ncert_books

&lt;span class="c"&gt;# generate thumbnails for each pdf (requires ImageMagick)&lt;/span&gt;
find ncert_books/ -iname &lt;span class="s2"&gt;&amp;quot;*.pdf&amp;quot;&lt;/span&gt; &amp;gt; all_pdf_files
sed -i &lt;span class="s2"&gt;&amp;quot;s/^/0\t/&amp;quot;&lt;/span&gt; all_pdf_files
python generate_thumbnails.py

&lt;span class="c"&gt;# resize the book cover images&lt;/span&gt;
python resize_image_thumbnails.py ncert_books

&lt;span class="c"&gt;# generate the navigation pages&lt;/span&gt;
python generate_navigation_pages.py ncert_books
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For the thumbnail generation to work, you will need ImageMagick. Read
&lt;a href="/2008/02/03/create-pdf-thumbnails-using-imagemagick-on-linux/"&gt;this&lt;/a&gt;
for more&amp;nbsp;information.&lt;/p&gt;</summary><category term="crawler"></category><category term="ncert"></category><category term="python"></category><category term="textbooks"></category></entry><entry><title>FOSSConf08 - A disappointment</title><link href="http://blog.prashanthellina.com/fossconf08-a-dissapointment.html" rel="alternate"></link><updated>2008-02-03T14:22:00-08:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-02-03:fossconf08-a-dissapointment.html</id><summary type="html">&lt;p&gt;I gave a talk at &lt;a href="http://www.fossconf.in/"&gt;FOSSConf08&lt;/a&gt; yesterday and
came away feeling very disappointed and let down! It was a poorly
organized event where total chaos prevailed. My friend
&lt;a href="http://justmoved.in"&gt;Venkat&lt;/a&gt; and I found ourselves unable to show our
presentation slides because of an overheating projector whose brightness
could not out-match the sunlight coming in from the open&amp;nbsp;windows!&lt;/p&gt;
&lt;p&gt;Venkat&amp;#8217;s talk got delayed by nearly 30 minutes because the machine
provided to him was ancient running a version of Fedora which could not
automount the &lt;span class="caps"&gt;USB&lt;/span&gt; drive he&amp;nbsp;had.&lt;/p&gt;
&lt;p&gt;The only thing we were happy about was the audience who patiently
listened to chalk screeching on the&amp;nbsp;blackboard!&lt;/p&gt;
&lt;p&gt;To any of you out there organizing a conference, here is a piece of&amp;nbsp;advice,&lt;/p&gt;
&lt;p&gt;The contributors spend their time and money visiting such events to
interact with fellow enthusiasts. The least, you, as an organizer can do
is to make sure everything is smooth and taken care of. I am not saying,
you should bear the travel expenses etc. Just make sure something as
basic as a projector&amp;nbsp;works!&lt;/p&gt;
&lt;p&gt;Here is my &lt;a href="{filename}/docs/interesting_ways_of_using_wikipedia_data.pdf"&gt;poor
presentation&lt;/a&gt;
which did not see the light of the day&amp;nbsp;:)&lt;/p&gt;</summary><category term="conference"></category><category term="event"></category><category term="experience"></category><category term="fossconf"></category><category term="presentation"></category></entry><entry><title>Create PDF thumbnails using ImageMagick on Linux</title><link href="http://blog.prashanthellina.com/create-pdf-thumbnails-using-imagemagick-on-linux.html" rel="alternate"></link><updated>2008-02-03T13:59:00-08:00</updated><author><name>prashanthellina</name></author><id>tag:blog.prashanthellina.com,2008-02-03:create-pdf-thumbnails-using-imagemagick-on-linux.html</id><summary type="html">&lt;p&gt;&lt;img alt="imagemagick
logo" src="http://blog.prashanthellina.com/images/imagemagick_logo.jpg" /&gt;I have
a bunch of &lt;span class="caps"&gt;PDF&lt;/span&gt; files for which I wanted to generate thumbnails. On
looking around a bit, I found
&amp;#8220;&lt;a href="http://www.imagemagick.org"&gt;ImageMagick&lt;/a&gt;&amp;#8220;. Since I have Ubuntu
installed, I&amp;nbsp;did&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install imagemagick
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It is not too big a download at around &lt;span class="caps"&gt;740KB&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;To create a thumbnails for all pages in the &lt;span class="caps"&gt;PDF&lt;/span&gt; document (say test.pdf
which has 3 pages),&amp;nbsp;do&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;convert -thumbnail x300 test.pdf test.png
ls
test.pdf &lt;span class="nb"&gt;test&lt;/span&gt;-0.png &lt;span class="nb"&gt;test&lt;/span&gt;-1.png &lt;span class="nb"&gt;test&lt;/span&gt;-2.png
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The &amp;#8220;x300&amp;#8221; tells the &amp;#8220;convert&amp;#8221; tool to keep the height at 300 pixels and
modify the width to suit the height. If you have absolute dimensions in
mind (say 400x300),&amp;nbsp;do&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;convert -thumbnail 400x300 test.pdf test.png
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you want to control the width and have the height suited,&amp;nbsp;do&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;convert -thumbnail &lt;span class="m"&gt;400&lt;/span&gt; test.pdf test.png
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;What do you do if you want only the first page&amp;#8217;s thumbnail?&amp;nbsp;do,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;convert -thumbnail x300 test.pdf&lt;span class="o"&gt;[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt; test.png
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;A neat feature of the &amp;#8220;convert&amp;#8221; tool is creation of animated gif&amp;#8217;s
having all the pages from the &lt;span class="caps"&gt;PDF&lt;/span&gt; document.&amp;nbsp;do,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;convert -thumbnail x300 test.pdf test.gif
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;convert&amp;#8221; is smart enough to figure out the output format from the file
extension you provide in the&amp;nbsp;arguments.&lt;/p&gt;
&lt;p&gt;Nifty tools like &amp;#8220;convert&amp;#8221; from the ImageMagick suite are one of the
reasons I love Linux! (ImageMagick is cross-platform, I&amp;#8217;m referring the
to utility of command-line tools and the &lt;span class="caps"&gt;UNIX&lt;/span&gt; philosophy of specialized
tools that do one task really&amp;nbsp;well)&lt;/p&gt;</summary><category term="graphics"></category><category term="imagemagick"></category><category term="linux"></category><category term="thumbnails"></category><category term="tools"></category></entry></feed>