diff --git a/source/Collection_Data_Types.rst b/source/Collection_Data_Types.rst
index e9f011aa7a505105321b5aa2db04bf2b4f48d23c..1ba09e1afc7d33a2d5a5cfc989fe9a854d7954ea 100644
--- a/source/Collection_Data_Types.rst
+++ b/source/Collection_Data_Types.rst
@@ -61,6 +61,38 @@ We can observe this using *id()* which give the memory adress of an object. This
    in ``a operator= b`` python looks up ``a`` ’s value only once, so it is potentially faster
    than the ``a = a operator b``.
 
+
+compare ::
+
+   x = 3
+   y = x
+   y += 3
+   x = ?
+   y = ?
+   
+   
+.. figure:: _static/figs/augmented_assignment_int2.png  
+   :width: 400px
+   :alt: augmented_assignment
+   :figclass: align-center 
+
+   
+and ::
+
+   x = [1,2]
+   y = x
+   y += [3,4]
+   x = ?
+   y = ?  
+
+
+.. figure:: _static/figs/augmented_assignment_list2.png  
+   :width: 400px
+   :alt: list extend
+   :figclass: align-center 
+
+
+
 Exercise
 --------
 
@@ -142,15 +174,51 @@ from the list l = [1, 2, 3, 4, 5, 6, 7, 8, 9] generate 2 lists l1 containing all
 Exercise
 --------
    
-generate a list containing all codons. ::
+generate a list containing all codons.
+   
+pseudocode:
+"""""""""""
+
+| *function all_codons()*
+|     *all_codons <- empty list*
+|     *let varying the first base*
+|     *for each first base let varying the second base*
+|     *for each combination first base, second base let varying the third base*
+|     *add the concatenation base 1 base 2 base 3 to all_codons*
+|     *return all_codons*
+
+first implementation:
+"""""""""""""""""""""
+.. literalinclude:: _static/code/codons.py
+   :linenos:
+   :language: python
+
+::
+
+   python -i codons.py 
+   >>> codons = all_codons()
+   
+:download:`codons.py <_static/code/codons.py>` .  
+
+second implementation:
+""""""""""""""""""""""
+
+Mathematically speaking the generation of all codons can be the cartesiens product 
+between 3 vectors 'acgt'. 
+In python there is a function to do that in ``itertools module``: `https://docs.python.org/2/library/itertools.html#itertools.product <product>`_
+
+
+.. literalinclude:: _static/code/codons_itertools.py
+   :linenos:
+   :language: python
+
+::
+
+   python -i codons.py 
+   >>> codons = all_codons()
    
-   bases = 'acgt'
-   codons = []
-      for a in bases:
-         for b in bases:
-            for c in bases:
-               codon = a + b + c
-               codons.append(codon)
+:download:`codons_itertools.py <_static/code/codons_itertools.py>` .
+
                
 Exercise
 --------
@@ -162,175 +230,213 @@ For example: ::
    >>> uniqify(l)
    >>> [1,2,3,5] #is one of the solutions 
 
-solution ::
 
-   >>> list(set(l))
+pseudocode:
+"""""""""""
 
+| *function uniqify(l)*
+|     *uniq <- empty list*
+|     *for each element of l*
+|        *add element if is not in uniq*
+|     *return uniq*
 
-Exercise
---------
+implementation:
+"""""""""""""""
 
-let the following enzymes collection: ::
- 
-   import collections
-   RestrictEnzyme = collections.namedtuple("RestrictEnzyme", "name comment sequence cut end")
+.. literalinclude:: _static/code/uniqify.py
+   :linenos:
+   :language: python
 
-   ecor1 = RestrictEnzyme("EcoRI", "Ecoli restriction enzime I", "gaattc", 1, "sticky")
-   ecor5 = RestrictEnzyme("EcoRV", "Ecoli restriction enzime V", "gatatc", 3, "blunt")
-   bamh1 = RestrictEnzyme("BamHI", "type II restriction endonuclease from Bacillus amyloliquefaciens ", "ggatcc", 1, "sticky")
-   hind3 = RestrictEnzyme("HindIII", "type II site-specific nuclease from Haemophilus influenzae", "aagctt", 1 , "sticky")
-   taq1 = RestrictEnzyme("TaqI", "Thermus aquaticus", "tcga", 1 , "sticky")
-   not1 = RestrictEnzyme("NotI", "Nocardia otitidis", "gcggccgc", 2 , "sticky")
-   sau3a1 = RestrictEnzyme("Sau3aI", "Staphylococcus aureus", "gatc", 0 , "sticky")
-   hae3 = RestrictEnzyme("HaeIII", "Haemophilus aegyptius", "ggcc", 2 , "blunt")
-   sma1 =  RestrictEnzyme("SmaI", "Serratia marcescens", "cccggg", 3 , "blunt")
+::
 
-and the 2 dna fragments: ::
+   >>> l=[1,2,3,2,3,4,5,1,2,3,3,2,7,8,9]
+   >>> uniqify(l)
+   [1, 2, 3, 4, 5, 7, 8, 9]
 
-   dna_1 = """tcgcgcaacgtcgcctacatctcaagattcagcgccgagatccccgggggttgagcgatccccgtcagttggcgtgaattcag
-   cagcagcgcaccccgggcgtagaattccagttgcagataatagctgatttagttaacttggatcacagaagcttccaga
-   ccaccgtatggatcccaacgcactgttacggatccaattcgtacgtttggggtgatttgattcccgctgcctgccagg"""
+:download:`codons_itertools.py <_static/code/codons_itertools.py>` .
 
-   dna_2 = """gagcatgagcggaattctgcatagcgcaagaatgcggccgcttagagcgatgctgccctaaactctatgcagcgggcgtgagg
-   attcagtggcttcagaattcctcccgggagaagctgaatagtgaaacgattgaggtgttgtggtgaaccgagtaag
-   agcagcttaaatcggagagaattccatttactggccagggtaagagttttggtaaatatatagtgatatctggcttg"""
+second implementation:
+""""""""""""""""""""""
 
-| which enzymes cut the dna_1 ?
-|                  the dna_2 ?
-|                  the dna_1 but not the dna_2?
+The problem with the first implementation come from the line 4.
+Remember that the membership operator uses a linear search for list, which can be slow for very large collections.
+If we plan to use ``uniqify`` with large list we should find a better algorithm.
+In the specification we can read that uniqify can work *regardless the order of the resulting list*.
+So we can use the specifycity of set ::
 
-::
+ 
+   >>> list(set(l))
 
-   dna_1 = dna_1.replace('\n', '')
-   dans_2 = dna_2.replace('\n', '')
 
-algorithm 1 ::
+Exercise
+--------
 
-   enzymes = [ecor1, ecor5, bamh1, hind3, taq1, not1, sau3a1, hae3, sma1]
-   digest_1 = []
-   for enz in enzymes:
-      if enz.sequence in dna_1:
-         digest_1.append(enz)
+We need to compute the occurence of all kmers of a given lenght present in a sequence.
 
-algorithm 2 we can determine the position of the site :: 
-   
-   enzymes = [ecor1, ecor5, bamh1, hind3, taq1, not1, sau3a1, hae3, sma1]
-   digest_1 = []
-   for enz in enzymes:
-      pos = dna_1.find(enz.sequence)
-      if pos != -1:
-         digest_1.append(enz)
+Below we propose 2 algorithms. 
 
+pseudo code 1
+"""""""""""""
 
-with these algorithms we find if an enzyme cut the dna but we cannot find all cuts in the dna for an enzyme. ::
+|   *function get_kmer_occurences(seq, kmer_len)*
+|      *all_kmers <- generate all possible kmer of kmer_len*
+|      *occurences <- 0* 
+|      *for each kmer in all_kmers*
+|         *count occurence of kmer*
+|         *store occurence*
+     
+pseudo code 2
+"""""""""""""
+
+|  *function get_kmer_occurences(seq, kmer_len)*
+|     *all_kmers <- empty*
+|     *from i = 0 to sequence length - kmer_len*
+|        *kmer <- kmer startin at pos i im sequence*
+|        *increase by of occurence of kmer*
+ 
 
-   enzymes = [ecor1, ecor5, bamh1, hind3, taq1, not1, sau3a1, hae3, sma1]
-   digest_1 = []
-   for enz in enzymes:
-      print enz.name, dna_1.count(enz.sequence)
+.. note::
 
-the latter algorithm display the number of occurence of each enzyme, But we cannot determine the position of every sites.
-We will see howt to do this later.
+   Computer scientists typically measure an algorithm’s efficiency in terms of its worst-case running time, 
+   which is the largest amount of time an algorithm can take given the most difficult input of a fixed size. 
+   The advantage to considering the worst case running time is that we are guaranteed that our algorithm 
+   will never behave worse than our worst-case estimate.
+   
+   Big-O notation compactly describes the running time of an algorithm. 
+   For example, if your algorithm for sorting an array of n numbers takes roughly n2 operations for the most difficult dataset, 
+   then we say that the running time of your algorithm is O(n2). In reality, depending on your implementation, it may be use any number of operations, 
+   such as 1.5n2, n2 + n + 2, or 0.5n2 + 1; all these algorithms are O(n2) because big-O notation only cares about the term that grows the fastest with 
+   respect to the size of the input. This is because as n grows very large, the difference in behavior between two O(n2) functions, 
+   like 999 · n2 and n2 + 3n + 9999999, is negligible when compared to the behavior of functions from different classes, 
+   say O(n2) and O(n6). Of course, we would prefer an algorithm requiring 1/2 · n2 steps to an algorithm requiring 1000 · n2 steps.
+
+   When we write that the running time of an algorithm is O(n2), we technically mean that it does not grow faster than a function with a 
+   leading term of c · n2, for some constant c. Formally, a function f(n) is Big-O of function g(n), or O(g(n)), when f(n) ≤ c · g(n) for some 
+   constant c and sufficiently large n.
+
+   For more on Big-O notation, see A `http://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/Beginner's <Guide to Big-O Notation>`_.
+   
 
+Compare the pseudocode of each of them and implement the fastest one. ::
 
+   """gtcagaccttcctcctcagaagctcacagaaaaacacgctttctgaaagattccacactcaatgccaaaatataccacag
+      gaaaattttgcaaggctcacggatttccagtgcaccactggctaaccaagtaggagcacctcttctactgccatgaaagg
+      aaaccttcaaaccctaccactgagccattaactaccatcctgtttaagatctgaaaaacatgaagactgtattgctcctg
+      atttgtcttctaggatctgctttcaccactccaaccgatccattgaactaccaatttggggcccatggacagaaaactgc
+      agagaagcataaatatactcattctgaaatgccagaggaagagaacacagggtttgtaaacaaaggtgatgtgctgtctg
+      gccacaggaccataaaagcagaggtaccggtactggatacacagaaggatgagccctgggcttccagaagacaaggacaa
+      ggtgatggtgagcatcaaacaaaaaacagcctgaggagcattaacttccttactctgcacagtaatccagggttggcttc
+      tgataaccaggaaagcaactctggcagcagcagggaacagcacagctctgagcaccaccagcccaggaggcacaggaaac
+      acggcaacatggctggccagtgggctctgagaggagaaagtccagtggatgctcttggtctggttcgtgagcgcaacaca"""
 
-Exercise
---------
-From a list return a new list without any duplicate, but keeping the order of items. 
-For example: ::
 
-   >>> l = [5,2,3,2,2,3,5,1]
-   >>> uniqify_with_order(l)
-   >>> [5,2,3,1]  
+In the first alogrithm. 
 
-solution ::
+| we first compute all kmers we generate 4\ :sup:`kmer length`
+| then we count the occurence of each kmer in the sequence
+| so for each kmer we read all the sequence so the algorith is in O( 4\ :sup:`kmer length` * ``sequence length``) 
 
-   >>> uniq = []
-   >>> for item in l:
-   >>>   if item not in uniq:
-   >>>      uniq.append(item)
+| In the secon algorithm we read the sequence only once 
+| So the algorithm is in O(sequence length)
 
 
-Exercise
---------
+Compute the 6 mers occurences of the sequence above, and print each 6mer and it's occurence one per line.
 
-list and count occurences of every 3mers in the following sequence ::
+.. literalinclude:: _static/code/kmer.py
+   :linenos:
+   :language: python
 
-   s = """gtcagaccttcctcctcagaagctcacagaaaaacacgctttctgaaagattccacactcaatgccaaaatataccacag
-   gaaaattttgcaaggctcacggatttccagtgcaccactggctaaccaagtaggagcacctcttctactgccatgaaagg
-   aaaccttcaaaccctaccactgagccattaactaccatcctgtttaagatctgaaaaacatgaagactgtattgctcctg
-   atttgtcttctaggatctgctttcaccactccaaccgatccattgaactaccaatttggggcccatggacagaaaactgc
-   agagaagcataaatatactcattctgaaatgccagaggaagagaacacagggtttgtaaacaaaggtgatgtgctgtctg
-   gccacaggaccataaaagcagaggtaccggtactggatacacagaaggatgagccctgggcttccagaagacaaggacaa
-   ggtgatggtgagcatcaaacaaaaaacagcctgaggagcattaacttccttactctgcacagtaatccagggttggcttc
-   tgataaccaggaaagcaactctggcagcagcagggaacagcacagctctgagcaccaccagcccaggaggcacaggaaac
-   acggcaacatggctggccagtgggctctgagaggagaaagtccagtggatgctcttggtctggttcgtgagcgcaacaca"""
+::
 
-and finally print the results one 3mer and it's occurence per line. 
+   >>> s = """"gtcagaccttcctcctcagaagctcacagaaaaacacgctttctgaaagattccacactcaatgccaaaatataccacag
+   ... gaaaattttgcaaggctcacggatttccagtgcaccactggctaaccaagtaggagcacctcttctactgccatgaaagg
+   ... aaaccttcaaaccctaccactgagccattaactaccatcctgtttaagatctgaaaaacatgaagactgtattgctcctg
+   ... atttgtcttctaggatctgctttcaccactccaaccgatccattgaactaccaatttggggcccatggacagaaaactgc
+   ... agagaagcataaatatactcattctgaaatgccagaggaagagaacacagggtttgtaaacaaaggtgatgtgctgtctg
+   ... gccacaggaccataaaagcagaggtaccggtactggatacacagaaggatgagccctgggcttccagaagacaaggacaa
+   ... ggtgatggtgagcatcaaacaaaaaacagcctgaggagcattaacttccttactctgcacagtaatccagggttggcttc
+   ... tgataaccaggaaagcaactctggcagcagcagggaacagcacagctctgagcaccaccagcccaggaggcacaggaaac
+   ... acggcaacatggctggccagtgggctctgagaggagaaagtccagtggatgctcttggtctggttcgtgagcgcaacaca"""
+   >>> s = s.replace('\n', '')
+   >>> kmers = get_kmer_occurences(s, 6)
+   >>> for kmer in kmers:
+   >>>   print kmer[0], '..', kmer[1]
+   gcagag .. 2
+   aacttc .. 1
+   gcaact .. 1
+   aaatat .. 2
+   
+   
+:download:`kmer.py <_static/code/kmer.py>` .
 
-write first the pseudocode, then implement it.
 
 bonus:
-print the kmer by incresing occurences.
+""""""
 
-solution ::
+Print the kmers by ordered by occurences.
 
-   s = s.replace('\n', '')
-   kmers = {}
-   # range exclude the last value range(3) -> 0, 1 ,2
-   # so we nned to go to len(s) minus trimer + 1 to include the 
-   # last base 
-   for i in range(len(s) - 3 +1):
-      kmer = s[i:i+3]
-      kmers[kmer] = kmers.get(kmer, 0) + 1
+| see `https://docs.python.org/2/library/stdtypes.html#mutable-sequence-types <sort>`_
+| see `https://docs.python.org/2/library/operator.html#operator.itemgetter <operator.itemgetter>`_
 
-   for kmer, occurence in kmers.items():
-      print kmer, " = ", occurence
 
-we can use also a defaultdict: ::
+.. literalinclude:: _static/code/kmer_2.py
+   :linenos:
+   :language: python
 
-   import collections
-   
-   s = s.replace('\n', '')
-   kmers = collection.defaultdict(int)
-   for i in range(len(s) - 2):
-      kmer = s[i:i+3]
-      kmers[kmer] += 1
-
-solution bonus ::
+::
 
-   list_of_kmers = kmers.items()  
-   from operator import itemgetter
-   list_of_kmers.sort(key=itemgetter(1)) 
-   for kmer, occurence in list_of_kmers:
-      print kmer, " = ", occurence
+   >>> s = """"gtcagaccttcctcctcagaagctcacagaaaaacacgctttctgaaagattccacactcaatgccaaaatataccacag
+   ... gaaaattttgcaaggctcacggatttccagtgcaccactggctaaccaagtaggagcacctcttctactgccatgaaagg
+   ... aaaccttcaaaccctaccactgagccattaactaccatcctgtttaagatctgaaaaacatgaagactgtattgctcctg
+   ... atttgtcttctaggatctgctttcaccactccaaccgatccattgaactaccaatttggggcccatggacagaaaactgc
+   ... agagaagcataaatatactcattctgaaatgccagaggaagagaacacagggtttgtaaacaaaggtgatgtgctgtctg
+   ... gccacaggaccataaaagcagaggtaccggtactggatacacagaaggatgagccctgggcttccagaagacaaggacaa
+   ... ggtgatggtgagcatcaaacaaaaaacagcctgaggagcattaacttccttactctgcacagtaatccagggttggcttc
+   ... tgataaccaggaaagcaactctggcagcagcagggaacagcacagctctgagcaccaccagcccaggaggcacaggaaac
+   ... acggcaacatggctggccagtgggctctgagaggagaaagtccagtggatgctcttggtctggttcgtgagcgcaacaca"""
+   >>> s = s.replace('\n', '')
+   >>> kmers = get_kmer_occurences(s, 6)
+   >>> for kmer, occ in kmers:
+   >>>   print kmer, '..', occ
+   cacagg .. 4
+   aggaaa .. 4
+   ttctga .. 3
+   ccagtg .. 3
+   
+   
+:download:`kmer_2.py <_static/code/kmer_2.py>` .
 
- solution bonus ::
 
-   list_of_kmers = kmers.items()      
-   list_of_kmers.sort(key = lambda kmer: kmer[1])
-   for kmer, occurence in list_of_kmers:
-      print kmer, " = ", occurence   
-      
-  
 Exercise
 --------
 
-compute the reversed complement of the following sequence: ::
+| Write a function which take a sequence as parameter and return it's reversed complement.
+| Write the pseudocode before to propose an implementation.
+
+pseudocode:
+"""""""""""
 
-   seq = 'acggcaacatggctggccagtgggctctgagaggagaaagtccagtggatgctcttggtctggttcgtgagcgcaacaca'
+| *function reverse_comp(sequence)*
+|     *complement <- establish a correpondance and each base and its complement*
+|     *rev_seq <- revert the sequence*
+|     *rev_comp <- empty*
+|     *for each nt of rev_seq*
+|        *concatenate nt complement to rev_comp*
+|     *return rev_comp
 
-   base_comp = { 'a' : 't', 
-                 'c' : 'g',
-                 'g' : 'c',
-                 't' : 'a'}
-   complement = ''
-   for base in seq:
-      complement += base_comp[base]
+.. literalinclude:: _static/code/rev_comp2.py
+   :linenos:
+   :language: python
 
-   reverse_comp = complement[::-1]
-   print reverse_comp
+::
+   >>> from rev_comp import rev_comp
+   >>>
+   >>> seq = 'acggcaacatggctggccagtgggctctgagaggagaaagtccagtggatgctcttggtctggttcgtgagcgcaacaca'
+   >>> print rev_comp(seq)
    tgtgttgcgctcacgaaccagaccaagagcatccactggactttctcctctcagagcccactggccagccatgttgccgt
+   
+:download:`rev_comp.py <_static/code/rev_comp.py>` .
+
   
 other solution
 """"""""""""""
@@ -346,18 +452,86 @@ the characters to change and their new values is made in funtion of thier positi
 the first character of the first string will be replaced by the first character of the second string,
 the second character of the first string will be replaced by the second character of the second string, on so on.   
 So we can write the reverse complement without loop.
+   
+.. literalinclude:: _static/code/rev_comp2.py
+   :linenos:
+   :language: python
 
 ::
+   >>> from rev_comp2 import rev_comp
+   >>>
+   >>> seq = 'acggcaacatggctggccagtgggctctgagaggagaaagtccagtggatgctcttggtctggttcgtgagcgcaacaca'
+   >>> print rev_comp(seq)
+   tgtgttgcgctcacgaaccagaccaagagcatccactggactttctcctctcagagcccactggccagccatgttgccgt
+   
+:download:`rev_comp2.py <_static/code/rev_comp2.py>` .
 
-   from string import maketrans
+Exercise
+--------
+
+let the following enzymes collection: ::
+ 
+   import collections
+   RestrictEnzyme = collections.namedtuple("RestrictEnzyme", "name comment sequence cut end")
+
+   ecor1 = RestrictEnzyme("EcoRI", "Ecoli restriction enzime I", "gaattc", 1, "sticky")
+   ecor5 = RestrictEnzyme("EcoRV", "Ecoli restriction enzime V", "gatatc", 3, "blunt")
+   bamh1 = RestrictEnzyme("BamHI", "type II restriction endonuclease from Bacillus amyloliquefaciens ", "ggatcc", 1, "sticky")
+   hind3 = RestrictEnzyme("HindIII", "type II site-specific nuclease from Haemophilus influenzae", "aagctt", 1 , "sticky")
+   taq1 = RestrictEnzyme("TaqI", "Thermus aquaticus", "tcga", 1 , "sticky")
+   not1 = RestrictEnzyme("NotI", "Nocardia otitidis", "gcggccgc", 2 , "sticky")
+   sau3a1 = RestrictEnzyme("Sau3aI", "Staphylococcus aureus", "gatc", 0 , "sticky")
+   hae3 = RestrictEnzyme("HaeIII", "Haemophilus aegyptius", "ggcc", 2 , "blunt")
+   sma1 =  RestrictEnzyme("SmaI", "Serratia marcescens", "cccggg", 3 , "blunt")
+
+and the 2 dna fragments: ::
+
+   dna_1 = """tcgcgcaacgtcgcctacatctcaagattcagcgccgagatccccgggggttgagcgatccccgtcagttggcgtgaattcag
+   cagcagcgcaccccgggcgtagaattccagttgcagataatagctgatttagttaacttggatcacagaagcttccaga
+   ccaccgtatggatcccaacgcactgttacggatccaattcgtacgtttggggtgatttgattcccgctgcctgccagg"""
+
+   dna_2 = """gagcatgagcggaattctgcatagcgcaagaatgcggccgcttagagcgatgctgccctaaactctatgcagcgggcgtgagg
+   attcagtggcttcagaattcctcccgggagaagctgaatagtgaaacgattgaggtgttgtggtgaaccgagtaag
+   agcagcttaaatcggagagaattccatttactggccagggtaagagttttggtaaatatatagtgatatctggcttg"""
+
+| which enzymes cut the dna_1 ?
+|                  the dna_2 ?
+|                  the dna_1 but not the dna_2?
+
+
+#. Write a function *seq_one_line* which take a multi lines sequence and return a sequence in one line.
+#. Write a function *enz_filter* which take a sequence and a list of enzymes and return a new list containing 
+   the enzymes which are a binding site in the sequence
+#. use the functions above to compute the enzymes which cut the dna_1 
+   apply the same functions to compute the enzymes which cut the dna_2
+   compute the difference between the enzymes which cut the dna_1 and enzymes which cut the dna_2
+   
+.. literalinclude:: _static/code/enzymes_1.py
+   :linenos:
+   :language: python
+
+::
+   from enzyme_1 import *
+   
+   enzymes = [ecor1, ecor5, bamh1, hind3, taq1, not1, sau3a1, hae3, sma1]
+   dna_1 = one_line(dna_1)
+   dans_2 = one_line(dna_2)
+   enz_1 = enz_filter(enzymes, dna_1)
+   enz_2 = enz_filter(enzymes, dna_2) 
+   enz1_only = set(enz_1) - set(enz_2)
+
+:download:`enzymes_1.py <_static/code/enzymes_1.py>` .
+
+with this algorithm we find if an enzyme cut the dna but we cannot find all cuts in the dna for an enzyme. ::
+
+   enzymes = [ecor1, ecor5, bamh1, hind3, taq1, not1, sau3a1, hae3, sma1]
+   digest_1 = []
+   for enz in enzymes:
+      print enz.name, dna_1.count(enz.sequence)
+
+the latter algorithm display the number of occurence of each enzyme, But we cannot determine the position of every sites.
+We will see how to do this later.
 
-   #first we reverse the sequence
-   rev_comp = seq[::-1]
-   #then we complement it
-   nucleotide = 'ATCG'
-   complement = 'TAGC'
-   rosetta_stone = maketrans(nucleotide, complement)
-   rev_comp = rev_comp.translate(rosetta_stone)
 
       
 Exercise
@@ -387,36 +561,3 @@ solution ::
 
    inverted_d = {v : k for k, v in d.items()}
    
-Exercise
---------
-
-We assume that we have a phylogenic tree of mammals represented as nested lists. ::
-    
-   mammals = ['Bovine', ['Gibbon', ['Orang Utan', ['Gorilla', ['Chimp', 'Human']]]], 'Mouse' ]
-   
-We want to work on the subtree of apes (Gibbon, Orang Utan, Gorilla, Chimp, Human) 
-
-* extract the this subtree in a new tree
-* then insert 'Bonobo' at the same level of Chimp we want to obtanin something like this :[chimp, bonobo], Human]
-   
-what's append on mammals? explain the result. ::
-
-   import copy
-     
-   mammals = ['Bovine', ['Gibbon', ['Orang Utan', ['Gorilla', ['Chimp', 'Human']]]], 'Mouse' ]
-   apes = copy.copy(mammals[1])
-   apes [1][1][1] = [['Chimp', 'Bonobo'], 'Human']
-   print mammals
-   ['Bovine', ['Gibbon', ['Orang Utan', ['Gorilla', ['Chimp', 'Human']]]], 'Mouse' ]
-
-what we should do to work with apes without modify mammals?
-   
-when we extract apes form mammals we did a shallow copy of mammals. tha mean we create a new list but each item in mammals 
-are not copy. when we modify apes we mutate an element of apes which was also referenced in mammals so mammals is modified to.
-This is what we call a side effect. To avoid that we should use deepcopy from module copy.
-to create apes we should write: ::
-
-   apes = copy.deepcopy(mammals[1]) 
-   
-deepcopy not only copy the list but make also a copy of each items of list recursively.
- 
diff --git a/source/Control_Flow_Statements.rst b/source/Control_Flow_Statements.rst
index 026d9e5dfe18d6527a3c06d2e5cba2c1125faf33..1ec4c1fc58900624dac35739b6128fd7b3a09827 100644
--- a/source/Control_Flow_Statements.rst
+++ b/source/Control_Flow_Statements.rst
@@ -11,7 +11,6 @@ Exercises
 Exercise
 --------
 
-Calculates the 10 first number of the Fibonacci sequence .
 The Fibonacci sequence are the numbers in the following integer sequence:
 
     0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
@@ -24,35 +23,162 @@ The fibonacci suite can be defined as following:
 |    
 |    F\ :sub:`n` = F\ :sub:`n-1` + F\ :sub:`n-2` 
 
+Write a function which take an integer ``n`` as parameter
+and returns a list containing the ``n`` first number of the Fibonacci sequence. 
+
+
 .. literalinclude:: _static/code/fibonacci_iteration.py
    :linenos:
    :language: python
    
-
+:download:`fibonacci_iteration.py <_static/code/fibonacci_iteration.py>` .
 We will see another way more elegant to implement the fibonacci suite in :ref:`Advance Programming Techniques` section.
 
+
+
 Exercise
 --------
 
-display the largest element in list (containing float or integer only)?::
+Reimplement your own function max (my_max).
+This function will take a list or tuple of float or integer and 
+returns the largest element?
 
-   l = [1,2,3,4,58,9]
-   higest = l[0]
-   for i in l:
-      if i > highest:
-         highest = i
-    print highest
-      
+Write the pseudocode before to propose an implementation.
+
+pseudocode
+^^^^^^^^^^
+
+| *function my_max(l)*
+|   *max <- first elt of l*
+|   *for each elts of l*
+|       *if elt is > max*
+|       *max <- elt*
+|   *return max*
 
+
+implementation
+^^^^^^^^^^^^^^
+
+::
+
+   def my_max(seq):
+      """
+      return the maximum value in a sequence 
+      work only with integer or float
+      """
+      higest = seq[0]
+      for i in seq:
+         if i > highest:
+             highest = i
+      return highest
+      
+   l = [1,2,3,4,58,9]
+   print my_max(l)
+   58
+   
+   
 Exercise
 --------
 
-let the following enzymes collection: ::
+| We want to establish a restriction map of a sequence. 
+| But we will do this step by step.
+| and reuse the enzymes used in previous chapter: 
+
+* create a function that take a sequence and an enzyme as parameter and return 
+   the position of first binding sites.
+   (write the pseudocode)
+
+**pseudocode** 
+   
+| *function one_enz_binding_site(dna, enzyme)*
+|     *if enzyme binding site is substring of dna*
+|          *return of first position of substring in dna* 
+ 
+**implementation**
+ 
+.. literalinclude:: _static/code/restriction.py
+   :linenos:
+   :lines: 1-8
+   :language: python
+   
+* improve the previous function to return all positions of binding sites
+
+**pseudocode of first algorithm**
+
+| *function one_enz_binding_sites(dna, enzyme)*
+|     *positions <- empty*
+|     *if enzyme binding site is substring of dna*
+|          *add the position of the first substring in dna in positions* 
+|     *positions <- find binding_sites in rest of dna sequence*
+|     *return positions*  
+
+**implementation**
+
+.. literalinclude:: _static/code/restriction.py
+   :linenos:
+   :lines: 9-16
+   :language: python
+
+**pseudocode of second algorithm**
+
+| *function one_enz_binding_sites(dna, enzyme)*
+|     *positions <- empty*
+|     *find first position of binding site in dna*
+|     *while we find binding site in dna*
+|         *add position of binding site to positions*
+|         *find first position of binding site in dna in rest of dna*
+|     *return positions*
+
+**implementation**
+
+.. literalinclude:: _static/code/restriction.py
+   :linenos:
+   :lines: 19-25
+   :language: python
+   
+   
+search all positions of Ecor1 binding sites in dna_1
+
+::
  
    import collections
    RestrictEnzyme = collections.namedtuple("RestrictEnzyme", "name comment sequence cut end")
 
    ecor1 = RestrictEnzyme("EcoRI", "Ecoli restriction enzime I", "gaattc", 1, "sticky")
+   
+   dna_1 = """tcgcgcaacgtcgcctacatctcaagattcagcgccgagatccccgggggttgagcgatccccgtcagttggcgtgaattcag
+   cagcagcgcaccccgggcgtagaattccagttgcagataatagctgatttagttaacttggatcacagaagcttccaga
+   ccaccgtatggatcccaacgcactgttacggatccaattcgtacgtttggggtgatttgattcccgctgcctgccagg"""
+   
+   
+* generalize the binding sites function to take a list of enzymes and return a list of tuple (enzyme name, position) 
+   
+**pseudocode**
+
+| *function binding_sites(dna, set of enzymes)*
+|     *positions <- empty*
+|     *for each enzyme in enzymes*
+|         *pos <- one_enz_binding_sites(dna, enzyme)*
+|         *pos <- for each position create a tuple enzyme name, position*
+|         *positions <- pos*
+|     *return positions*
+
+**implementation**
+
+in bonus we can try to sort the list in the order of the position of the binding sites like this:
+[('Sau3aI', 38), ('SmaI', 42), ('Sau3aI', 56), ('EcoRI', 75), ...
+
+.. literalinclude:: _static/code/restriction.py
+   :linenos:
+   :lines: 27-
+   :language: python
+   
+::
+ 
+   import collections
+   RestrictEnzyme = collections.namedtuple("RestrictEnzyme", "name comment sequence cut end")
+
+   ecor1 = RestrictEnzyme("EcoRI", "Ecoli restriction enzime I", "gaattc", 1, "sticky")   
    ecor5 = RestrictEnzyme("EcoRV", "Ecoli restriction enzime V", "gatatc", 3, "blunt")
    bamh1 = RestrictEnzyme("BamHI", "type II restriction endonuclease from Bacillus amyloliquefaciens ", "ggatcc", 1, "sticky")
    hind3 = RestrictEnzyme("HindIII", "type II site-specific nuclease from Haemophilus influenzae", "aagctt", 1 , "sticky")
@@ -72,77 +198,17 @@ and the 2 dna fragments: ::
    attcagtggcttcagaattcctcccgggagaagctgaatagtgaaacgattgaggtgttgtggtgaaccgagtaag
    agcagcttaaatcggagagaattccatttactggccagggtaagagttttggtaaatatatagtgatatctggcttg"""
 
-| which enzymes cut the dna_1 get the name of the enzymes and all their positions of binding site?
-|                  the dna_2 ?
-|                  the dna_1 but not the dna_2?
-
-
-::
+   enzymes= (ecor1, ecor5, bamh1, hind3, taq1, not1, sau3a1, hae3, sma1)
+   binding_sites(dna_1, enzymes)
+   [('Sau3aI', 38), ('SmaI', 42), ('Sau3aI', 56), ('EcoRI', 75), ('SmaI', 95), ('EcoRI', 105), 
+   ('Sau3aI', 144), ('HindIII', 152), ('BamHI', 173), ('Sau3aI', 174), ('BamHI', 193), ('Sau3aI', 194)]
 
-   dna_1 = dna_1.replace('\n', '')
-   dans_2 = dna_2.replace('\n', '')
+   binding_sites(dna_2, enzymes)
+   [('EcoRI', 11), ('NotI', 33), ('HaeIII', 35), ('EcoRI', 98), ('SmaI', 106), 
+   ('EcoRI', 179), ('HaeIII', 193), ('EcoRV', 225)]
    
-   enzymes = [ecor1, ecor5, bamh1, hind3, taq1, not1, sau3a1, hae3, sma1]
-   digest_1 = []
-   for enz in enzymes:
-      pos = dna_1.find(enz.sequence)
-      if pos != -1:
-         digest_1.append(enz)
-
-with this first algorithm we find if an enzyme cut the dna but we cannot find all cuts in the dna for an enzyme.
-If we find a cutting site, we must search again starting at the first nucleotid after the begining of the match 
-until the end of the the dna, for this we use the start parameter of the find function, and so on. 
-As we don't know how many loop we need to scan the dna until the end we use a ``while`` loop testing for the presence of a cutting site.::  
-
-   digest_1 = []
-   for enz in enzymes:
-      pos = dna_1.find(enz.sequence)
-      while pos != -1:
-         digest_1.append(enz)
-         pos = dna_1.find(enz.sequence, pos + 1)
-         
-   digest_2 = []
-   for enz in enzymes:
-      pos = dna_2.find(enz.sequence)
-      while pos != -1:
-         digest_2.append(enz)
-         pos = dna_2.find(enz.sequence, pos + 1)  
-                
-   cut_dna_1 = set(digest_1)
-   cut_dna_2 = set(digest_2)
-   cut_dna_1_not_dna_2 = cut_dna_1 - cut_dna_2
-         
-         
-but we want also the position, for instance to compute the fragments of dna. ::
-
-   digest_1 = []
-   for enz in enzymes:
-      pos = dna_1.find(enz.sequence)
-      while pos != -1:
-         digest_1.append((enz, pos))
-         pos = dna_1.find(enz.sequence, pos + 1)
-    
-   #if we want to sort the list in function of their positions in the sequence 
-   from operator import itemgetter
-   digest_1.sort(key=itemgetter(1))
-   print [(e.name, pos) for e, pos in digest_1]
+:download:`restriction.py <_static/code/restriction.py>` .
 
-   
-   digest_2 = []
-   for enz in enzymes:
-      pos = dna_2.find(enz.sequence)
-      while pos != -1:
-         digest_2.append((enz, pos))
-         pos = dna_2.find(enz.sequence, pos + 1)
-   
-   print "list of all enzymes cutting dna 1 and theirs position in dna1 :", [(e.name, pos) for e, pos in digest_1]
-   print "list of all enzymes cutting dna 2 and theirs position in dna2 :", [(e.name, pos) for e, pos in digest_2]
-           
-   cut_dna_1 = set([e.name for e, pos in digest_1])
-   cut_dna_2 = set([e.name for e, pos in digest_2])
-   
-   cut_dna_1_not_dna_2 = cut_dna_1 - cut_dna_2
-   
 
 Exercise
 --------
diff --git a/source/Data_Types.rst b/source/Data_Types.rst
index 9fd039c336acef87fbc2a730c17b3a89a38717b8..65de161c593407ac7d408e06fe80f9de63671b94 100644
--- a/source/Data_Types.rst
+++ b/source/Data_Types.rst
@@ -195,7 +195,7 @@ without header or any non sequence characters
 
 pseudocode:
 
-|   *fasta_to_one_line(seq)*
+|   *function fasta_to_one_line(seq)*
 |      *header_end_at <- find the first return line character*
 |      *raw_seq <- remove header from sequence*
 |      *raw_seq <- remove non sequence chars*
diff --git a/source/Creating_and_Calling_Functions.rst b/source/Dive_into_Functions.rst
similarity index 97%
rename from source/Creating_and_Calling_Functions.rst
rename to source/Dive_into_Functions.rst
index 2d1d744dd12a4939e33478e776daceb77f2dba1c..34a44461c8b31014cf7db47993abad4b64aabad3 100644
--- a/source/Creating_and_Calling_Functions.rst
+++ b/source/Dive_into_Functions.rst
@@ -1,8 +1,8 @@
-.. _Creating_and_Calling_Functions:
+.. _Dive_into_Functions:
 
-******************************
-Creating and Calling Functions
-******************************
+*******************
+Dive into Functions
+*******************
 
 Exercises
 =========
@@ -105,7 +105,7 @@ As soon as you make an assignment to a variable in a scope,
 that variable becomes local to that scope and shadows any similarly named variable in the outer scope.
 even if the assignment appear later in code.
 Here *x = y* make *x* as local variable whatever you are in func.
-so at line  *y = x + 2* we try to use the loca variable *x* but we have to asign it a value (it is done later) so
+so at line  *y = x + 2* we try to use the local variable *x* but we have to asign it a value (it is done later) so
 Python raise an UnboundLocalError (`see python faq for details <https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value>`_) 
 
 .. container:: clearer
diff --git a/source/Modules_and_Packages.rst b/source/Modules_and_Packages.rst
index b3e1718823ac132480f1838551078096902343cb..53734b981911804d4f50ffa7f70689b7885ba1d5 100644
--- a/source/Modules_and_Packages.rst
+++ b/source/Modules_and_Packages.rst
@@ -27,22 +27,13 @@ Exercise
 
 Write a program that calculates the similarity of 2 RNA sequences.
 
-* To compute the simalirity you need to parse a file containing the similarity matrix.
+* To compute the simalirity you need to parse a file containing the :download:`similarity matrix <_static/data/similarity_matrix>`.
+  **Hint**: use the module containing the functions that handle a matrix from previous chapter.
+  put this matrix.py file in a directory named "my_python_lib" in your home or Desktop
+  and import it in your current program (the similarity script must be placed elsewhere).
 * The similarity of the 2 sequences is the sum of base similarities. 
-  so you have to compare the first base of to sequence and use the matrix to get the similarity
+  so you have to compare the first base of two sequences and use the matrix to get the similarity
   from the similarity table, on so on for all bases then sum these similarities.
-  
-.. note::
-   as we  don't yet see how to read a file, we provide a list of strings that represents the file
-   as we can get them if we read that file.
-   
-::
-
-   lines = iter(['  A G C U\n'
-                 'A 1.0 0.5 0.0 0.0\n',
-                 'G 0.5 1.0 0.0 0.0\n',
-                 'C 0.0 0.0 1.0 0.5\n',
-                 'U 0.0 0.0 0.5 1.0\n'])
 
 .. literalinclude:: _static/code/similarity.py
    :linenos:
diff --git a/source/_static/code/codons.py b/source/_static/code/codons.py
new file mode 100644
index 0000000000000000000000000000000000000000..89734869ad0178813b586d0f62eb25c7bdee1b41
--- /dev/null
+++ b/source/_static/code/codons.py
@@ -0,0 +1,10 @@
+
+def all_codons():
+    all_codons = []
+    alphabet = 'acgt'
+    for base_1 in alphabet:
+        for base_2 in alphabet:
+            for base_3 in alphabet:
+                codon = base_1 + base_2 + base_3
+                all_codons.append(codon)
+    return all_codons
\ No newline at end of file
diff --git a/source/_static/code/codons_itertools.py b/source/_static/code/codons_itertools.py
new file mode 100644
index 0000000000000000000000000000000000000000..317d3831abdd00a6e86d067ae9290ed52061373a
--- /dev/null
+++ b/source/_static/code/codons_itertools.py
@@ -0,0 +1,6 @@
+from itertools import product
+
+def all_codons():
+    alphabet = 'acgt'
+    all_codons = [ ''.join(codon) for codon in product(alphabet, repeat = 3)]
+    return all_codons
\ No newline at end of file
diff --git a/source/_static/code/enzyme_1.py b/source/_static/code/enzyme_1.py
new file mode 100644
index 0000000000000000000000000000000000000000..09667e3d165a908e31c324fe3863ea3c1a1a8e1c
--- /dev/null
+++ b/source/_static/code/enzyme_1.py
@@ -0,0 +1,12 @@
+
+
+def one_line(seq):
+    return seq.replace('\n', '')
+
+def enz_filter(enzymes, dna):
+    cuting_enz = []
+    for enz in enzymes:
+        if enz.sequence in dna: 
+            cuting_enz.append(enz)
+    return cuting_enz
+
diff --git a/source/_static/code/kmer.py b/source/_static/code/kmer.py
index d1e11b62916e3eba8e5ba1d36fd1cd974274be28..02dc1341b8e537527a17235456d68af12478de8d 100644
--- a/source/_static/code/kmer.py
+++ b/source/_static/code/kmer.py
@@ -1,8 +1,12 @@
-import collections
 
-def kmer(sequence, k):
-    kmers = collection.defaultdict(int)
-    for i in range(len(sequence) - k):
-        kmer = sequence[i:i + k]
+def get_kmer_occurences(seq, kmer_len):
+    """
+    return a list of tuple 
+    each tuple contains a kmers present in seq and its occurence
+    """
+    kmers = {}
+    stop = len(seq) - kmer_len
+    for i in range(stop + 1):
+        kmer = s[i : i + kmer_len]
         kmers[kmer] = kmers.get(kmer, 0) + 1
-    return kmers
\ No newline at end of file
+    return kmers.items()
\ No newline at end of file
diff --git a/source/_static/code/kmer_2.py b/source/_static/code/kmer_2.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f98d53e0a7b4b52db2afcd89776a15dd7a4ac85
--- /dev/null
+++ b/source/_static/code/kmer_2.py
@@ -0,0 +1,17 @@
+import collections
+from operator import itemgetter
+
+def get_kmer_occurences(seq, kmer_len):
+    """
+    return a list of tuple 
+    each tuple contains a kmers present in seq and its occurence
+    """
+    kmers = collections.defaultdict(int)
+    stop = len(seq) - kmer_len
+    for i in range(stop + 1):
+        kmer = s[i : i + kmer_len]
+        kmers[kmer] += 1
+    kmers = kmers.items()
+    kmers.sort(key = itemgetter(1), reverse =True)
+    return kmers
+        
\ No newline at end of file
diff --git a/source/_static/code/restriction.py b/source/_static/code/restriction.py
new file mode 100644
index 0000000000000000000000000000000000000000..26e228fb07df2d39c2be47ad0f78720efc01de75
--- /dev/null
+++ b/source/_static/code/restriction.py
@@ -0,0 +1,50 @@
+from operator import itemgetter
+
+
+def one_enz_binding_site(dna, enzyme):
+    """
+    return the first position of enzyme binding site in dna
+    or None if there is not
+    """
+    pos = dna.find(enzyme.sequence)
+    if pos != -1:
+        return pos
+
+
+def one_enz_binding_sites1(dna, enzyme):
+    """
+    return all positions of enzyme binding sites in dna
+    """
+    positions = []
+    pos = dna.find(enzyme.sequence)
+    if pos != -1:
+        positions.append(pos)
+        positions.extend(one_enz_binding_site1(dna[pos+1:], enzyme))
+    return positions
+        
+        
+def one_enz_binding_sites(dna, enzyme):
+    """
+    return all positions of enzyme binding sites in dna
+    """
+    positions = []
+    pos = dna.find(enzyme.sequence)
+    while pos != -1:
+        positions.append(pos)
+        pos = dna.find(enzyme.sequence, pos + 1)
+    return positions
+
+
+def binding_sites(dna, enzymes):
+    """
+    return all positions of all enzymes binding sites present in dna
+    sort by the incresing position
+    """
+    positions = []
+    for enzyme in enzymes:
+        pos = one_enz_binding_sites(dna, enzyme)
+        pos = [(enzyme.name, pos) for pos in pos]
+        positions.extend(pos)
+    positions.sort(key = itemgetter(1))
+    return positions 
+
diff --git a/source/_static/code/rev_comp.py b/source/_static/code/rev_comp.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd0337e1fb9baaca5beff07ab719ac51a7ba91b3
--- /dev/null
+++ b/source/_static/code/rev_comp.py
@@ -0,0 +1,15 @@
+
+def rev_comp(seq):
+    """
+    return the reverse complement of seq
+    the sequence must be in lower case
+    """
+    complement = {'a' : 't',
+                  'c' : 'g',
+                  'g' : 'c',
+                  't' : 'a'}
+    rev_seq = seq[::-1]
+    rev_comp = ''
+    for nt in rev_seq:
+        rev_comp += complement[nt]
+    return rev_comp
\ No newline at end of file
diff --git a/source/_static/code/rev_comp2.py b/source/_static/code/rev_comp2.py
new file mode 100644
index 0000000000000000000000000000000000000000..59ea1a1e6157c645d808fbf58376e8a04f827900
--- /dev/null
+++ b/source/_static/code/rev_comp2.py
@@ -0,0 +1,17 @@
+import string
+
+def rev_comp(seq):
+    """
+    return the reverse complement of seq
+    the case is respect but if the sequence mix upper and lower case the function will failed
+    """
+    upper = seq.isupper()
+    reverse = seq[::-1]
+    direct = 'acgt'
+    comp = 'tgca'
+    if upper:
+        table = string.maketrans(direct.upper(), comp.upper())
+    else:
+        table = string.maketrans(direct, comp)
+    rev_comp = reverse.translate(table)
+    return rev_comp
\ No newline at end of file
diff --git a/source/_static/code/similarity.py b/source/_static/code/similarity.py
index b46d1a0943cf2d1dfdebaa0c618841078f8e1888..286742ae63d66f9d6575f3c52f6cc0f44f555d25 100644
--- a/source/_static/code/similarity.py
+++ b/source/_static/code/similarity.py
@@ -1,26 +1,27 @@
+import sys
+import os.path
+
+sys.path.insert(0, os.path.join(expanduser('~'), "my_python_lib"))
+
 import matrix
 
-lines = iter( ['  A G C U\n',
-               'A 1.0 0.5 0.0 0.0\n',
-               'G 0.5 1.0 0.0 0.0\n',
-               'C 0.0 0.0 1.0 0.5\n',
-               'U 0.0 0.0 0.5 1.0\n']
-             )
 
-def parse_similarity_file():
+def parse_similarity_file(path):
     """
     parse file containing RNA similarity matrix and return a matrix
     """
     sim_matrix = matrix.create(4, 4)
-    #skip first line
-    lines.next()
-    for row_no, line in enumerate(lines):
-        line = line.strip()
-        fields = line.split()
-        values = [float(val) for val in fields[1:]]
-        matrix.replace_row(sim_matrix, row_no, values)
+    with open(path, 'r') as sim_file:
+        #skip first line
+        sim_file.next()
+        for row_no, line in enumerate(sim_file):
+            line = line.strip()
+            fields = line.split()
+            values = [float(val) for val in fields[1:]]
+            matrix.replace_row(sim_matrix, row_no, values)
     return sim_matrix
 
+
 def get_similarity(b1, b2, sim_matrix):
     """
     :param b1: the first base must be in ('A', 'G', 'C', 'U')
@@ -40,6 +41,7 @@ def get_similarity(b1, b2, sim_matrix):
     if not b2 in bases:
         raise KeyError("unknown base b2: " + str(b2))
     return matrix.get_cell(sim_matrix, bases[b1], bases[b2])
+                      
                            
 def compute_similarity(seq1, seq2, sim_matrix):
     """
@@ -58,12 +60,13 @@ def compute_similarity(seq1, seq2, sim_matrix):
         sim = get_similarity(b1, b2, sim_matrix)
         similarities.append(sim)
     return sum(similarities)
+       
             
 if __name__ == '__main__':
     seq1 = 'AGCAUCUA'
     seq2 = 'ACCGUUCU'
-    sim_matrix = parse_similarity_file()
+    sim_matrix = parse_similarity_file("similarity_matrix")
     print matrix.to_str(sim_matrix)
     similarity = compute_similarity(seq1, seq2, sim_matrix)
     print similarity
-            
\ No newline at end of file
+            
diff --git a/source/_static/code/translate.py b/source/_static/code/translate.py
index d4238900f7e57b176023f9d9f52dbf66f2e366e4..288a0659da8990079d3e8958f7946b125aabd0d3 100644
--- a/source/_static/code/translate.py
+++ b/source/_static/code/translate.py
@@ -19,17 +19,21 @@ genetic_code = {  'ttt': 'F', 'tct': 'S', 'tat': 'Y', 'tgt': 'C',
 def translate(nuc_seq, code):
     
     prot_seq = ''
-    start = 0
-    while (start + 2) < len(nuc_seq):
+    n = 0
+    # to avoid to compute len(seq)/3 at each loop
+    # I compute it once and use a reference
+    # it could be expensive if the sequence is very long.
+    cycle = len(nuc_seq)/3
+    while n < cycle:
+        start = n * 3
         end = start + 3
-        print start, end
         codon = nuc_seq[start:end]
         codon = codon.lower()
         if codon in code:
             prot_seq += code[codon] 
         else:
             raise RuntimeError("unknow codon: " + codon)
-        start += 3
+        n += 1
     return prot_seq
         
 def translate2(nuc_seq, code, phase = 1):
@@ -39,7 +43,9 @@ def translate2(nuc_seq, code, phase = 1):
     elif -4 < phase < 0:
         start = -phase - 1
         nuc_seq = nuc_seq[::-1]
-    while(start + 2) < len(nuc_seq):
+    # an other way to determine the end of looping
+    stop_iteration = len(nuc_seq)
+    while (start + 2) < stop_iteration:
         end = start + 3
         codon = nuc_seq[start:end].lower()
         if codon in code:
@@ -47,4 +53,4 @@ def translate2(nuc_seq, code, phase = 1):
         else:
             raise RuntimeError("unknow codon")
         start += 3        
-    return prot_seq
\ No newline at end of file
+    return prot_seq
diff --git a/source/_static/code/uniqify.py b/source/_static/code/uniqify.py
new file mode 100644
index 0000000000000000000000000000000000000000..299d4c3529c239cb17161879276ecc5be1f06bc4
--- /dev/null
+++ b/source/_static/code/uniqify.py
@@ -0,0 +1,6 @@
+def uniqify(l):
+    uniq = []
+    for item in l:
+       if item not in uniq:
+          uniq.append(item)
+    return (uniq)
\ No newline at end of file
diff --git a/source/_static/data/similarity_matrix b/source/_static/data/similarity_matrix
new file mode 100644
index 0000000000000000000000000000000000000000..aa60f6e5349bea04e6846441754908a3d415d1b0
--- /dev/null
+++ b/source/_static/data/similarity_matrix
@@ -0,0 +1,5 @@
+   A   G   C   U
+A 1.0 0.5 0.0 0.0
+G 0.5 1.0 0.0 0.0
+C 0.0 0.0 1.0 0.5
+U 0.0 0.0 0.5 1.0
diff --git a/source/_static/figs/augmented_assignment_int2.png b/source/_static/figs/augmented_assignment_int2.png
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d3d457ca9c70aa814c1cca7bfa870a8d37101
Binary files /dev/null and b/source/_static/figs/augmented_assignment_int2.png differ
diff --git a/source/_static/figs/augmented_assignment_list2.png b/source/_static/figs/augmented_assignment_list2.png
new file mode 100644
index 0000000000000000000000000000000000000000..14e73407319b7d0d73fd8cfb4d3400448d5db6d9
Binary files /dev/null and b/source/_static/figs/augmented_assignment_list2.png differ
diff --git a/source/index.rst b/source/index.rst
index df46468eab7faed899db9237fb03ccf91d0bfb83..e10020472a81e9944ef08bd388f3fe609344230f 100644
--- a/source/index.rst
+++ b/source/index.rst
@@ -18,7 +18,7 @@ Contents:
    Collection_Data_Types
    Logical_Operations
    Control_Flow_Statements
-   Creating_and_Calling_Functions
+   Dive_into_Functions
    Modules_and_Packages
    Input_Output