Ah, classe :)
J'ai rien de joli à montrer ce coup-ci.
Mais bon, journée présentiel au taf hier, trois heures dans la voiture, 4h en réunions, j'ai à peine eu le temps de bricoler une solution, en ayant réfléchi sur le trajet...
J'ai fait un parcours de graphe inventé à la volée : je n'ai jamais été fichu de retenir le moindre des algos de parcours que j'ai pu apprendre, alors je suis condamné à réinventer la roue !
J'ai des cases en entrée, je regarde pour chacune d'elles où elles peuvent aller (haut, bas, gauche, droite, si la différence de hauteur est bonne), et si je n'ai pas déjà été là (donc matrice des cases visitées avec distance au départ dedans).
Je note l'ensemble des cases nouvellement visitées, et j'itère sur cet ensemble.
Donc a priori inutile de stocker le score pour le retrouver et calculer la suite comme dans mon code plus bas : il suffit de compter les étapes.
Instinctivement, je me suis dis que ça pouvait grossir, et donc j'ai décidé de manger le problème par les deux bouts, donc j'explore en montant depuis "S" et en descendant depuis "E".
Je stocke des scores positifs en montant, et négatifs en descendant.
Si je rencontre une case visitée depuis l'autre bout (case négative si je monte ou positive si je descends), j'ai fait la liaison.
En pratique je peux m'arrêter là : si je suis en train de monter c'est étape*2+1, si je suis en train de descendre c'est étape*2+2.
Dans mon code j'additionne les valeurs absolues : la valeur que j'aurais dû mettre dans la case, et celle déjà présente, et j'ai mon résultat.
Pour l'exercice 2, comme je fournis déjà une liste de case par itération, il suffit de mettre comme liste de démarrage tout les "a" et le "S", vraiment rien à coder, la dernière ligne du programme et basta.
Ah, et j'ai aligné, je bosse sur un tableau à une dimension, au lieu d'une matrice.
Et les mouvements possibles ne sont pas (haut, bas, gauche droite) mais (-1, +1, -largeur, +largeur) et un mouvement doit être dans [0, taille[
Allez, trêve de blabla, code !
heights={v:(26ifk==27elsek)or1fork,vinenumerate("SabcdefghijklmnopqrstuvwxyzE")}input=[lineforlineinsys.stdin.read().strip().splitlines()]w,h=len(input[0]),len(input)size=w*hmoves=[1,-1,w,-w]input="".join(input)map=[heights[c]forcininput]start=input.index("S")end=input.index("E")deftest(score,newpos,height,sign):""" False : mouvement impossible True : mouvement possible vers case non visitée int : mouvement possible vers case visitée, retourne le score de cette case """ifnewpos<0ornewpos>=size:returnFalseif(sign>0andmap[newpos]>height+1)\
or(sign<0andmap[newpos]<height-1):returnFalseifscore[newpos]isNone:returnTruereturnscore[newpos]defmove(score,pos,sign=1):height=map[pos]visited=[]solution=Falseforminmoves:newpos=pos+mt=test(score,newpos,height,sign)ifnott:# Movement not allowedcontinueiftisTrue:# New tile visitedscore[newpos]=score[pos]+signvisited.append(newpos)continueift*sign>0:# Already visitedcontinue# Visited from the other side : solution found !visited.append(newpos)solution=min(solutionorsize,1+sign*score[pos]-sign*score[newpos])returnvisited,solutiondefmain(s1,s2):score=[0if(posins1orposins2)elseNoneforposinrange(size)]unfinished=Truewhileunfinished:v1,v2=[],[]forposins1:v,solution=move(score,pos,1)v1+=vifsolution:print(score)print(f"Path found in {solution} moves !")unfinished=Falseforposins2:v,solution=move(score,pos,-1)v2+=vifsolution:print(score)print(f"Path found in {solution} moves !")unfinished=Falses1,s2=v1,v2main([start],[end])main([posforpos,heightinenumerate(map)ifheight==1],[end])
[^] # Re: python et lib de graph
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 12. Évalué à 2.
Ah, classe :)
J'ai rien de joli à montrer ce coup-ci.
Mais bon, journée présentiel au taf hier, trois heures dans la voiture, 4h en réunions, j'ai à peine eu le temps de bricoler une solution, en ayant réfléchi sur le trajet...
J'ai fait un parcours de graphe inventé à la volée : je n'ai jamais été fichu de retenir le moindre des algos de parcours que j'ai pu apprendre, alors je suis condamné à réinventer la roue !
J'ai des cases en entrée, je regarde pour chacune d'elles où elles peuvent aller (haut, bas, gauche, droite, si la différence de hauteur est bonne), et si je n'ai pas déjà été là (donc matrice des cases visitées avec distance au départ dedans).
Je note l'ensemble des cases nouvellement visitées, et j'itère sur cet ensemble.
Donc a priori inutile de stocker le score pour le retrouver et calculer la suite comme dans mon code plus bas : il suffit de compter les étapes.
Instinctivement, je me suis dis que ça pouvait grossir, et donc j'ai décidé de manger le problème par les deux bouts, donc j'explore en montant depuis "S" et en descendant depuis "E".
Je stocke des scores positifs en montant, et négatifs en descendant.
Si je rencontre une case visitée depuis l'autre bout (case négative si je monte ou positive si je descends), j'ai fait la liaison.
En pratique je peux m'arrêter là : si je suis en train de monter c'est étape*2+1, si je suis en train de descendre c'est étape*2+2.
Dans mon code j'additionne les valeurs absolues : la valeur que j'aurais dû mettre dans la case, et celle déjà présente, et j'ai mon résultat.
Pour l'exercice 2, comme je fournis déjà une liste de case par itération, il suffit de mettre comme liste de démarrage tout les "a" et le "S", vraiment rien à coder, la dernière ligne du programme et basta.
Ah, et j'ai aligné, je bosse sur un tableau à une dimension, au lieu d'une matrice.
Et les mouvements possibles ne sont pas (haut, bas, gauche droite) mais (-1, +1, -largeur, +largeur) et un mouvement doit être dans [0, taille[
Allez, trêve de blabla, code !