Au cours du concours actuel (2013) Google Code Jam , un problème s'est produit avec C++ et Java personnes 200+ lignes de code par rapport à Python personnes qui ont résolu le même problème en utilisant seulement 40 lignes de code.
Python n'est pas directement comparable avec C++ et Java mais la différence de verbosité que je pensais pourrait peut-être avoir une influence sur l'efficacité de l'algorithme.
Quelle est l'importance de connaître le bon algorithme par rapport au choix de la langue? Un programme Python parfaitement implémenté pourrait-il être implémenté en C++ ou Java d'une meilleure façon (en utilisant le même algorithme) et cela a-t-il une relation avec la verbosité naturelle) de certains langages de programmation?
Évidemment, si vous considérez cette question dans le contexte de quelque chose comme Google Code Jam, la pensée algorithmique est clairement plus importante lorsque vous devez résoudre des problèmes algorithmiques.
Dans la vie quotidienne, cependant, environ un million d'autres facteurs doivent également être pris en compte, ce qui rend la question beaucoup moins noire que blanche.
Juste un contre-exemple: si vous avez besoin de 200 lignes supplémentaires en Java, mais que tout le monde dans votre entreprise connaît Java, ce n'est pas grave. Si vous pouviez l'écrire en 5 lignes de Python ou toute autre langue, mais vous seriez le seul dans l'entreprise à connaître cette langue - c'est une grosse affaire. Une si grosse affaire dans en fait, que vous ne serez même pas autorisé à le faire et que vous devrez l'écrire en Java.
Du point de vue d'un artisan, nous essayons toujours d'approcher avec le bon outil pour le travail, mais le mot à droite là-dedans est si délicat que l'on peut facilement se tromper.
Au contraire, j'ai trouvé la pensée algorithmique dans les entreprises presque absente. Seules quelques personnes choisies le possèdent, alors que le joe moyen a souvent du mal à estimer la complexité d'exécution des boucles, des recherches, etc.
En termes de compétitions algorithmiques, cependant, mon expérience personnelle de leur participation depuis plusieurs années, me dit clairement que vous devez vous en tenir à une seule langue. La vitesse est un facteur majeur et vous ne pouvez tout simplement pas vous permettre de perdre du temps sur vos outils, alors que vous devriez le consacrer à la résolution des problèmes dans le délai imparti. Considérez également que l'écriture de 200 lignes de code Java sans réfléchir est encore beaucoup plus rapide que de fabriquer à la main 50 lignes de code compliqué python nécessitant beaucoup de réflexion, mais les deux résolvent plus ou moins le même problème.
Oh et enfin, assurez-vous de comprendre les principales différences entre le code de compétition algorithmique et le code de production de l'entreprise. J'ai vu de fantastiques codeurs algorithmiques, qui ont écrit un code horrible que je n'accepterais jamais dans un produit.
Je dirais que, même en dehors des compétitions, la pensée algorithmique est plus importante que de connaître chaque astuce pour une langue spécifique.
Bien sûr, vous voulez connaître au mieux la langue avec laquelle vous travaillez, mais les langues vont et viennent, tandis que la capacité de penser de manière abstraite en termes d'algorithmes est une compétence hautement transférable.
Exemple: si je me souviens bien, il y a quelque temps, il y avait un article sur Programmers dans lequel quelqu'un se plaignait d'avoir échoué FizzBuzz dans une interview et lui reprochait son manque de connaissances sur l'opérateur modulo de Java. Cette conclusion est fausse - le manque de connaissances sur le fonctionnement de modulo l'a rendu incapable de penser algorithmiquement au problème et de le résoudre, même en l'absence d'un opérateur modulo dédié. Pour aller plus loin: Java a une classe Tree - et si, à l'avenir, vous deviez travailler avec un langage qui n'implémente pas cette classe? Encore une fois, la capacité de penser au problème l'emporte sur le langage -détails spécifiques.
J'admets que les exemples sont simplistes, mais ils aident à faire passer le message.
La langue compte.
La DARPA et l'US Navy ont fait une expérience fusillade il y a près de 20 ans. Le vainqueur en fuite du cheval noir était Haskell. Ada et C++ étaient tous deux représentés; Java ne l'était pas.
À peu près à la même époque, Pratt & Whitney a mené une étude d'exploration de données sur des projets de contrôleurs de moteurs à réaction, en examinant les données des fiches de présence et du suivi des bogues. Ils ont découvert qu'Ada donnait le double de la productivité du programmeur et 1/4 de la densité de défauts de tout autre langage qu'ils utilisaient.
Atari utilisait FORTH pour développer des jeux vidéo, et le fait qu'ils utilisaient FORTH était considéré comme extrêmement propriétaire.
commentaires de Paul Graham sur l'utilisation de LISP sont bien connus. Erann Gat commentaires sur LISP au JPL sont tout aussi convaincants, bien que moins connus.
Le logiciel avionique Boeing 777 est à peu près tout Ada. Leur expérience a été très bonne, même si un sous-traitant majeur a dû recommencer à mi-parcours.
La langue compte.
Des points:
Les premières positions ont tendance à être C++/C/Java, quel que soit le nombre de lignes de code la différence entre ce langage et un autre. Cela peut être davantage dû au fait que les meilleurs codeurs ont tendance à choisir ces langues par rapport à d'autres, probablement en raison de leur vitesse brute.
Malheureusement, vous ne pouvez pas facilement voir le langage de programmation sur Google Code Jam, mais j'ai téléchargé quelques-uns des meilleurs et, pour autant que je m'en souvienne, ce sont principalement C/C++. TopCoder (un site d'hébergement de concours de programmation en ligne populaire) a principalement des résultats similaires.
Parce qu'ils sont assez bas, je suis sûr que vous n'allez pas facilement battre C/C++ en termes de temps d'exécution brut (et Java ne suit pas aussi loin derrière). D'après mon expérience, les langages typés dynamiquement ont tendance à être beaucoup plus lents que les langages typés statiquement. La solution optimale n'est peut-être même pas assez rapide dans certaines langues, mais cela ne devrait pas être une règle générale.
Le bon algorithme est vital. Si vous saviez comment résoudre tous les problèmes (dans les moindres détails) dès le départ et que vous êtes un bon codeur rapide, vous gagnerez probablement, quelle que soit la langue dans laquelle vous codez (en supposant la solution optimale dans cette langue). est assez rapide).
Le nombre de lignes droites n'est pas si grave. Une fois que vous aurez suffisamment d'expérience en programmation, vous saurez que vous pouvez passer 10 minutes à programmer 10 lignes ou 200 lignes, tout dépend de la complexité des lignes. De plus, si vous avez codé des codes similaires des centaines de fois, vous pourrez le faire assez rapidement. Sans trop mentionner toutes les macros que les meilleurs codeurs C/C++ utilisent souvent pour optimiser leur temps de codage.
Frank fait une bonne remarque - (en dehors des compétitions de programmation), vous ne pouvez pas vous lancer dans le codage en Python pour votre entreprise si toute leur base de code est en C ou autre, vous devez vous conformer à leur Langue.
Il est raisonnablement facile de basculer entre les langues, il n'est pas facile d'acquérir des années de connaissances en pensée algorithmique. Je suis prêt à parier que presque n'importe quel excellent programmeur peut passer à une autre langue (vaguement similaire) dans, disons, une semaine. Peut-être qu'il/elle ne sera pas assez bon pour gagner des compétitions de programmation dans cette langue (donnez-lui encore 2 semaines), mais il aura les bases.
La même logique peut-elle être mieux implémentée en C++? Bien sûr, cela peut être le cas, si vous voulez dire plus rapide et plus efficace en mémoire. Le problème est que la quantité d'effort requise pour le faire est considérablement plus élevée. De plus, théoriquement, vous pourriez toujours aller à un niveau inférieur et l'implémenter en C pur ou même en ASM, ce qui prendrait encore plus de temps, mais vous pourriez avoir un code encore plus optimisé.
Bien sûr, dans le cas de compétitions comme Code Jam ou TopCoder, ce n'est pas un gros problème, car ce n'est que 40 lignes contre 200 lignes. Par contre dans ce type de compétition ce qui compte le plus c'est la complexité temps/espace de l'algorithme. Dans une application réelle, YMMV, dans ces types de compétitions O (n) l'algorithme écrit dans les langues les plus lentes battra toujours O (n²) écrit dans la plus rapide des langues. Surtout qu'il y aura plusieurs tests qui constituent le pire des cas.
Mais en dehors des compétitions, si nous parlons de gros projets dans la vraie vie, ce n'est plus 40 lignes vs 200 lignes. Dans les grands projets, l'énorme base de code commence à poser problème. À quel point vous arrivez à:
Pure Python est lent. C'est pourquoi l'interpréteur standard Python (CPython) est écrit en C. Pratiquement tous avec des fonctions intégrées écrites en C. hautement optimisé = Python peut également être facilement utilisé en conjonction avec les bibliothèques C (via ctypes ou comme modules cpython natifs ) et avec les bibliothèques C++ via Boost :: Python . De cette façon, vous pouvez écrire votre logique de haut niveau en Python, un langage flexible, permettant un prototypage et une adaptation rapides (ce qui signifie que vous pouvez passer plus de temps à peaufiner et améliorer votre algorithme). OTOH, vous peut écrire vos fonctions de bibliothèque de niveau inférieur dans le module C ou C++. Un bon exemple d'une telle approche est SciPy, qui est Python, mais sous le capot, il utilise des bibliothèques numériques hautement optimisées telles que ATLAS, LAPACK, Intels MKL ou ACML d'AMD.
À mon avis, ce que les gens considèrent familièrement comme un "langage de programmation" sont en fait trois choses distinctes:
Par exemple, lorsque quelqu'un évoque C # dans une discussion, vous pouvez penser qu'il/elle parle de la syntaxe du langage (1) mais il est certain à 95% que la discussion impliquera le framework .Net (3). Si vous ne concevez pas un nouveau langage, il est difficile et généralement inutile d'isoler (1) et d'ignorer (2) et (3). C'est parce que IDE et la bibliothèque standard sont des "facteurs de confort", des choses qui affectent directement l'expérience d'utilisation d'un certain outil.
Ces dernières années, j'ai moi aussi participé à Google Code Jam. La première fois, j'ai opté pour C++ car il a un bon support pour lire l'entrée. Par exemple, lire trois entiers à partir d'une entrée standard en C++ ressemble à ceci:
int n, h, w;
cin >> n >> h >> w;
En C #, la même chose ressemblerait à ceci:
int n, h, w;
string[] tokens = Console.ReadLine().Split(' ');
n = int.Parse(tokens[0]);
h = int.Parse(tokens[1]);
w = int.Parse(tokens[2]);
C'est beaucoup plus de frais généraux pour une fonctionnalité simple. Les choses deviennent encore plus compliquées en C # avec une entrée multiligne. Peut-être que je n'ai tout simplement pas trouvé de meilleur moyen à l'époque. Quoi qu'il en soit, je n'ai pas réussi le premier tour car j'avais un bug que je ne pouvais pas corriger avant la fin du tour. Ironiquement, la méthode de lecture d'entrée a obscurci le bogue. Le problème était simple, l'entrée contenait un nombre trop grand pour un entier 32 bits. En C # int.Parse(string)
lèverait une exception, mais en C++, le flux d'entrée de fichier définirait un certain indicateur d'erreur et échouerait sans que le développeur sans méfiance ne soit au courant d'un problème.
Les deux exemples montrent comment la bibliothèque a été utilisée plutôt que la syntaxe du langage. Le premier démontre la verbosité et l'autre démontre la fiabilité. De nombreuses bibliothèques sont portées dans plusieurs langues et certaines langues peuvent utiliser des bibliothèques qui ne sont pas spécialement conçues pour elles (voir la réponse de @ vartec à propos de Python avec les bibliothèques C).
Pour conclure, il est utile de connaître le bon algorithme. Dans les compétitions de codage, c'est crucial, surtout lorsque les ressources telles que le temps d'exécution et la mémoire sont volontairement limitées. Dans le développement d'applications, c'est bienvenu mais généralement pas crucial. La maintenabilité y est plus importante. Cela est possible en appliquant des modèles de conception corrects, en ayant une bonne architecture, un code lisible et une documentation pertinente et toutes ces méthodes dépendent fortement des bibliothèques internes et tierces. Donc, je trouve plus important de savoir quel type de roues est déjà inventé et comment s’adaptent-elles, puis comment fabriquer les miennes.
Tout algorithme peut être implémenté dans n'importe quel langage de programmation. Après tout, ce n'est pas la syntaxe qui compte. Mais utiliser un langage de haut niveau comme Python a ses propres avantages. Moins de travail et moins de codage. Donc, pour implémenter un algorithme en Python, vous aurez besoin de moins de lignes que ce qui est requis dans un langage de bas niveau comme C.
Python a la plupart des structures de données intégrées à sa bibliothèque. Mais en C, nous devons partir de zéro et utiliser une structure pour tout construire. Il existe certainement des différences entre le langage de haut niveau et le langage de bas niveau, mais le langage ne devrait pas vous empêcher de mettre en œuvre un algorithme.
En extrapolant l'exemple "40 LoC vs 200 LoC", en disant "eh bien, seulement un cinquième de la LoC totale est évidemment plus rapide à écrire, donc ça doit être mieux" peut sembler tentant, je pense vraiment qu'il y a peu de vérité à y trouver.
Optimiser pour le moins de LoC n'est presque jamais une bonne idée à mon avis. Oui, chaque LoC écrit est un potentiel pour les bugs, et vous n'avez jamais à déboguer ce que vous n'avez jamais écrit etcetc. Le point est d'optimiser la lisibilité et la découplage. Peu importe que vous résolviez un problème en utilisant une grande expression régulière de 20 lignes, par opposition à l'écriture d'un module de 1k LoC. Le regex sera un mur opaque, extrêmement sujet aux bogues, difficile à comprendre, cauchemardesque à modifier sans changer son comportement de manière non normative, etc.
Se débarrasser du passe-partout et de la verbosité qui n'ajoute aucune valeur est bien beau, mais d'un autre côté, utiliser quelque chose comme Java ou C #, avoir des connaissances sur les modèles de conception et des outils comme resharper vous permet SO beaucoup de flexibilité pour refactoriser le code, le nettoyer au fil du temps, décomposer les choses, etc., ce serait tout simplement beaucoup plus difficile si vous l'aviez écrit comme beaucoup plus petit python ou Ruby.
Une comparaison très révélatrice: je préfère avoir 100k LoC de code C # découplé couvert par les tests, rempli de trucs "excessifs" comme un modèle de stratégie, des usines, etc., plutôt qu'une application de 20k python qui ne fait que " fait avancer les choses ". 5 fois plus de code ou pas, l'architecture gagne chaque jour.
Je suis entièrement d'accord pour dire que certains types de travaux sont plus faciles et plus pratiques dans certaines langues, mais je crois plus dans le choix de votre langue en fonction des outils dont vous avez besoin et des exigences (et qui pourraient l'être dans un proche avenir).
Si vous voulez participer à des compétitions de programmation chronométrées, vous devez apprendre le langage le plus expressif autorisé dans la compétition. Perl serait probablement le meilleur, suivi de Ruby ou Python. Vous aurez toujours besoin d'une bonne facilité avec les algorithmes, mais au moins vous ne serez pas embourbé en écrivant quelque chose comme
Integer prev = b.get(k)
if (prev == null) prev = 0
Integer v = a.get(k);
if (v == null) v = 0;
b.put(prev + v);
au lieu de
b[k] += a[k]
Ne vous inquiétez pas d'apprendre plusieurs bibliothèques. Ils sont tous très similaires et la documentation est en ligne. La maîtrise de langues plus expressives fera de vous un meilleur programmeur (mais peut-être frustré) dans des langues moins expressives. L'inverse n'est pas vrai.
N.B.
La différence entre 200 lignes de code et 40 lignes de code est énorme, et elle est encore plus grande lorsque c'est la différence entre un programme de 200 000 lignes et un programme de 40 000 lignes. Ensuite, c'est la différence entre une équipe de cinq plus un manager et une équipe d'un ou deux.