Rapport CodinGame: Ghost LegsPrép’ISIMA 23/01/2023
Lien de l’exercice : https://www.codingame.com/training/easy/ghost-legs
Le jeu ghost legs est un jeu de loterie qui ce présente comme ceci :

Le jeu est constitué de lignes verticales et parallèles, ayant chacune un nom. Entre ces lignes, à l’horizontale, on trouve d’autres lignes qui relient les lignes verticales entre elles.
Le but du jeu est que le joueur choisisse une ligne verticale en haut du jeu et suive cette ligne vers le bas. Il faut cependant suivre la regle qui indique que si le joueur rencontre un ligne horizontale,à droite ou à gauche de sa ligne, il doit la suivre jusqu’à la ligne verticale suivante. Le joueur repete cette action jusqu’a ce qu’il arrive en bas du jeu.
Le but de l’algorithme est donc de predire pour chaque ligne verticale, à quelle fin de ligne verticale elle est connectée.
Le principe est assez simple, on parcourt une premiere fois le jeu pour enregistrer les connexions entre les lignes verticales. On parcourt ensuite les lignes verticales de haut en bas et on verifie si la ligne verticale est connectée a une autre ligne verticale, si oui, on change de ligne verticale.
height = int(input().split()[1]) - 2 # on retire 2 car on a pas besoin de la premiere et de la derniere ligne qui contiennent les labels
topLabels = input().split() # on recupere les noms des entrées des lignes verticales
connectors = {} # dictionnaire qui contient les connexions entre les lignes verticales sous la forme (hauteur, ligneVerticale) : ligneVerticaleSuivante
for lineNumber in range(height): # on parcours les lignes du haut vers le bas
verticalLineNumber = -1 # on initialise le numero de la ligne verticale a -1 car on va l'incrementer avant de l'utiliser
for char in input(): # on parcours les caracteres de la ligne
if char == "-":
# on ajoute la connexion entre les deux lignes verticales dans les deux sens
connectors[(lineNumber, verticalLineNumber)] = verticalLineNumber + 1
connectors[(lineNumber, verticalLineNumber + 1)] = verticalLineNumber
elif char == "|":
verticalLineNumber += 1
bottomLabels = input().split() # on recupere les noms sorties des lignes verticales
for lineId, lineLabel in enumerate(topLabels): # pour chaque debut de ligne verticale
for i in range(height): # on parcours les lignes du haut vers le bas
if (i, lineId) in connectors.keys(): # si la ligne verticale est connecté a une autre ligne verticale
lineId = connectors[(i, lineId)] # on change de ligne verticale
print(lineLabel + bottomLabels[lineId]) # on affiche le nom de la ligne verticale de depart et de la ligne verticale d'arrivéLe code fonctionne comme prévu, il passe tous les tests. On peut cependant ameliorer le code, en effet lors du premier balayage du jeu, on enregistre les connexions entre les lignes verticales ainsi dans l’exemple suivant :
A B C
| | |
|--| |
| |--|
| |--|
| | |
1 2 3
lors du parcours, la troisieme ligne est la suivante : |–| | et lors de la boucle la correspondance du caractère “-” se fera deux fois pour une meme connexion puisqu’il y a deux tirets pour une meme connexion. Cela ne pose cependant pas de probleme puisque les dictionnaires ecrasent les valeurs similaires.
Solution de Danyosate:
https://www.codingame.com/training/easy/ghost-legs/solution?id=13774112
w, h = [int(i) for i in input().split()]
words = input().split()
order = [i for i in range(len(words))]
for i in range(h - 2):
line = [int(j) for j in input().replace(' ', '0').replace('--', '1').split('|')[1:-1]]
for j, v in enumerate(line):
if v:
order[j], order[j+1] = order[j+1], order[j]
nums = input().split()
for i, v in enumerate(words):
print(v, nums[order.index(i)], sep='')Cette solution est interressante puiqu’elle parcourt toutes les lignes en meme temps, elle est donc plus rapide que la mienne. Elle utilise une liste qui contient les numeros des lignes verticales. Elle parcourt ensuite les lignes et lorsqu’elle rencontre un tiret, elle inverse les deux valeurs de la liste. A la fin, elle parcourt la liste des noms des lignes verticales et affiche le nom de la ligne verticale de depart et de la ligne verticale d’arrivé. Cette solution est donc plus efficace puisqu’elle ne parcourt qu’une seule fois le jeu.
Cependant, cette solution est moins lisible car elle multiplie les actions dans une seul ligne de code et utlise des comprehensions de liste pour parcourir les lignes.
Cette exercice ma permis de revoire les dictionnaires et la fonction
enumerate() qui permet de parcourir une liste en recuperant
l’index et la valeur de l’élément courant.