2008-04-08

Functional Python Palindromes

To find all palindromes from a list of words in a file, one word per line, you could write a procedural Python program like this:

for row in file('test.txt'):
  s = row.strip()
  if s == s[::-1]:
    print s

Here's a functional Python version, with notes below:

from itertools import imap
filter(lambda s: s == s[::-1], imap(str.strip, file('test.txt')))
  5       3              4       2               1
  1. Create a file iterator.
  2. When we read a line from a file into a string, the string has a trailing newline character (e.g. 'add\n'). We want to remove that trailing newline character, so we use the itertools.imap() function to create a new iterator that applies the str.strip() to each line read. The result is that we have an iterator that provides strings without the newline character.
  3. Define an anonymous function using lambda keyword that returns true if the input string is a palindrome.
  4. Python idiom for returning a reversed sequence (a string is a sequence of characters).
  5. Use the filter function to return a list of palindromes.

Using this input file …

add
dad
dam
mad
made
madam
set

… the result of running the functional script is:

['dad', 'madam']

2008-04-07

Reading CSV Files in Python

Python has a csv module for reading and writing CSV files (usually exported by Excel or database tables). The basic use of this module is documented in the on-line help. My CSV files usually have a header row, so the idiomatic way to skip this line is to open the CSV file and use the next() function immediately:

from csv import reader
f = open("blah.csv", "rb")
f.next()
for row in reader(f):
  print row

If your CSV files are pretty simple (e.g. only single line data, no quotes, etc.), you can use list comprehension and array slicing:

                   1       2                                      3
for row in [line.strip().split(',') for line in file("blah.csv")][1:]:
  print row

Notes:

  1. You have to remove the trailing "\n" from each line.
  2. Split the input line using the delimiter, typically a comma.
  3. The list comprehension statement returns all lines, so to ignore the first line, you take a slice of the array starting from the second line.

2008-03-19

Poor Man's Which Command For Windows Cmd.exe

The Windows Command Processor (cmd.exe) doesn't seem to have an equivalent to a Unix shell's which command to find the directory in the PATH variable of a given executable. Here's a poor man's version using the for command:

>for /F %i in ("notepad.exe") do @echo %~$PATH:i
C:\WINDOWS\system32\notepad.exe
>for /F %i in ("gawk.exe") do @echo %~$PATH:i
C:\Program Files\GnuWin32\bin\gawk.exe

20-Mar-2008: Added as a macro using doskey:

>doskey which=for %i in ("$1") do @echo %~$PATH:i

2008-03-15

Making ID Photos with GIMP

You can make ID photos cheaply using GIMP:

  1. Take a head-and-shoulders picture with your digital camera.
  2. Load or paste the image into GIMP.
  3. Rotate the image, if necessary, to a portrait orientation using menu item Image / Transform / Rotate 90 ….
  4. Shrink the image to one quarter the original size using menu item Image / Scale Image. You have to calculate the required pixel size because the Scale Image doesn't have a "shrink by half" function.
  5. Create a new image with the dimensions of the original image, in landscape orientation.
  6. Select menu item Image / Configure Grid and set the spacing so that it matches the size of your shrunk image. The idea is to have a grid as per ASCII art below:
    +--+--+--+--+
    |  |  |  |  |
    +--+--+--+--+
    |  |  |  |  |
    +--+--+--+--+
    
  7. Select menu item View / Snap to Grid and View / Show Grid.
  8. Copy and paste your shrunk image into the new image. You should be able to fit 8 images in one picture. Use the grid to help you position the images in each cell. Positioning all images in the grid's cells also makes it easier to cut the photos after they have been printed.

My camera takes 3072 x 2304 pixel images (or 6:4.5 ratio), so if I use 15cm x 10cm (6:4 ratio) paper, the images on the left and right edges would be cropped unless I further shrink the images by 5%.