Durante o atual concurso do Google Code Jam (2013) , houve um problema que levou mais de 200 linhas de código em C ++ e Java em comparação com as pessoas em Python que resolveram o mesmo problema usando apenas 40 linhas de código.
Python não é diretamente comparável com C ++ e Java, mas a diferença de verbosidade que pensei talvez pudesse ter uma influência na eficiência do algoritmo.
Quão importante é conhecer o algoritmo certo em comparação com a escolha do idioma? Um programa Python excelentemente implementado poderia ser implementado em C ++ ou Java de uma maneira melhor (usando o mesmo algoritmo) e isso tem alguma relação com a verbosidade natural de certas linguagens de programação?
java
c++
algorithms
python
superspacemarines
fonte
fonte
Respostas:
Obviamente, se você considerar essa pergunta no contexto de algo como o Google Code Jam, o pensamento algorítmico é claramente mais importante ao resolver problemas algorítmicos.
Na vida cotidiana, no entanto, cerca de um milhão de outros fatores também devem ser considerados, o que torna a questão muito menos preta versus branca.
Apenas um contra-exemplo: se você precisa de mais 200 linhas em Java, mas todos na sua empresa conhecem Java, isso não é grande coisa. Se você pudesse escrevê-lo em 5 linhas de Python ou em qualquer outro idioma, mas seria o único na empresa a conhecer esse idioma - é um grande negócio. Um negócio tão grande, de fato, que você nem poderá fazê-lo e, em vez disso, precisará escrevê-lo em Java.
Da perspectiva de um artesão, nós sempre tentar se aproximar com a ferramenta certa para o trabalho, mas a palavra certa lá é tão complicado que se pode facilmente obtê-lo errado.
Pelo contrário, achei o pensamento algorítmico nas empresas quase ausente. Apenas poucas pessoas selecionadas o possuem, enquanto o joe médio geralmente já tem problemas para estimar as complexidades do tempo de execução de loops, pesquisas etc.
Em termos de competições algorítmicas, no entanto, minha experiência pessoal de competir nelas por vários anos me diz claramente que você deve se ater a um idioma. A velocidade é um fator importante e você simplesmente não pode perder tempo com suas ferramentas, quando deve dedicá-lo à solução dos problemas dentro do prazo. Considere também que escrever 200 linhas de código Java sem pensar ainda é muito mais rápido do que criar 50 linhas de código python complicado, exigindo muito pensamento, mas resolvendo mais ou menos o mesmo problema.
Ah, e finalmente, certifique-se de entender as principais diferenças entre o código algorítmico da concorrência e o código de produção da empresa. Vi codificadores algorítmicos fantásticos, que escreviam códigos horríveis que eu nunca aceitaria em um produto.
fonte
Eu argumentaria que, mesmo fora das competições, o pensamento algorítmico é mais importante do que conhecer todos os truques para um idioma específico.
É claro que você deseja conhecer o idioma com o qual trabalha da melhor maneira possível, mas os idiomas vêm e vão, enquanto a capacidade de pensar abstratamente em termos de algoritmos é uma habilidade altamente transferível.
Caso em questão: se bem me lembro, havia um post aqui nos programadores há um tempo atrás em que alguém se queixou de ter falhado no FizzBuzz em uma entrevista e culpou seu desconhecimento sobre o operador de módulo do Java por isso. Esta conclusão está errada - a falta de conhecimento sobre como o módulo funciona o tornou incapaz de pensar algoritmicamente sobre o problema e resolvê-lo, mesmo na ausência de um operador de módulo dedicado. Indo além: Java possui uma classe Tree - e se, no futuro, você precisar trabalhar com uma linguagem que não implementa essa classe? Novamente, a capacidade de pensar sobre o problema supera os detalhes específicos do idioma.
Admito que os exemplos são simplistas, mas ajudam a esclarecer o assunto.
fonte
A linguagem é importante.
A DARPA e a Marinha dos EUA fizeram um experimento de tiroteio há quase 20 anos. O vencedor da corrida de cavalos negros foi Haskell. Ada e C ++ estavam ambos representados; Java não era.
Na mesma época, a Pratt & Whitney fez um estudo de mineração de dados em projetos de controladores de motores a jato, analisando dados de cartões de ponto e rastreadores de erros. Eles descobriram que Ada dava o dobro da produtividade do programador e 1/4 da densidade de defeitos de qualquer outro idioma que estavam usando.
A Atari costumava usar o FORTH para desenvolver videogames, e o fato de eles estarem usando o FORTH era considerado extremamente proprietário.
Os comentários de Paul Graham sobre o uso do LISP são bem conhecidos. Os comentários de Erann Gat sobre o LISP no JPL são igualmente convincentes, embora não sejam tão conhecidos.
O software aviônico Boeing 777 é praticamente todo Ada. A experiência deles foi muito boa, apesar de um grande subcontratado ter que começar de novo no meio do fluxo.
A linguagem é importante.
fonte
Alguns pontos:
As primeiras posições tendem a ser C ++ / C / Java, independentemente de quantas linhas de código a diferença entre essa e outra linguagem. Talvez isso aconteça porque os principais codificadores tendem a escolher esses idiomas em detrimento de outros, provavelmente por causa de sua velocidade bruta.
Infelizmente, você não consegue ver facilmente a linguagem de programação no Google Code Jam, mas baixei algumas das principais e, tanto quanto me lembro, elas são principalmente em C / C ++. O TopCoder (um popular site de hospedagem de concursos de programação on-line) geralmente apresenta resultados semelhantes.
Porque eles são bastante baixo nível, eu tenho certeza que você não vai facilmente bater C / C ++ em termos de tempo de execução crua (e Java de não arrastar muito longe atrás). De acordo com minha experiência, os idiomas tipificados dinamicamente tendem a ser significativamente mais lentos que os idiomas estaticamente. A solução ideal pode até não ser rápida o suficiente em alguns idiomas, mas isso não deve ser uma regra geral.
O algoritmo certo é vital. Se você soube resolver todos os problemas (em detalhes) desde o início e é um codificador bom e rápido, provavelmente vencerá, independentemente do idioma em que codificar (assumindo a solução ideal nesse idioma) é rápido o suficiente).
O número direto de linhas não é grande coisa. Depois de obter experiência de programação suficiente, você saberá que pode gastar 10 minutos programando 10 linhas ou 200 linhas, tudo depende da complexidade das linhas. Além disso, se você codificou código semelhante centenas de vezes, poderá fazê-lo rapidamente. Sem mencionar também todas as macro que os principais codificadores C / C ++ costumam usar para otimizar seu tempo de codificação.
Frank faz um bom argumento - (fora das competições de programação), você não pode codificar em Python para sua empresa se toda a sua base de códigos estiver em C ou o que for, você precisa estar em conformidade com a linguagem deles.
É razoavelmente fácil alternar entre idiomas, não é fácil criar anos de conhecimento de pensamento algorítmico. Estou disposto a apostar que quase qualquer programador excelente pode mudar para outra linguagem (vagamente semelhante) em, digamos, uma semana. Talvez ele / ela não seja bom o suficiente para vencer competições de programação nesse idioma (aguarde mais 2 semanas), mas tenha o básico.
fonte
A mesma lógica pode ser implementada melhor em C ++? Claro que pode, se por melhor você quer dizer mais rápido e mais eficiente em termos de memória. O problema é que a quantidade de esforço necessária para isso é significativamente maior. Além disso, teoricamente, você ainda pode diminuir o nível e implementá-lo em C puro ou mesmo ASM, o que levaria ainda mais tempo, mas você poderia ter um código ainda mais otimizado.
Obviamente, no caso de competições como Code Jam ou TopCoder, não é nada demais, pois são apenas 40 linhas versus 200 linhas. Por outro lado, nesse tipo de competição, o que mais importa é a complexidade de tempo / espaço do algoritmo. Enquanto na aplicação da vida real, YMMV, nesses tipos de competições, o algoritmo O (n) escrito nas linguagens mais lentas sempre supera O (n²) escrito nas linguagens mais rápidas. Especialmente que haverá vários testes que são o pior cenário.
Mas, além das competições, se estamos falando de grandes projetos da vida real, não são mais 40 linhas versus 200 linhas. Em grandes projetos, uma enorme base de código começa a ser um problema. Nesse ponto, você chega a:
C ++ vs Python?
O Python puro é lento. É por isso que o interpretador Python padrão (CPython) é escrito em C. Praticamente todos com funções internas escritas como C. altamente otimizadas C. Python também pode ser facilmente usado em conjunto com bibliotecas C (via ctypes ou como módulos cpython nativos ) e com bibliotecas C ++ via Boost :: Python . Dessa forma, você pode escrever sua lógica de alto nível em Python, uma linguagem flexível, que permite prototipagem e adaptação rápidas (o que significa que você pode gastar mais tempo aprimorando e aprimorando seu algoritmo). OTOH, você pode escrever suas funções de biblioteca de nível inferior no módulo C ou C ++. Um bom exemplo dessa abordagem é o SciPy, que é a biblioteca Python, mas, sob o capô, usa bibliotecas numéricas altamente otimizadas, como ATLAS, LAPACK, Intels MKL ou ACML da AMD.
fonte
Na minha opinião, o que as pessoas consideram coloquialmente como "linguagens de programação" são na verdade três coisas distintas:
Por exemplo, quando alguém menciona C # em uma discussão, você pode pensar que está falando sobre sintaxe de linguagem (1), mas é 95% certo de que a discussão envolverá a estrutura .Net (3). Se você não está projetando um novo idioma, é difícil e geralmente inútil isolar (1) e ignorar (2) e (3). Isso ocorre porque o IDE e a biblioteca padrão são "fatores de conforto", coisas que afetam diretamente a experiência do uso de uma determinada ferramenta.
Nos últimos anos, eu também participei do Google Code Jam. Na primeira vez, optei pelo C ++ porque ele possui um bom suporte para a leitura da entrada. Por exemplo, a leitura de três números inteiros de uma entrada padrão em C ++ se parece com isso:
Enquanto em C #, o mesmo ficaria assim:
Isso representa muito mais sobrecarga mental para uma funcionalidade simples. As coisas ficam ainda mais complicadas em C # com entrada de várias linhas. Talvez eu simplesmente não tenha descoberto uma maneira melhor naquela época. De qualquer forma, não consegui passar na primeira rodada porque tinha um bug que não consegui corrigir antes do final da rodada. Ironicamente, o método de leitura de entrada ofuscou o bug. O problema era simples, a entrada continha um número muito grande para um número inteiro de 32 bits. Em C #
int.Parse(string)
lançaria uma exceção, mas em C ++ o fluxo de entrada de arquivo definiria um certo sinalizador de erro e falharia silenciosamente, tornando o desenvolvedor desavisado inconsciente de um problema.Ambos os exemplos demonstram como a biblioteca foi usada e não a sintaxe da linguagem. Primeiro demonstra a verbosidade e o outro demonstra a confiabilidade. Muitas bibliotecas são portadas para vários idiomas e alguns idiomas podem usar bibliotecas que não foram criadas especificamente para eles (consulte a resposta da @ vartec sobre o Python com bibliotecas C).
Para finalizar, saber o algoritmo certo ajuda. Nas competições de codificação, é crucial, especialmente quando recursos como tempo de execução e memória são propositadamente limitados. No desenvolvimento de aplicativos, é bem-vindo, mas geralmente não é crucial. A manutenção é mais importante lá. Isso pode ser alcançado aplicando padrões de design corretos, com boa arquitetura, código legível e documentação relevante, e todos esses métodos dependem muito das bibliotecas internas e de terceiros. Portanto, acho mais importante saber que tipo de rodas já foram inventadas e como elas se encaixam, e como fazer as minhas.
fonte
Main
e poucas coisas dentro doMain
método (instância da minha classe de entrada e o fluxo de saída e loop de caso).Se você deseja competir em competições de programação programada, deve aprender a linguagem mais expressiva permitida na competição. Perl provavelmente seria o melhor, seguido por Ruby ou Python. Você ainda precisará de boas instalações com algoritmos, mas pelo menos não ficará atolado escrevendo algo como
ao invés de
Não se preocupe em aprender várias bibliotecas. Eles são todos muito parecidos e a documentação está online. Tornar-se fluente em idiomas mais expressivos fará de você um programador melhor (mas possivelmente frustrado) em idiomas menos expressivos. O oposto não é verdadeiro.
NB
A diferença entre 200 linhas de código e 40 linhas de código é enorme e é ainda maior quando é a diferença entre um programa de 200.000 linhas e um programa de 40.000 linhas. Então é a diferença entre uma equipe de cinco pessoas e um gerente e uma equipe de um ou dois.
fonte
Qualquer algoritmo pode ser implementado em qualquer linguagem de programação. Afinal, não é a sintaxe que importa. Mas usar uma linguagem de alto nível como Python tem suas próprias vantagens. Menos trabalho e menos quantidade de codificação. Portanto, para implementar um algoritmo em Python, você precisará de menos linhas do que o necessário em uma linguagem de baixo nível como C.
O Python possui a maioria das estruturas de dados incorporadas à sua biblioteca. Mas em C, precisamos começar do zero e usar uma estrutura para construir tudo. Certamente, existem diferenças entre a linguagem de alto e baixo nível, mas a linguagem não deve impedi-lo de implementar qualquer algoritmo.
fonte
Embora extrapolar o exemplo "40 LoC vs 200 LoC", dizendo "bem, apenas um quinto do LoC total é obviamente mais rápido de escrever, portanto deve ser melhor" pode parecer tentador, eu realmente acho que há pouca verdade a ser encontrada lá.
Otimizar para menos LoC quase nunca é uma boa ideia na minha opinião. Sim, todo LoC escrito é um potencial para erros, e você nunca precisa depurar o que nunca escreveu etcetc. A questão é otimizar para facilitar a leitura e a dissociação. Não importa se você resolver um problema usando um grande regex de 20 linhas, em vez de escrever um módulo de 1k LoC. O regex será uma parede opaca, extremamente propensa a bugs, difícil de entender, pesadelo para alterar sem alterar seu comportamento de maneiras inaceitáveis, etc.
Livrar-se da clichê e da verbosidade que não agregam valor é muito bom, mas, por outro lado, usar algo como Java ou C #, ter conhecimento sobre padrões de design e ferramentas como o re-afiador, permite tanta flexibilidade na refatoração do código , limpá-lo com o tempo, quebrar coisas etc., isso seria MUITO mais difícil se você o tivesse escrito como um script python ou aplicativo ruby muito menor.
Uma comparação muito reveladora: eu preferiria ter 100k LoC de código C # dissociado coberto por teste, preenchido com coisas de "exagero", como padrão de estratégia, fábricas etc., em vez de um aplicativo python de 20k que apenas "faz as coisas". 5 vezes mais código ou não, a arquitetura vence todos os dias.
Concordo plenamente que alguns tipos de trabalho são mais fáceis e convenientes em alguns idiomas, mas acredito mais na escolha do seu idioma com base em quais ferramentas você precisa e quais são os requisitos (e podem ser no futuro próximo).
fonte