Programmes et Algorithmes (L1 IEEA S1IN102 ; site Moodle)

Enseignant principal (CMs, ...) :  Sébastien HOARAU (seb.hoarau@...)
  Chargé de TDs pour les groupes IEEA_1+3+5 et SF3-1b :  Philippe MARTIN (philippe.martin@...)
Cette page (  http://www.phmartin.info/cours/python/  )
rappelle certaines informations (liens, ...) importantes pour les TDs.


* Page centrale du cours sur Moodle (CMs, TDs, solutions, forum, ...).
* MOOC "Apprendre à coder avec Python" (exo UpyLaB 2.1) ;

* Page Web du MOOC relative au livre du cours : c'est la page "Aide mémoire" qui est principalement
    affichée (ayez la toujours ouverte, elle vous sera utile) mais une page "Bonnes pratiques" est aussi
    directement accessible et, via un onglet, le "Manuel du cours" l'est aussi ; si vous avez des difficultés à
    trouver un exercice particulier dans le MOOC, faites une recherche (<ctrl>-F) dans ce manuel.
* Documentations officielles sur Python 3.6.3.



Voici ci-dessous des aides/rappels complémentaires à celles listées dans
la page de "Bonnes pratiques" référée ci-dessus. Plus vous suivrez de "bonnes pratiques",
plus votre code sera lisible/compréhensible (par vous et d'autres), réutilisable et
automatiquement analysable/modifiable, et donc
1. plus vous éviterez des erreurs et gagnerez du temps,
2. plus vous montrerez que vous savez suivre des spécifications, ce qui est fondamental dans
    le développement de logiciels (voyez ces amusantes illustrations et notez que généralement
    au moins 70% de la valeur d'un code tient dans sa maintenabiité/réutilisabilité), et donc
3. plus favorable sera – ou aura tendance à être – l'évaluation de votre chargé de TDs.





Exemple de fonctions ou conseils relatifs à l'usage de Checkio :


Évitez Internet Explorer (qui a quelques problèmes ; utilisez plutôt Firefox ou Chrome).


Pour l'exercice "First Word" (de Elementary, dans Checkio), ici renommé String_firstWord,
notez qu'un "mot" ["word"] est
- une suite de caractères qui ne sont pas des caractères de punctuation, et donc
- précédé et/ou suivi par rien ou par des caractères de punctuation.
Implémentant cette définition, voici au moins 90% de cette fonction :

def String_firstWord (text: str) -> str:  #this function uses a string (text) and returns a string (w)
  w= ""                             #  initialize w to the empty string
  sPunctuations= ( ... )            #  initialize sPunctuations (a list;  "...": to complete)
  lng= len(text)                    #  initialize lng since it is used more than once below
  for i1 in range(0,lng):           #  skip the punctuations before the 1st word (in text)
    c= text[i1]                     #    c is the current character
    if (c not in sPunctuations):    #    if c is not a sPunctuations
      break                         #      exit loop (c is the 1st character of the 1st word)
  for i2 in range(i1,lng):          #  starting from i1, skip the non-punctuations and
    c= text[i2]                     #                    build w (append the characters to w)
    if (c in sPunctuations):        #    if c is a punctuation character
      ...                           #      do something (you have to write this part)
    else: w+= ...                   #    else append c to w 
  return w                          #  return w (which now has all the characters of the 1st word)


Pour que l'exercise "Between Markers" soit instructif, n'utilisez pas la fonction
index() ou une autre fonction qui fait l'essentiel du travail.
Voici ci-dessous au moins 75% de cette fonction. Notez les similarités avec
le code de first_word() ci-dessus. "w+= ..." aurait pu être utilisé comme ci-dessus
mais, pour changer, "return text[iEndOfStrStart : ...]" est utilisé.

def String_betweenMarkers (text:str, strStart:str, strEnd:str) -> str: 
  #if strStart is not in text, the beginning of text is the begining of the string to return
  #if strEnd is not in text, the end of text is the end of the string to return
  #if strEnd occurs before strStart in text, an empty string is returned
  lng= len(text)                          
  lngStrStart= len(strStart)               #since len(strStart) is needed in the loop below
  lngStrEnd= len(strEnd)                   #idem
  iEndOfStrStart= 0                        #index of the end of strStart in text
  iStrEnd= ...                             #index of strEnd in text
  print("==============================")                   #trace for clarity purposes
  for i1 in range(0,lng):                  #loop from 0 to the last index of text
    #print(f"1. i1:{i1}",text[i1])                         #   trace for debugging purposes
    for j in range(lngStrStart):           #  loop to test if there is a strStart at text+i1
      #print(f"  1. text[{i1}+{j}]:{text[i1+j]}  strStart[{j}]:{strStart[j]}")
      if text[i1+j] != strStart[j]: break  #    stop as soon as it is clear this is not the case
      else: print("  no break")
    #print(f" 1. j:{j} lngStrStart:{lngStrStart}")
    print(f" 1. text[{i1}+{j}]:{text[i1+j]}  strStart[{lngStrStart-1}]:{strStart[lngStrStart-1]}")
    if (j==lngStrStart-1) and (text[i1+j]==strStart[lngStrStart-1]): #if strStart is at text+i1
      iEndOfStrStart= i1 + lngStrStart                               #  re-initialize iEndOfStrStart
      print("1. iEndOfStrStart:",iEndOfStrStart)
      break                                                          #  stop searching
  print("------------------------------")                   #trace for clarity purposes
  for i2 in range(...,lng):                #loop from ... (not exactly i1) to the last index of text
    for j in range(lngStrEnd):             #  loop to test if there is an strEnd at text+i2
      if ...                               #    ... 
    if (j==lngStrEnd-1) and ... :          #  if there is an strEnd at text+i2
      iStrEnd= ...                         #    ...
      if iStrEnd < iEndOfStrStart: ...     #    ... (reason for "... (not exactly i1)" above)
      ...                                  #    ...
  return text[iEndOfStrStart : ...]        #return the text between iEndOfStrStart and ...


Pour l'exercice "Number Base", il est très facile d'utiliser fonction int() (→ peu de points)
et plus dur&formateur de ne pas l'utiliser : pour cela, vous pouvez par exemple utiliser
l'un des algorithmes ici pointés.


Comme exemple de fonction calculant un maximum/minimum, sans utiliser max()/min(),
voici le code de la fonction "The Most Numbers" (ici renommée SequenceOfIntegers_maxMinusMin).
Cette fonction calcule le maximum moins le minimum de ses arguments (ce sont des entiers).
Le code étant ici donné, vous n'aurez aucun point pour l'implémentation de cette fonction dans Checkio.

from typing import Sequence, TypeVar
def SequenceOfIntegers_maxMinusMin (*args : Sequence[int]) -> int: 
   intMin= 100;  intMax= -100  #precondition: for each a in args, we have  -100 < a < 100
   if (len(args) == 0): return 0
   for a in args:
      if (a < intMin):  intMin= a
      elif(a > intMax): intMax= a
   return intMax - intMin


Pour l'exercice "Most Frequent", commencez par regarder comment utiliser les "dictionnaires" (associative arrays)
en Python (cf. votre cours ; mots clés pour Google: "dictionnary" ou "associative array").

def String_mostFrequentWord (sWords: str) -> int:
  aaFrequency= {}; 
  for w in sWords:  aaFrequency[w]= 0   #initialize/reset the associative array aaFrequency
  for w in sWords:  ...   #initialize/update aaFrequency with the frequencies of the words
  nMax= 0;  wordWithNMax= ""
  for w in aaFrequency:   #or:  for w in aaFrequency.keys():
    n= aaFrequency[w]     #frequency of w
    if n > ...:           #
       nMax= ...          #
       wordWithNMax= ...  #
  return wordWithNMax


Tris : Quicksort, Heapsort, ...