## martedì 24 maggio 2011

### A method to exchange keys and values in a python dictionary

Around the web i've found this method to exchange keys and values in a python dictionary:

the_dict = { 'a': 1, 'b': 2, 'c': 3 }
inverted_dict = dict(zip(*zip(*the_dict.items())[::-1]))

output:
{ 1:'a', 2:'b', 3:'c' }

it is nice isn't it?
but how does it work?
The main idea is to split keys and values in a list of two n-tuples $$[ (k_1,...,k_n) , (v_1,...,v_n)] ,$$
switch the tuples and re-create a dictionary.

ingredients are:
1 - operator * (also known as 'splat' operator) that is able to unpack a list
2 - zip function that returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterable
3 - a_list[::-1] to revert a_list

We can unpack the algorithm in those 5 nested steps:
a - the_dict.items()
b - zip(*the_dict.items())
c - zip(*the_dict.items())[::-1]
d - zip(*zip(*the_dict.items())[::-1])
e - dict(zip(*zip(*the_dict.items())[::-1]))

a - with the_dict.items() we obtain:
[('a', 1), ('b', 2), ('c', 3)]
b - then, using * operator in the zip function:
zip(*the_dict.items())
we are doing:
zip(('a', 1), ('b', 2), ('c', 3) )
obtaining:
[('a', 'b', 'c'), (1, 2, 3)]

c - with [::-1] we actually switch key and values
zip(*the_dict.items())[::-1] = [('a', 'b', 'c'), (1, 2, 3)][::-1]
=
[('a', 'b', 'c'), (1, 2, 3)]

d - with the second zip * pair we re-unpack the list to recreate the 3 pairs:
zip(*zip(*the_dict.items())[::-1]) =
zip(*[('a', 'b', 'c'), (1, 2, 3)]) =zip(('a', 'b', 'c'), (1, 2, 3) )
=
[('a', 1), ('b', 2), ('c', 3)]

e - now our new dict is almost cooked, we use dict() function to complete the opera:
dict(zip(*zip(*the_dict.items())[::-1]))
=
dict ([('a', 1), ('b', 2), ('c', 3)])
the output:
{ 1:'a', 2:'b', 3:'c' }
all this stuff in 1 row.

## lunedì 23 maggio 2011

### Happy numbers in python

I'll show you a method in python to check if a number is happy.
When a number is happy? Well, you have to follow this algorithm:

1. Take a number n.
n = 23
2. Dissect it into digits.
2 and 3
3. Square them all and add them up
2^ 2 + 3 ^ 2 = 4 + 9 = 13
4. You get a new number m.
m = 13
5. If m = 1, n is happy; otherwise set n = m and repeat at 1.
1^2 + 3^2 = 1 + 9 = 10
n = 10
1 ^ 2 + 0 ^ 2 = 1
23 is happy!
6. If you run into a loop, n is not a happy number (is sad).

I've used recursion because it is fun (talking about happy numbers).

def happy(n, past = set()):
m = sum(int(i)**2 for i in str(n))
if m == 1:
return True
if m in past:
return False
return happy(m,past)

print [ x for x in range(1,100) if happy(x, set())]

Here 'past' is a set, needed to check if we are in a loop.
The output shows the set of happy numbers below 100.

[1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97]

## giovedì 19 maggio 2011

### logistic map in python

Simple logistic map using python and matplotlib.

import math
import matplotlib.pyplot as plt

def logistic(xa =2.9 , xb=4.0 , imgx = 240 , imgy = 500,
maxit = 200, f=lambda x,r: r * x * (1 - x) ):
xs = []
ys = []
for i in range(imgx):
r = xa + (xb - xa) * float(i)/(imgx - 1)
x = 0.5
for j in range(maxit):
x = f(x,r)
if j > maxit / 2:
xs.append( i )
ys.append(int(x * imgy))
return [xs,ys]

myfunction = lambda x,r: r * (math.sin(x)**2)
points = logistic( xa = 2.1 ,xb = 3.1, imgy=200 , f=myfunction)
ax = plt.subplot(121)
ax.scatter(points[0], points[1], s= 1)

points = logistic()
bx = plt.subplot(122)
bx.scatter(points[0], points[1], s= 1)
plt.show()