Une journĂ©e de repos aura fait le plus grand bien Ă mes neurones. Non seulement jâai rĂ©ussi Ă comprendre la partie 2 de ce jour, mais jâai repris de zĂ©ro le jour 12, jâai fait simple et ça passe en moins dâ une seconde ![]()
Une journĂ©e 16 Ă©galement sans difficultĂ© particuliĂšre. Câest surprenant, en gĂ©nĂ©ral les problĂšmes du week-end lors des deux derniĂšres semaines sont plutĂŽt corsĂ©s.
Bon ben week-end Ă tous alors ![]()
Oui, pas de piĂšge sur ce jour 16. Va-t-on prendre cher demain ? ![]()
Pas eu de soucis si ce nâest une erreur entre un + et un - qui mâa retardĂ©. Câest bien du brute force quâil faut faire pour la partie 2 (ça me prend 11s
) ?
Le brute force marche trĂšs bien oui. Juste une grosse seconde pour moi pour la partie 2 Ă essayer chaque entrĂ©e, sans ajouter dâoptimisation particuliĂšre par rapport Ă la partie 1.
Jâai aussi tendance Ă nâutiliser que des structures « lourdes » (genre je prĂ©fĂšre une Map<Pair<Int, Int>, Char> plutĂŽt quâun tableau 2D de Char, faut pas chercher), mais comme je fais ça en Kotlin câest beaucoup moins punitif que le Python niveau perf.
Moi aussi, parcours systĂ©matique de toutes les entrĂ©es, pas dâoptimisation sur un cache des chemins.
Et utilisation dâun bon vieux dict. 2.6s en python sur proc de 5 ans.
â part 1 (0.006s): 7632
â part 2 (2.591s): 8023
Day 16
edit
â part 2 (1.548s): 8023 : jâavais laissĂ© des deepcopy qui ne servent a rien. 1s de gagnĂ©! ![]()
Pour le coup je stock un set de (int, int, str) (i,j, direction) les parties visitĂ©es. Je vais voir si je peux faire mieux si jâai le temps.
Edit: en changeant une queue.Queue pour une collection.deque ça va 10x plus vite jâai lâimpression. Je ne vais pas chercher plus ![]()
Oui Jour 16 ça se brute force bien, idem entre 1 et 2 secondes sur mon vénérable pc portabe de 2015.
Jour 17 pas de problĂšme particulier. Jâavais peur au dĂ©but la partie 1 ramait beaucoup, mais je testais plusieurs fois les mĂȘmes possibilitĂ©.
Pour la partie 2 ça tourne en 2-3 sec, et pas besoin de retoucher Ă beaucoup de code pour y arriver. Bref pas de piĂšge aujourdâhui
Hmm moi je bloque sur 1 : je tente un Dijkstra, en ajoutant une condition sur les voisins non visitĂ©s. Quand jâarrive sur une position, je regarde les 3 prĂ©dĂ©cesseurs. Sâils sont tous sur la mĂȘme colonne ou ligne, alors je suis obligĂ© de tourner. Sur lâexemple, jâobtiens 127 comme rĂ©sultat, donc pas bon.
Je bloque aussi sur la partie 1.
Jâai essayĂ© un algo maison au dĂ©but, mais sans grande surprise ça part vite en sucette.
Ce qui me gĂȘne câest que sur lâexample le chemin ne se recoupe jamais, alors que je pense quâen thĂ©orie il devrait ĂȘtre possible dâavoir un trajet optimal qui passe plusieurs fois sur une mĂȘme case - et je nâose pas partir sur un Dijsktra « standard » (ou modifiĂ© comme le tient) qui ne prendrait a priori pas en compte cette possibilitĂ©.
Je pense que ça vient du fait que si tu gardes les 3 derniers trajets dâun node « optimal », tu vas te couper des routes alors quâune arrivĂ©e sur le mĂȘme node avec un moins bon score (dĂ©jĂ Ă©liminĂ© chez toi) permettrait de continuer tout droit par un chemin meilleur au final.
Peut-ĂȘtre quâil faudrait exploser chaque node du graphe en sous-node diffĂ©rente selon la direction dâarrivĂ©e et le nombre de pas dans cette direction prĂ©cĂ©dents.
.
Oui jâai fait ça. Je garde un Ă©tat qui est la position, la direction en cours et le nombre de fois successives que je suis cette direction. Et ça aide pour la partie 2.
Et oui, il ne faut pas se couper dâune arrivĂ©e sur un noeud en gardant uniquement lâarrivĂ©e optimale.
Un pattern frĂ©quent est quâon veut aller tout droit, mais la limite de 3 impose de faire un pas de cĂŽtĂ©, dâavancer dâun cran et de revenir sur la trajectoire initiale.
Et pas de boucle constatĂ© dans mon cas. Dâailleurs je ne vois pas comment ça pourrait se produire. Sur la partie 2 Ă la rigueur, mais le coĂ»t de faire la boucle sera trop grand je pense par rapport Ă une autre solution.
Je vois la limite de mon approche, sur un exemple simple
11111
21191
ça ne marche pasâŠ
Formalisme
En rĂ©flĂ©chissant, est-ce que les noeuds devraient donc ĂȘtre (i, j, dir, k), tous initialisĂ©s avec une distance max (avec dir entre 0 et 3) ? Et ensuite, pour chaque noeud, je trouve celui de distance min pas encore visitĂ©, et je mets Ă jour les voisins potentiels ? Jâai pas lâimpression que ça va marcher ![]()
Edit: je mâen suis sorti : il faut changer un peu lâalgo de Dijkstra pour en remettre dans la boucle si nĂ©cessaire. Une fois que jâai compris ça, le reste dĂ©roule simplement. Et la partie 2 se fait bien si on stock la direction et le nombre de pas dĂ©jĂ fait.
Oui, mais chez moi chaque noeud doit ĂȘtre dupliquĂ© avec la distance k entre 1 et 3 (pas 0 et 3) vu que câest le nombre de cases parcourues dans cette distance sans tourner, et ce pour chacunes de 4 directions. Du coup quand tu vas insĂ©rer un nouveau noeud, il aura toujours dĂ©jĂ parcouru une case dans cette direction. Ăa donne donc 12 noeuds pour chaque case dans le graphe Ă©clatĂ© sur lequel on fait ensuite tourner Dijkstra.
Et pas de souci concernant ma rĂ©serve sur le fait que Dijkstra ne couvre pas les chemins se coupant: Ăa marche tout Ă fait, car un chemin optimal se recoupera forcĂ©ment selon des directions perpendiculaires - et comme les directions sont diffĂ©rentes, ce sont donc 2 noeuds diffĂ©rents dans le graphe « Ă©clatĂ© », donc pas de souci, aucun noeud du graphe Ă©clatĂ© ne doit ĂȘtre parcouru 2 fois par le chemin optimal.
Sinon pour la partie 2 jâai galĂ©rĂ© un peu en oubliant le fait que le wagon ne peut pas sâarrĂȘter sur la case finale sans avoir parcouru au moins 4 cases dans la mĂȘme direction. Heureusment que le deuxiĂšme exemple mâa aidĂ© Ă identifier le problĂšme !
En effet je nâai pas trouvĂ© de cas avec une boucle pour ces rĂšgles du problĂšme. Jâai Ă©tĂ© un peu trop prĂ©cautionneux car je mâattendais Ă une partie 2 du genre « maintenant les wagons doivent toujours tourner du mĂȘme cĂŽtĂ© », ce qui aurait rendu possible les cycles sur le chemin optimal.
Et donc le code que jâai oubliĂ© de poster. Pour ceux que ça intĂ©resse, jâai mis pas mal de commentaires si vous bloquez et que vous cherchez Ă comprendre.
17.1 faite en sâinspirant du jour 10 pour intĂ©rieur/extĂ©rieur, par contre jâai peur que le brute force ne fonctionne pas pour la partie 2. Il va falloir rĂ©flĂ©chirâŠ
Je me prend grave la tĂȘte sur la partie 2 du jour 18. Je suis sĂ»r quâil doit y avoir un moyen plus simple que ce que je tente, quitte Ă faire un peu de brute force, mais jâhĂ©site Ă tout reprendre de zĂ©ro⊠Dans tous les cas câest trĂšs intĂ©ressant comme problĂšme !
Jâai une idĂ©e que je nâarrive pas Ă mettre en oeuvre:
Idée
On rĂ©cupĂšre les segments horizontaux et verticaux sĂ©parĂ©ment. On rĂ©cupĂšre aussi tous les corners, on met les x dans abs, et les y dans ord. Ensuite, on teste chaque rectangle possible avec les x dans abs et ord. Pour chaque rectangle, on calcule son centre, et on regarde combien de segments horizontaux il intersecte en haut, si impair on regarde combien de verticaux Ă gauche, si impair on ajoute lâair du rectangle. Mais je dois me planter dans des indices
Câest vraiment la galĂšre avec les indices. Jâai choisi une approche encore moins simple:
Idée
- Je stocke tous les coins (points) dans une liste.
- Je cherche le point le plus en haut puis le plus Ă gauche de la forme
- JâĂ©crase cette excroissance jusquĂ arriver au prochain coins, je calcule lâaire du rectangle ainsi Ă©crasĂ©. Faut faire gaffe Ă bien tout calculer quand ça fait une ligne qui sort de la forme en bas de lâĂ©crasement.
- Rebelotte jusquâĂ arriver Ă un rectangle.
- Câest plus corsĂ© si il y a une boucle Ă lâintĂ©rieur du rectangle que jâĂ©crase - dans ce cas, aprĂšs avoir ajoutĂ© lâaire du rectangle Ă©crasĂ©, ça va me faire deux circuits fermĂ©s de part et dâautre de la boucle, et jâutilise le mĂȘme algo pour calculer lâaire de chacun
LĂ jâen suis au cas oĂč je tombe sur une boucle en Ă©crasant le rectangle, je mâembrouille de partout mais jâavance petit Ă petit !