Second Python User Group meeting

I gave a talk at the second python user group in leeds on Wednesday. It was called “Anatomy Of A Python Program - How Much Can You Do In 0.1 KLOC?”. It is based on Peter Norvigs Sudoku solver. I had been thinking about doing it for WYLUG, possibly as a second talk after an intro to python. The slides were the same, but instead of looking at cool features of python that make the code so concise we critiqued it a bit and spoke about the style and possible speedups. The slides for the talk is here, but as I did not add any notes, you would be better off just reading Norvigs article (though the Javascript slideshow is cool, press t to toggle views)

The slideshow was made using rst2s5 and I am amazed how well it works. Restructuredtext is from Pythons Docutils and is a simple markup language designed to be readable as plain text, see here for details. Below is part of the code for my presentation


==============================================================
Anatomy Of A Python Program - How Much Can You Do In 0.1 KLOC?
==============================================================

:Author: Tom Hall
:Date: 11pm Tues Dec 4th


The Problem - Sudoku
====================

::

   +----------+----------+----------+
   | A1 A2 A3 | A4 A5 A6 | A7 A8 A9 |
   | B1 B2 B3 | B4 B5 B6 | B7 B8 B9 |
   | C1 C2 C3 | C4 C5 C6 | C7 C8 C9 |
   +----------+----------+----------+
   | D1 D2 D3 | D4 D5 D6 | D7 D8 D9 |
   | E1 E2 E3 | E4 E5 E6 | E7 E8 E9 |
   | F1 F2 F3 | F4 F5 F6 | F7 F8 F9 |
   +----------+----------+----------+
   | G1 G2 G3 | G4 G5 G6 | G7 G8 G9 |
   | H1 H2 H3 | H4 H5 H6 | H7 H8 H9 |
   | I1 I2 I3 | I4 I5 I6 | I7 I8 I9 |
   +----------+----------+----------+

Setting The Scene
=================



::

    def cross(A, B):
        return [a+b for a in A for b in B]

    rows = 'ABCDEFGHI'
    cols = '123456789'
    digits   = '123456789'
    squares  = cross(rows, cols)
    unitlist = ([cross(rows, c) for c in cols] +
                [cross(r, cols) for r in rows] +
                [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')])
    units = dict((s, [u for u in unitlist if s in u])
                 for s in squares)
    peers = dict((s, set(s2 for u in units[s] for s2 in u if s2 != s))
                 for s in squares)

Taking in problems
==================

::

    def parse_grid(grid):
        "Given a string of 81 digits (or . or 0 or -), return a dict of {cell:values}"
        grid = [c for c in grid if c in '0.-123456789']
        values = dict((s, digits) for s in squares) ## To start, every square can be any digit
        for s,d in zip(squares, grid):
            if d in digits and not assign(values, s, d):
            return False
        return values

The second talk went a bit over my head but was interesting, a declarative metaclass pattern. The chat after was great, everyone is interesting and excited about similar things to me.

I used Python the next day in work when our FTP server (a crappy windows app that I have disliked all the time I have been here) decided to recreate its password list as a 0 byte file and left us with no FTP. I took the time to do an upgrade to Filezilla and wrote a little python script to create entries in Filezillas xml config for all the users (though I had to manually create a .csv with all the usernames/passwords in). Simple things like this are another reason I like Python, it’s great tool for a SysAdmin to get those annoying little jobs done.

import md5

users = open("usernames.csv","r")
outputxml = open("usernames.xml","w")

usernamestr = """

%s

0
0
0
1

0






1
1
1
1
1
1
1
1
1
0







"""

def md5hash(password): return md5.new( password ).hexdigest()

for line in users.readlines():
    user , password = line.split(",")[0], line.split(",")[1][:-1]
    print user, password
    outputxml.write(usernamestr % (user, md5hash(password), user))

outputxml.close()

Passwords md5 hashed in 1 line and most of these 50 lines are the template for Filezilla. Definitely satisfies the mantra “Simple Things Should Be Simple, Complex Things Should Be Possible”. That the same language can be so applicable right across the complexity spectrum is amazing. I love the learning curve for Python, very smooth and it can take you very far.