Benoit DAJOUX



Rapport detective pikaptcha EP1


L'EP1 de detective pikaptcha disponible sur est un programme a écrire pour aider le detective pikaptcha a cartographier l'environnement qui l'entoure. Le but est de créer un programme qui analyse chaque case de la grille et qui renvoie le nombre de voisins pour chaque case, les mur sont représentés par "#" et les passages par des "0", le but etant que les "0" soient remplacés par le nombre de voisins que possèdent chaque cases.


Méthode de résolution


  1. stockage de la carte dans une liste

    On initialise une liste composée de chaine de caractère, on récupère les dimensions (hauteur et largeur), et on y stock le labyrinthe complet composé de "0" pour les passages et de "#" pour les murs.

  2. Transformation du Labyrinthe et affichage

    On créé une double boucle qui permet d'analyser chaque cases, et on ajoute 1 à une variable qui correspond au nombres de voisins pour chaque case voisine qui n'est pas un mur, on regarde au dessus, à gauche, à droite, en dessous. Une case a donc au maximum 4 voisins et donc une case aura un chiffre qui sera compris entre 0 et 4. lorsque cela est fait pour une case, on ajoute le nombres de voisins a une chaine de caractere correspondant a une ligne du labyrinthe. Une fois cela fait pour une ligne on affiche cette ligne.

Détail algorithmique

        
          On définie la hauteur et la largeur

          on définie la grille vide

          on creer une boucle qui va de 0 à la hauteur

           |   on insere la ligne dans la console
           |
           |   on ajoute la ligne a la grille

          on initialise la boucle qui va parcourir chaque ligne

           |   on définie la variable ligne et nb_voisins
           |
           |   on initialise la boucle qui parcours chaque élément de la ligne actuelle
           |
           |    |   on regarde si l'élément est différent de "#"
           |    |
           |    |   |   si la case du dessus est dans la grille et qu'elle est egale a "0" alors on ajoute 1 a nb_voisins
           |    |   |
           |    |   |   si la case en dessous est dans la grille et qu'elle est egale a "0" alors on ajoute 1 a nb_voisins
           |    |   |
           |    |   |   si la case à droite est dans la grille et qu'elle est egale a "0" alors on ajoute 1 a nb_voisins
           |    |   |
           |    |   |   si la case à gauche est dans la grille et qu'elle est egale a "0" alors on ajoute 1 a nb_voisins
           |    |
           |    |   si l'élément est un "#" alors nb_voisins prend la valeur "#"
           |    |
           |    |   on ajoute nb_voisins a la ligne et on le reinitialise a 0
           |
               on affiche ligne
        
      

Code de résolution

        
#on définie la hauteur et et la largeur du labyrinthe
width, height = [int(i) for i in input().split()]

#on instancie la grille
grille=[]

#on rempli la grille avec chaque ligne
for i in range(height):
    line = input()
    grille.append(line)

#on commence la boucle qui va parcourir chaque ligne
for i in range(height):

    #on instancie ligne et nb_voisins, le nombre de voisins ira dans ligne pour chaque chaque passage dans la boucle
    ligne=""
    nb_voisins=0

    #on commence la boucle qui parcours chaque éléments de la ligne
    for j in range(width):

        #on regarde si la case sur laquelle on est, est un mur ou un passage et on change nb_voisins en fonctions
        if grille[i][j]!='#':

            #case au dessus
            if i-1>=0 and grille[i-1][j]=='0':
                nb_voisins+=1

            #case en dessous
            if i+1=0 and grille[i][j-1]=='0':
                nb_voisins+=1
        else:
            nb_voisins='#'

        #on ajoute nb_voisins a ligne et on reinitialise nb_voisins
        ligne+=str(nb_voisins)
        nb_voisins=0

    #on print la ligne complete avec les bonnes valeurs de retour
    print(ligne)
                          
      

Présentation des tests

Le code a passé plusieurs test sur codingame et on tous réussi. Il a passer entre autre ce test:

en entrée:

5
3
"0000#"
"#0#00"
"00#0#"

et la sortie demandé étaient:

"1322#"
"#2#31"
"12#1#"

Il a aussi passer ce test:

Il avait pour entrée:

9
3
"#00###000"
"000000000"
"000##0000"

et en sortie:

"#22###232"
"244223443"
"232##2332"

Présentation de la méthode d’ un autre dévellopeur

Voici le code de SignumX, j’ ai choisi ce code car il est très court à écrire, il n’ utilise que 13 lignes de codes en comptant les saut de ligne

        
width, height = [int(i) for i in input().split()]
lines = [input() for _ in range(height)]

def check(x, y):
    return 1 if 0 <= x < width and 0 <= y < height and lines[y][x] == '0' else 0

for y in range(height):
    line = ''

    for x in range(width):
        line += '#' if lines[y][x] == '#' else str(check(x - 1, y) + check(x + 1, y) + check(x, y - 1) + check(x, y + 1))

print(line)

                                                        
      

présentation du code

Tout d’ abord il récupère les dimensions du labyrinthe ainsi que toute les lignes dans une liste de liste en seulement 2 lignes, il utilise les méthodes par comprehension pour faire ses listes.
Ensuite il définie une fonction "check" qui lui renvoie True si la case est bien dans le tableau et qu’ elle est bien égale à "0". Enfin il créé la double boucle pour parcourir chaque case du tableau et ajoute à la ligne "#" ou le nombre de voisins en fonctions de si la case est un mur ou un passage, il utilise la fonctions check pour chaque cases voisines à la case qu’ on regarde dans la boucle.







Detective Pikaptcha EP2


L’ EP2 de détéctive pikaptcha consiste a aider pikaptcha à trouver la sortie, il sait que la sortie est invisible et qu’ il va devoir cartographier clairement la structure du labyrinthe. Pikaptcha va donc devoir coller un mur et le suivre jusq’ à retourner à sont point de départ.

On nous demande de créer un code permettant a pikaptcha de longer le mur du labyrinthe, et qu’ elle que soit le coter qu’ il choisi, gauche ou droite.

Méthode de résolution


  1. On définie d’ abord 2 fonctions qui vont nous aider pour la suite, une fonction qui nous donne le cycle a suivre, il dépend du mur que pikaptcha doit longer, gauche ou droite, la fonction nous renvoie le cycle dans le bon ordre, tout dépend de l’ orientation qu’ a dejà pikaptcha à la base, "<",">","^","v", et ensuite on créé la fonction move, elle renvoie les indices de la case dans laquelle devra se deplacer pikaptcha ainsi que sont orientation et un booléen qui sert a dire quand on a fini le parcours car il passe a False.

  2. On créé ensuite nos variables qu’ on utilisera par la suite, il y a la hauteur et la largeur de labyrinthe, la grille, on initialise une variable booléenne qui mettra fin au parcours si elle passe a True, enfin, la grille finale intialiser avec tout les élément séparés, c’ est à dire qu’ il n’ y a pas "#0...", il y a seulement "#","0"par éléments.

  3. On crée ensuite la boucle qui va créer la grille avec les "0","#" et aussi le point de depart qui correspond a un "0" mais qui indique aussi la direction. On initialise dans la boucle la variables point_de_départ qui contiendra les coordonées du point de départ, la direction ainsi qu’ un booléen qui dit si on a fini le tour du labyrinthe ou pas. On ajoute aussi les "#" a grille finale la ou il y a des murs

  4. On créé le programme principal qui va appliquer la fonction move et ajouter 1 a la case si on passe une fois par cette case ou qui va mettre fin au parcours car pikaptcha sera revenue au point de départ.

  5. Enfin on affiche le résultat sous la forme attendue.

Détail algorithmique du code

          
            on définie la fonction cycle

            |   si le mur a longer est le gauche alors direction prend en valeurs la liste "<","^",">","v"
            |
            |   sinon direction prend en valeur la liste "v",">","^","<"
            |
            |   on définie rang qui prend la valeur de la direction actuelle de pikaptcha dans la variable direction
            |
            |   direction change l’ ordre de ses éléments pour passer à l’ ordre qui convient
            |
            |   on renvoie la variable direction

            on définie la fonction move

            |   on prend les coordonées i et j ainsi que la direction du point initiale
            |
            |   on définie le cycle grace a la fonction cycle
            |
            |   on démarre une boucle qui itère dans l’ ordre sur les éléments de cycle
            |
            |   |   si k est "<", et la case de gauche est dans le labyrinthe et différente de "#"
            |   |
            |   |   |   alors on change de case et on coupe la boucle
            |   |
            |   |   si k est ">", et la case de droite est dans le labyrinthe et différente de "#"
            |   |
            |   |   |   alors on change de case et on coupe la boucle
            |   |
            |   |   si k est "^", et la case du dessus est dans le labyrinthe et différente de "#"
            |   |
            |   |   |   alors on change de case et on coupe la boucle
            |   |
            |   |   si k est "v", et la case d’ en dessous est dans le labyrinthe et différente de "#"
            |   |
            |   |   |   alors on change de case et on coupe la boucle
            |
            |   on renvoie le nouveau point

            on initialise la hauteur et la largeur du labyrinthe

            on initialise la grille vide

            on initialise fin_parcours qui est un booléen qui mettra fin au parcours

            on créé la grille finale en ayant chaque élément séparer

            on commence la boucle qui va remplir la grille

            |    on indique recoit la ligne et on l’ ajoute dans la grille
            |
            |    on créé une boucle qui permet d’ initialiser le point de départ
            |
            |    on créé une boucle qui permet de mettre les murs dans grille_finale avec les "#"

            on recoit le mur a longer

            on commence une boucle non bornée

            |   on applique la fonction move au point de départ
            |
            |   on définie i et j en fonctions des coordonées du point
            |
            |   on regarde si le booléen presént dans la variable point de départ est egal à True et si il l’ est on ajoute 1 à la case actuelle
            |
            |   on regarde si la case actuelle correspond à un des motifs de directions, ">","<","^","v", si elle l’ est on met fin au parcours

                on créé la double boucle qui va afficher le résultat

                
        

Code de résolution

          
#cette fonctions définie le cycle que doit suivre pikaptcha pour se tourner si il a un mur à
#sa gauche ou a sa droite, en fonction de l’ ordre définie par side
def cycle(side, dir):
    if side=='L':
        direction=["<","^",">","v"]
    else:
        direction=["v",">","^","<"]
    rang=direction.index(dir)

    if rang>0:
        direction=direction[rang-1:len(direction)]+direction[0:rang-1]
    else:
        direction=direction[3:]+direction[0:3]
    return direction

#cette fonctions définie le point suivant sur lequel doit allez pikaptcha
def move(grille,point_de_depart,side,height,width):
    i=point_de_depart[0]
    j=point_de_depart[1]
    dir=point_de_depart[2]

    directions=cycle(side, dir)

    for k in directions:

        if k=="<" and j>0 and grille[i][j-1]!='#':
            point_de_depart=(i, j-1, "<", True)
            break

        if k==">" and j", True)
            break

        if k=="^" and i>0 and grille[i-1][j]!='#':
            point_de_depart=(i-1, j, "^", True)
            break

        if k=="v" and i","v"]:
        for j in range(len(line)):
            if direction == line[j] :
                point_de_depart=(i, j, direction, False)

    for j in range(len(line)):
        if grille[i][j]=="#":
            grille_finale[i][j]="#"

#on éxecute le programme principale
side = input()
while fin_parcours==False:
    point_de_depart=move(grille,point_de_depart,side,height,width)
    i=point_de_depart[0]
    j=point_de_depart[1]

    if point_de_depart[3]==True:
        grille_finale[i][j]+=1
    if grille[i][j] in ["<","^",">","v"]:
        fin_parcours=True

#on affiche le résultat
for i in range(height):
    for j in range(width):
        print(grille_finale[i][j], end="")
    print("")

                                 
      

Présentation des tests

Le code à passer plusieurs test qui ont tous réussi, il a notamment passé le test:

en entrée:

5
3
"0000#"
"#0#00"
"00#0#"

et la sortie demandé étaient:

"1322#"
"#2#31"
"12#1#"

Il a aussi passer ce test:

Il avait pour entrée:

9
3
"#00###000"
"000000000"
"000##0000"

et en sortie:

"#11###000"
"112210000"
"111##0000"


Présentation de la méthode d’ un autre dévellopeur

J’ ai choisi la méthode de GeoCon car c’ est une méthode assez courte comparé à la mienne et qu’ il utilise un système totalement différent du mien pour reussir cet exercice.

      
directions = {'<':(-1, 0), '>':(1, 0), '^':(0, -1), 'v':(0, 1)}

def next_direction(d, clockwise):
    dd = [1, -1][clockwise]
    dirs_ccw = '>^= 0 and y >= 0 and x < width and y < height and map[y][x] != '#'

width, height = map(int, input().split())
map = [list(input()) for y in range(height)]
side = input()

origin = ()
for y in range(height):
    for x in range(width):
        if map[y][x] in directions:
            origin = (x, y)
            break
    if origin: break

x, y = origin
d = map[y][x]
map[y][x] = '0'

stuck = False
while True:
    wd = wall_direction(d, side)
    new_d = d
    if can_move(map, x, y, wd): # check wall on the side
        new_d = wd
    else:
        rotations = 4 # max rotations to detect blocked situation
        while not can_move(map, x, y, new_d) and rotations: # rotate if wall in front
            new_d = rotate_direction(new_d, side)
            rotations -= 1
        stuck = rotations == 0
    if stuck: break
    map[y][x] = str(int(map[y][x]) + 1)
    d = new_d
    x, y = move(x, y, d)
    if (x, y) == origin: break

for i in map: print(*i, sep='')
      
    

explications du code

Il définie la variable directions qui est un dictionnaire contenant les directions et les coordonées d’ un point, puis il créé 5 fonctions qui vont lui apporter la prochaine direction, est ce que la prochaine direction est un mur, dans quel sens il doit tourner, comment est ce qu’ il doit se deplacer, et enfin est ce qu’ il peut se déplcaer. Ensuite il recupère la hauteur, la largeur, il créé la grille, et récupère le mur qu’ il doit longer. Il créé ensuite une boucle qui va lui donner le point de départ pour ensuite éxécuter le programme principale dans lequel il va se servir de ses fonctions pour arriver au résultat attendu.

voila la fin de ce rapport que vous pouvez retrouver sur:ma page personelle