apillai's posterous

apillai's posterous

Mar 21 / 9:41am

Rescuing a little bat

20032010045

It was my 4 year old daughter who spotted the strange black "object"
on the balcony floor in the evening. She did not know what to make out
of it, so she asked me to look, and at first sight, I mistook it to be
a large hairy spider. Guess what ! It turned out to be a tiny bat !

The poor bat, hardly 3 inches long, tired and exhausted from the
summer heat was barely alive. I proffered some water from a tiny
spoon, which was gladly taken, albeit with a lot of difficulty. After
a round of refreshments, I carried it in a sheet of paper, but the bat
preferred to sit in my palm. After a while, it started grooming itself
and later, calling out for its friends (I guess this latter part,
since it seemed to do so, I definitely could not hear anything).

Finally, after about 45 minutes of taking rest, refreshments and
grooming, the little bat spread its wings, fluttered around the room,
and took off into the evening sky. We watched it fly around for a few
minutes before it disappeared into the darkness.

Dec 13 / 10:11pm

Solver for a 3x3 tictactoe board

I saw this puzzle, supposedly credited as an interview question asked by Google:  How would you find a winner in a tic-tac-toe board of arbitrary size ?

Let us see how we can check if a 3x3 tic-tac-toe board has a valid winner. A convenient representation of a square board like (I) is a sequence like (II), organized as row major mode. To see if there is a winner, we need to find the expected pattern 'XXX' or 'OOO' in a row, column or diagonal. So the real work is in partitioning the space into rows, columns and diagonals.



"""


    -------------  
    | 0 | 1 | 2 |
    -------------           -------------------------------------
    | 3 | 4 | 5 |   ==>     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 
    -------------           -------------------------------------
    | 6 | 7 | 8 |                              (II) 
    -------------

        (I)


"""


Let us start with defining a couple of convenience variables: (a) span = 3, which is the length of the edge of the square / board, (b) length = 9, which is the length of the sequence (= span*span)  and (c) pos, which is the current position.

Getting rows is straight-forward: start from top-left corner and iterate over each element until a distance of span has been covered. Getting the columns requires traveling in step = span from the starting position. For example, if start is element at (0,1), which is pos = 1 itself, the next element in column-major traversal is (1,1) for which pos = (pos + span). Effectively, we always travel in distances of 'span' to the next
element in the column. Diagonal traversing requires us to start at a corner. If we start at top-left corner (0,0), which is pos = 0, the next diagonal element is pos + (span+1), the (+1) giving that diagonal movement (otherwise it would be a column-traversal). Similarly, if we start from bottom left corner (3,0) = position 6, which is pos = (length-span), the next element is at pos - (span-1) = 4. In short, we travel a positive step of (span+1) from top-left and negative step of (span-1) from bottom left to find next diagonal element. Iterations are limited to 'span' number of times. The algorithm should work neatly for any length which is a perfect square.

Now, to writing some code to do this elegantly. In typical C style, getting rows, columns and diagonals would look like this:

/* this is not compile clean C... */
int rows[length], columns[length], diagonals[2*span];

int i, j, k; k = 0;
for (i = 0; i < length; i += span)
    for (j = 0; j < span, ++j) 
    {
        rows[k] = i + j;
        ++k; 
    }

k = 0;
for (i = 0; i < span, ++i) 
    for (j = 0; j < length; j += span)
    {
        columns[k] = i + j;
        ++k; 
    }

k = 0;
for (i = 0; i < length; i += span+1)
    diagonals[k] = i;
for (i = length-span; i > 0; i -= (span-1) )
    diagonals[k] = i;


The loops are already getting unwieldy and I do not think code to check if a row has pattern 'XXX' is going to be any better with strcmp() and the likes. Attempting to use Python, I stumbled across a couple of nifty features: the function range(), which allows you to step in specific increments across a range, up or down, and list comprehension, a functional programming paradigm to apply filters on a given list of objects. For example, our sequence can be constructed with a single call to range(), and we can produce a list of all even numbers in the sequence, with a list comprehension. List comprehensions should be read from right to left: in this case for i in range(...), make a list containing sequence[i]

 
>>> length = 9
>>> sequence = range(length)
>>> print sequence
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> print [sequence[i] for i in range(0, length, 2)]
[0, 2, 4, 6, 8]
>>> 

With these features, the code becomes ridiculously simple and intiuitive:



import math


sequence_ = range(9)
length = len(sequence_)
span   = int(math.sqrt(length))

# read list comprehensions from right to left...

rows = [[sequence_[i+j] for j in range(span)] for i in range(0, length, span)]
print "rows:         ",rows

columns = [[sequence_[i+j] for j in range(0, length, span)] for i in range(span)]
print "columns:      ",columns


diagonals = [[sequence_[i] for i in range(0, length, span+1)], 
             [sequence_[i] for i in range(length-span, 0, -(span-1))]]
print "diagonals:    ", diagonals

The output looks like this:

rows:          [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
columns:       [[0, 3, 6], [1, 4, 7], [2, 5, 8]]
diagonals:     [[0, 4, 8], [6, 4, 2]]

So, given a tic-tac-toe as a sequence of characters such as 'XXOXXXXOO', it is trivial to partition them into rows, columns and diagonals. But wait ! it would have been easy to compare each row, column or diagonal against possible winning patterns 'XXX' and 'OOO'

Python gives us yet another feature: join() elements of a list into a string, if elements are either characters or strings. In quintessential Python style, '' is an empty string, and join() can be called on any string type, which means, all elements in the iterable type (sequence which is a list in this case) will be concatenated into a single string !

>>> sequence = [str(i) for i in range(9)] # list of strings containing numbers 0 - 9
>>> print sequence
['0', '1', '2', '3', '4', '5', '6', '7', '8']
>>> print [''.join([sequence_[i+j] for j in range(span)]) for i in range(0, length, span)] 
[ '012', '345', '678' ] 

If we generate a single list called partitions that has the rows, columns and diagonals - use extend() method of list - solving a tic-tac-toe board is then as simple as:

pattern_x, pattern_y = 'XXX', 'OOO'
if pattern_x in partitions:
    winner = 'X'
else if pattern_y in partitions:
    winner = 'O'
else:
    winner = None

Now, that was a simple and elegant solution in a few lines of intuitive code...

Filed under  //  programming   python  
Aug 13 / 1:33pm

No access / slow loading / timeout of Linkedin

I have been experiencing slow response (initially), and more recently, timeout while attempting to connect to Linkedin from home (Dell Inspiron 1420 running Ubuntu Hardy Heron 8.04, Firefox 3.1x or 3.5x, with D-Link 2640T ADSL/Wi-Fi combo modem/router. Apparently, there was no problem connecting with the office VPN, or through a proxy (e.g. www.tntproxy.com), but then Javascript is disabled with a proxy access --> I cannot update the profile or manage contacts.

I finally fixed the problem with the material discussed in:
http://marzoa.com/2009/03/08/d-link-dsl-g624t-and-linkedincom
https://bugs.launchpad.net/ubuntu/+source/network-manager/+bug/314713.

The ADSL default configuration for PPPoE is MTU (Maximum Transmission Unit) at 1400 and MRU (Maximum Receive Unit) at 1492. (I have Airtel 512 kbps DSL connection) Changing this to match the eth0 MTU default value of 1500 on the DSL modem did no good - apparently the modem cannot handle MTU = 1500. So, I tried the two steps to remove the iptables FORWARD and change the eth0 MTU:

(a) Delete the iptables rule as described from the router. I too had the offending line in position 1

iptables -D FORWARD 1

(b) Reset MTU on the machine (interface eth0 in my case)

sudo ifconfig eth0 mtu 1400

The MTU value is 1400 since TCPMSS is set to 1360 in the router. (Note: TCPMSS = 1400 - 40 = 1360)

Naturally, it is not a stable fix: I have to telnet to my modem, reset the iptables each time, but something is better than nothing... Next step: Try to upgrade router firmware and pray it does not screw things up any further ;-)

Filed under  //  tech  
Aug 1 / 12:36pm

More fun with ffmpeg...

The standard ffmpeg installed with Ubuntu does not have libmp3lame for mp3 encoding. Paul Maunders describes how to install ffmpeg with libmp3lame support from the Medibuntu distribution. Now it is easy to rip mp3 off a flash video file in either of the following ways:
ffmpeg -i some.flv -acodec mp3 some.mp3ffmpeg -i some.flv -vn -acodec copy some.mp3

Here is the output from my machine:
apillai@giraffe:~/Videos/$ ffmpeg -i some.flv -vn -acodec copy some.mp3FFmpeg version SVN-rUNKNOWN, Copyright (c) 2000-2007 Fabrice Bellard, et al.  configuration: --enable-gpl --enable-pp --enable-swscaler --enable-pthreads --enable-libvorbis --enable-libtheora --enable-libogg --enable-libgsm --enable-dc1394 --disable-debug --enable-libmp3lame --enable-libfaadbin --enable-libfaad --enable-libfaac --enable-xvid --enable-x264 --enable-liba52 --enable-amr_nb --enable-amr_wb --enable-shared --prefix=/usr  libavutil version: 1d.49.3.0  libavcodec version: 1d.51.38.0  libavformat version: 1d.51.10.0  built on Mar 17 2009 21:37:49, gcc: 4.2.4 (Ubuntu 4.2.4-1ubuntu3)Seems stream 0 codec frame rate differs from container frame rate: 1000.00 (1000/1) -> 29.97 (30000/1001)Input #0, flv, from 'some.flv':  Duration: 00:04:43.9, start: 0.000000, bitrate: 64 kb/s  Stream #0.0: Video: flv, yuv420p, 320x240, 29.97 fps(r)  Stream #0.1: Audio: mp3, 22050 Hz, mono, 64 kb/sOutput #0, mp2, to 'some.mp3':  Stream #0.0: Audio: mp3, 22050 Hz, mono, 64 kb/s    <=== mp3 streamStream mapping:  Stream #0.1 -> #0.0Press [q] to stop encodingsize=    2219kB time=284.0 bitrate=  64.0kbits/s  video:0kB audio:2219kB global headers:0kB muxing overhead 0.000000%apillai@giraffe:~/Videos/$

Now we have a clean mp3 that can be played on your ipod! Tux Radar has a nice write up on ffmpeg tips and tricks.
Filed under  //  tech  
Jun 17 / 12:56pm

Holy crap !

Here is an extract from a recent post by Uncle Bob in the ObjectMentor Blog:

"CRAP is a metric that is applied to each function in the system. The formula for CRAP is: CRAP = comp(f)2. X (1 – cov(f)/100)3. + comp(f), Where comp(f) = the cyclomatic complexity of the function f. and cov(f) = the unit test coverage of function f. So a function’s CRAP will be small iff the cyclomatic complexity is low and the test coverage is high. CRAP will be huge if cyclomatic complexity is high, and there is no coverage."

They even have a tool available for measuring this: crap4j ! Take a look at that sample report ! Holy crap ! What a change from the dry formality of percentage of dead code, fault density and so on... A follow-up post is here.

Filed under  //  opinions   programming  
Jun 14 / 9:31am

The twp (thin wallet program)

I started an active intent to reduce the size of my wallet around the New Year. My wallet was becoming a dumpyard of transaction slips, cash, coins a few credit / debit cards, assorted visiting cards and what not... After all, size zero is so much in vogue these days and I didn't see why I should not cut the wallet to size first.

So I sat down and looked at what is really essential and came to the following conclusion: At any point of time, a couple of cards, copy of my driving license and some petty cash is fine. Coins are useless - not even beggars accept them these days. Transaction slips can be shunted out every other week; visiting cards can be kept elsewhere.

I purchased a new thin wallet that can hardly accommodate these items (lest I fall prey to stuffing once again) and I have been happy since the last few months. Optimization at times is not so much of an evil...

Filed under  //  opinions  
May 24 / 1:18am

Movie List

I have listed down a few interesting movies I have seen over the last few years. None of them are of the popular genre, nor are they too artistic to leave you with a sinking feeling of "what the hell was that" after the movie is over. UTV world movies has been airing a few of them - for the others you have to search other sources (Youtube ?). More of them, in a later post.

Filed under  //  movies   opinions  
Jan 14 / 5:35am

Free MBTI Online Analysis

There is a comprehensive, yet free online test for Myers-Brigg Type Indicator. For the curious ones, I tend to be somewhere in between an INTJ and INTP.
Filed under  //  thoughts  
Jan 14 / 5:26am

Samsung SCX 4300 on Ubuntu

I bought a Samsung SCX 4300 multifunction device a couple of weeks back. Getting it work with Ubuntu was a little tricky, but thanks to information from Volatile Yard, I got it working completely in a couple of hours. The experiences are listed in Ubuntu Launchpad and in Ubuntu Forums
Filed under  //  linux  
Aug 3 / 2:37pm

Dell Inspiron 1420

I got a new Dell Inspiron 1420 for my personal use and installed Ubuntu to dual boot it with the pre-installed Windows Vista. Installing a Linux distro for dual booting has come a long way since the first time I did it with Slackware and Windows NT - one needed to know the disk geometry, ensure that the partitions were within the first 1GB, tweaking the MBR and and worst, finally hand-tuning the X-Windows setup for a clean resolution. With Ubuntu, it looked like a "fire and forget". Good !

Getting the WiFi connection to work with the DELL 1395 mini-card (Broadcom 4315) needed a little tweak as outlined in http://ubuntuforums.org/showthread.php?t=704088, but it worked perfectly. What surprised me was that the Broadcom 4315 drivers that shipped with laptop for Vista did not work with ndiswrappers.

So far, so good.

Filed under  //  linux