I Might Be Wrong

Computing permutations with a recursive generator expression

Posted in Python by Leif Ryge on October 21, 2008
#!/usr/bin/python2.5
def permute(li):
    """Generate all permutations of a sequence
    >>> for i in permute([1,2,3]): print i
    (1, 2, 3)
    (1, 3, 2)
    (2, 1, 3)
    (2, 3, 1)
    (3, 1, 2)
    (3, 2, 1)"""
    return ((i,)+j for i in li for j in (permute([k for k in li if k is not i])
                                         if len(li) > 1 else [()] ) )

import doctest
doctest.testmod(verbose=True)

LCARS 4.2 released

Posted in Maemo by Leif Ryge on September 23, 2008

Here is another photo and a screenshot of our new theme, Okuda:

 

The changelog has details on what else is new. To install or upgrade, just use this .install file. After installing, select a theme and a background and then reboot for everything to be properly reloaded.

The install process is unfortunately rather slow, usually taking between 1 and 3 minutes, due to the numerous cache files which must be updated post-install. Starting with this release, the themes’ postinst scripts now run gtk-update-icon-cache on the icon themes’ directories, and lcars-extras runs it on the hicolor icon theme in postinst and postrm. The Okuda theme includes a font, so it runs fc-cache. And, as before, all of the themes run hildon-theme-cacher (which is the slowest of the three types of cache). I’m not sure why hildon-theme-cacher needs to be run on the device; it seems like it would make more sense (and be quicker for users) to pre-generate those gtkrc cache files as part of the themes’ build process. Oh well.

Enjoy the new themes, and please let us know if you make modified versions! :)

Tagged with: , , , ,

Preview of our new Maemo theme

Posted in Maemo, Python by Leif Ryge on September 21, 2008

Ian and I have been working on a new release of our LCARS packages, featuring a number of bug fixes as well as a new theme called “Okuda”:
"Okuda" theme running on N810

If all goes well, we should be ready to release this within the next 48 hours. All four of our themes now include icon templates, which we’re slicing with hildon-theme-slicer (the same way that the main theme template is processed). This is what the icon template for the Okuda theme looks like:
icon_template.png
Anyone else wishing to create a hildon-theme-tools (and ThemeMaker) compatible layout definition might find this Python script helpful:

#!/usr/bin/python2.5
"""Generate a hildon-theme-tools layout from variously sized images.
Edit script to specify desired margin, width, and origin (dx,dy).
usage: hildon-theme-layout-grid-generator.py `find icons|sort|grep png`
"""

__author__ = "Leif Ryge <leif @synthesize.us>"
__license__ = "no rights reserved / public domain"

from sys import argv
from PIL import Image

margin, width, dx,dy = 10, 600, 0,0 # margin, output width, starting coords
sizes = {}

for f in argv[1:]: sizes.setdefault(Image.open(f).size,[]).append(f)

print "[Main]\nTemplateWidth=%s\nTemplateHeight=%s\n\n[Elements]" % (width, \
    sum((h+margin)*(len(sizes[w,h])/(width/(w+margin))+1) for w,h in sizes) )

for w,h in sorted(sizes):
    column = width / (w+margin)
    row = 1 + len(sizes[w,h]) / column
    print "# %s images are %sx%s (%sx%s grid)" % (len(sizes[w,h]),w,h,column,row)
    for i, f in enumerate(sizes[w,h]):
        print "%s=%s,%s,%s,%s" % (f, dx+(i%column)*(w+margin),
                                     dy+(i/column)*(h+margin),w,h)
    dy = dy+row*(h+margin)

The actual template can then be created from existing images using Nokia’s hildon-theme-regenerator tool.

Memoization in one line

Posted in Python by Leif Ryge on August 27, 2008

The memoization decorator in the Python Decorator Library has served me well, but, after reading stupid lambda tricks, I started thinking about how it could be reduced to a single expression. This is the result:

memoize = lambda f: (lambda d={}: lambda *a: d.setdefault(a, a in d or f(*a)))()

Unlike the original, mine doesn’t catch the case of the memoized function being called with unhashable (mutable) arguments. It doesn’t seem like that is a likely scenario, though.

Here is another version which also works with functions taking named arguments:

memo_with_named_args = lambda f: (lambda d={}: lambda *a,**kw: \
    (lambda *k: d.setdefault(k, k in d or f(*a,**kw)))(tuple(kw.items()),a) )()