using the os module

2010 February 1
by pythonisms

nice and simple, takes a little bit of fiddling to ‘get’ os.walk() it returns a 3-tuple which we’ll call x,y,z: x is the current folder, y a list of all subfolders within x and z a list of all files in x, so for each folder you iterate through the mp3 tracks adding each to a playlist which is just a text file with the name (and path if necessary) of each track, this file is written to the current folder.. done ! I have a lot of music so this saved me a good amount of time.

# make playlist for each subfolder in My Music

import os
a=r'C:\Documents and Settings\Luke\My Documents\My Music'

for x,y,z in os.walk(a):
    q=open(x+chr(92)+'a.m3u','w')
    for song in z:
         if song[-1]=='3':
              q.write(song+'\n')
    q.close()

Quicksort

2010 January 28
by pythonisms

Is recursion really profound ? I want to learn Lisp to find out. In the meantime here is a piece of code that rightly belongs in an undergraduate Algorithms course, one of which, I hasten to point out, I have never taken. It’s good practice to work out these algorithms yourself starting from a hint.

Of course if we confine ourselves to the high level functions already available in Python we never need to know how it’s done. Is lazily calling a sort() function bad karma ? It depends how deep you want to go.

I had a friend who was obsessed with climbing the chalk cliffs near where he lived as a boy. He has never been to Everest but I know he’s a better climber than me, probably since he always had something close by to practice on !

Do all the work yourself. Rediscovery is still discovery, you just aren’t the first. Let’s use what comes to hand and develop our coding muscles until they are bulging !

Then why the heck am I telling you the answer immediately then ? Maybe I should declare a spoiler below. OK but what’s the puzzle ?

“Write an algorithm to sort a set of numbers by recursively taking a value from the list and dividing the list into two parts, one where each value is greater, and one where each is less than the selected value.”

Is that too general ? Sorry.

++ spoiler below ++

def quick(a):
    x=len(a)
    if x<=1:
        return a
    left=[]
    right =[]
    pivot = a.pop()
    for z in a:
        if z<=pivot:
            left.append(z)
        else:
            right.append(z)
    return quick(left)+[pivot]+quick(right)

a=[1,5,2,4,3,6,7,8,10,9]

print (quick(a))
>>>
[1,2,3,4,5,6,7,8,9,10]
>>>

other methods of sorting – insertion sort

2010 January 26
by pythonisms

In some ways this sort is similar to Gnome Sort, and I may have to go back on my previous words since it is shorter in Python too. “a” is a list of numbers.

for x in range(len(a)):
    key=a[x]
    i=x-1
    while i>=0 and a[i]>key:
        a[i+1]=a[i]
        i-=1
    a[i+1]=key

a very simple sort algorithm

2010 January 26

I love Gnome sort. It is probably the shortest code for a sort algorithm there is. This is usually expressed by saying it has “low space complexity”.

Start at the beginning of a list and move one to the right. If the left adjacent value is less than the current value then move one to the right, if it is more then swap the two and move one to the left, repeat until you reach the end of the list. That’s it. In a world of information overload, simplicity is what nourishes the coder’s soul.

# gnome-sort.py

def gnome(a):
    """very simple sort"""
    x=0
    while x<len(a):
        if a[x]>a[x-1] or x==0:
            x+=1
        else:
            a[x-1],a[x]=a[x],a[x-1]
            x-=1
    return a

z=[1,3,2,5,4,6,8,9,7]

print (gnome(z))

>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>

self-descriptive numbers

2010 January 17

Here is a puzzle I saw in a Martin Gardner book. We want to find a number that satisfies the following condition. for each of the digits 0-9 we make a box. each digit of the target number must be the number of occurences of the digit above the box.

+++++ Warning : Spoilers Below +++++

We might observe that the sum of the digits of the number must be 10. So what about using a function that returns the integer partitions of 10. ok fine then you’d need a function that filled the blanks in with zeros. This would give you a 10 digit number string, and then you could obtain all the permutations of the string and test each for whether it satisfied the condition that each digit represented the number of occurences of the column digit.

The permutations function will yield some duplicates so its output is converted to a Python set. This is very brute forcey and takes quite a while to find the answer, which is 6210001000 by the way. You can run the same problem in other bases, see this

OEIS page

Here’s some code as a starting point, please comment or help us improve it…

def sel(x):
    """checks whether a given number
    (as string) is self descriptive"""
    tot=0
    for z in x:
        if x.count(z)==int(x[int(z)]):
            tot+=1
    if tot==len(x):
        return True
    else:
        return False

def dig(x):
    q=''
    """takes tuple and converts to string
    then prepends zeros to string"""
    for z in x:
        q+=str(z)
    add=''
    for i in range(10-len(q)):
        add+='0'
    return add+q

def partitions(n):
    """partitions of an integer"""
    if n == 0:
        yield []
        return
    for p in partitions(n-1):
        yield [1] + p
        if p and (len(p) < 2 or p[1] > p[0]):
            yield [p[0] + 1] + p[1:]

def perm(a):
    """permutations of a string of characters"""
   if len(a)==1:
      yield a
   else:
      for i in range(len(a)):
         this = a[i]
         rest = a[:i] + a[i+1:]
         for p in perm(rest):
            yield this + p

for x in partitions(10):
    for y in set(perm(dig(x))):
        if sel(y):
            print(y)
            break
            break

obscure facts #5

2010 January 12
by pythonisms

>>> sum([int(x) for x in '4913'])**3
4913
>>>

encapsulation of numerical esoterica #4

2010 January 12

>>> str(2178*4)[::-1]
'2178'
>>>

terse code illustrating math facts #3

2010 January 12

>>> import itertools
>>> sum([int(a+b) for a,b in itertools.permutations('1782',2)])*3
1782
>>>

MP3 ID tags

2010 January 8
by pythonisms

The ID tag of an MP3 file resides in the last 128 bytes of the file. This code displays all the tags in your collection neatly. Operations such as changing the tags and rationalising or standardising the data in them could be easily added.

If you don’t want to do it yourself you could use the program at http://www.mp3tag.de/en/ to do this. It works quite well although I had a fair amount of mousework along the way. It queries a range of music databases and find tags for you automagically without you having to enter much information. The databases are Amazon, discogs, freedb and MusicBrainz.

I might write some code that does the querying later.

import os

def gettag(songname):
    """returns id tag of an mp3 track""" 
    if songname[-3:]=='mp3':
        try:
            a=open(songname,'rb')
            a.seek(-128,2)
            tag=a.read()
        except IOError:
            tag=''
            pass
        a.close()
        return tag
    else:
        return "not an mp3"

# specify a path to look for music in

songpath=r'H:\music'

# go through songs in every subfolder printing out their tags
# formatted neatly

for x,y,z in os.walk(songpath):
    for name in z:
        if name[-3:]=='mp3':
            tag=gettag(x+chr(92)+name)
            print ('filename:  '+ name)
            print ('title:  '+ tag[3:33])
            print ('artist:  '+ tag[33:63])
            print ('album:  '+ tag[63:93])
            print ('year:  '+ tag[93:97])
            print ('comment:  '+ tag[97:126])
            print ('genre:  '+ tag[126:128])
            print ()

    

two liner

2010 January 2
by pythonisms

>>> def fac(x): return 1 if x<1 else x*fac(x-1)
>>> sum([fac(int(x)) for x in '40585'])
40585
>>>