web-dev-qa-db-ja.com

アルゴリズムはプログラミング言語よりも重要ですか?

現在の(2013) Google Code Jam コンテスト中に、C++とJavaの人が200行以上のコードをPython 40行のコードだけを使用して同じ問題を解決した人々。

PythonはC++やJavaと直接比較することはできませんが、冗長性の違いがアルゴリズムの効率に影響を与える可能性があると考えました。

言語の選択と比較して、正しいアルゴリズムを知ることはどのくらい重要ですか?優れた実装PythonプログラムはC++またはJavaでより良い方法で(同じアルゴリズムを使用して)実装できます)これは自然な冗長性と関係がありますか特定のプログラミング言語の?

35

明らかに、Google Code Jamのような状況でこの質問を検討する場合、アルゴリズムの問​​題を解決する必要があるときは、アルゴリズムの考え方が明らかに重要です。

ただし、日常生活では、約100万の他の要因も考慮する必要があるため、問題は黒と白の比較ではるかに少なくなります。

単なる反例:Javaでさらに200行が必要だが、社内の全員がJavaを知っている場合、これは大した問題ではありません。 Pythonまたは他の言語の5行でそれを書くことができても、その言語を知っているのは社内で唯一の人でしょう-それは大きな問題です。実際、そうすることも許可されず、Javaで記述する必要があります。

職人の観点から、私たちは常に仕事に適したツールでアプローチしようとしますが、Word rightは非常にトリッキーなので、簡単に間違えることがあります。

それどころか、企業のアルゴリズム的思考はほとんどないことがわかりました。少数の選択した人だけがそれを所有していますが、平均的なジョーは、ループや検索などの実行時の複雑さを推定するのにすでに問題を抱えていることがよくあります。

ただし、アルゴリズムの競争に関しては、数年間の競争での個人的な経験から、1つの言語に固執する必要があることがはっきりとわかります。速度は重要な要素であり、制限時間内に問題を解決するためにそれを捧げる必要がある場合、ツールに時間を浪費する余裕はありません。また、200行のJavaコードを考えずに書くことは、50行の複雑なpythonコードを手作業で作成するよりもはるかに高速ですが、どちらも多かれ少なかれ同じ問題を解決します。

最後に、アルゴリズムの競争コードと会社の生産コードの主な違いを理解してください。私は製品で受け入れられないような恐ろしいコードを書いた素晴らしいアルゴリズムコーダーを見てきました。

73
Frank

私は、競争以外でも、特定の言語のすべてのトリックを知ることよりもアルゴリズム的思考の方が重要だと主張します。

もちろん、使用する言語をできるだけ知りたいのですが、言語は行き来しますが、アルゴリズムの観点から抽象的に考える能力は非常に移転可能なスキルです。

適例:私が正しく思い出せば、インタビューでFizzBu​​zzに失敗したことについて誰かが不満を述べ、Javaのモジュロ演算子に関する知識の欠如を非難したプログラマに関する投稿が少し前にありました。この結論は間違っています。moduloがどのように機能するかについての知識がないため、専用のmodulo演算子がない場合でも、アルゴリズムについて問題について考え、解決することができませんでした。さらに進んで:JavaにはTreeクラスがあります-将来、このクラスを実装していない言語を使用する必要がある場合はどうでしょうか?繰り返しになりますが、問題について考える能力が言語より優先されます固有の詳細。

例は単純化していることを認めますが、それらはポイントを全体に伝えるのに役立ちます。

17
ACEG

言語は重要です。

DARPAと米国海軍は、ほぼ20年前に shootout 実験を行いました。ダークホースの暴走の勝者はHaskellでした。 AdaとC++の両方が表現されました。 Javaではありませんでした。

ほぼ同時期に、 Pratt&Whitney は、ジェットエンジンコントローラープロジェクトのデータマイニング調査を行い、タイムカードとバグトラッカーのデータを調べました。彼らは、Adaがプログラマーの生産性を2倍、欠陥密度を他の言語の1/4にしたことを発見しました。

アタリは以前はFORTHを使用してビデオゲームを開発しており、彼らがFORTHを使用していたという事実は非常に独占的であると考えられていました。

LISPの使用に関するPaul Grahamの comments はよく知られています。 JPLのLISPに関するErann Gatの comments は、あまり知られていませんが、同等に説得力があります。

Boeing 777アビオニクスソフトウェア はほぼすべてのエイダです。主要な下請業者の1人が途中でやり直さなければならなかったとしても、彼らの経験は非常に良好でした。

言語は重要です。

14
John R. Strohm

いくつかのポイント:

  • 上位の位置はC++/C/Javaである傾向があり、それと他の言語との違いが何行のコードであるかにかかわらず。これは、おそらく彼らの生の速度のために、トップコーダーが他の言語よりもこれらの言語を選ぶ傾向があることの詳細かもしれません。
    残念ながら、Google Code Jamでプログラミング言語を簡単に確認することはできませんが、上位のものをいくつかダウンロードしました。覚えている限り、これらは主にC/C++です。 TopCoder (人気のあるオンラインプログラミングコンテストホスティングサイト)でも、ほとんど同じような結果になります。

  • それらはかなり低いレベルなので、生の実行時間の点でC/C++を簡単に打ち負かすことはないと確信しています(そしてJavaはtooはるかに遅れています)。私の経験から、動的に型付けされた言語は、静的に型付けされた言語よりも大幅に遅くなる傾向があります。一部の言語では最適なソリューションで十分な速度が得られない場合もありますが、これは一般的なルールではありません。

  • 適切なアルゴリズムが不可欠です。最初からすべての問題を(詳細に)解決する方法を知っていて、優れた高速コーダーであれば、どの言語でコーディングしても(その言語での最適なソリューションを想定している場合)、おそらく成功するでしょう。十分に高速です)。

  • 直線の数はそれほど大したことではありません。十分なプログラミング経験を得ると、10行または200行のプログラミングに10分を費やすことができることがわかります。すべての行がどれほど複雑であるかによって異なります。また、同様のコードを何百回もコード化している場合は、かなり迅速にコード化できます。上位のC/C++プログラマーがコーディング時間を最適化するためにしばしば使用するすべてのマクロについても言及しないでください。

  • フランクは良い点を述べています-(プログラミングの競争以外では)Pythonあなたの会社のコードベース全体がCか何かである場合、あなたは彼らに準拠する必要があります)でコーディングすることはできません言語。

  • 言語を切り替えるのはかなり簡単で、長年にわたるアルゴリズム的思考の知識を蓄積することは簡単ではありません。私は、ほぼすべての優秀なプログラマーが、たとえば1週間で別の(漠然と類似した)言語に切り替えることができると確信しています。多分、彼/彼女はその言語でのプログラミングコンテストに勝つには十分ではないでしょう(それをもう2週間与えてください)が、基本を失います。

7
Dukeling

同じロジックをC++でよりよく実装できますか?もちろんそれは可能ですが、もしあなたがより良いとすれば、より速く、より多くのメモリ効率を意味します。問題は、そのために必要な労力が大幅に増えることです。さらに、理論的には、より低いレベルに移行して純粋なCまたはASMに実装することもできますが、さらに時間がかかりますが、コードをさらに最適化することもできます。

もちろん、Code JamやTopCoderのようなコンペティションの場合、40行と200行しかないため、それほど大きな問題ではありません。一方、この種の競争で最も重要なのは、アルゴリズムの時間/空間の複雑さです。実際のアプリケーションであるYMMVでは、これらのタイプの競技O(n)で最も遅い言語で記述されたアルゴリズムは、常にO(n²)最速の言語で書かれています。特に、最悪のシナリオである複数のテストがあるでしょう。

しかし、競争を除けば、現実の大きなプロジェクトについて話している場合、それはもはや40行対200行ではありません。大きなプロジェクトでは、巨大なコードベースが問題になり始めます。その時点で、次のようになります。

C++ vs Python?

enter image description here

純粋なPythonは遅いです。そのため、標準Pythonインタプリタ(CPython)はCで書かれています。実質的にすべて、組み込み関数が高度に最適化されたCとして書かれています。 Pythonは、Cライブラリと組み合わせて簡単に使用することもできます( ctypes を介して、または ネイティブcpythonモジュール として)) Boost :: Python を介してC++ライブラリを使用することで、柔軟性のある言語であるPythonで高レベルのロジックを記述できるため、プロトタイピングと適応をすばやく行うことができます(つまり、アルゴリズムの調整と改善により多くの時間をかけることができます。OTOH、CまたはC++モジュールで低レベルのライブラリ関数を記述できます。そのようなアプローチの良い例は、Python library、it under ATLAS、LAPACK、Intel MKL、またはAMDのACMLなどの高度に最適化された数値ライブラリを使用するフード。

5
vartec

私の意見では、人々が口頭で「プログラミング言語」と考えるものは、実際には3つの別個のものです。

  1. 言語の種類と構文
  2. 言語IDE
  3. 言語に利用可能なライブラリ

たとえば、誰かがディスカッションでC#を取り上げた場合、彼/彼女は言語構文について話していると思うかもしれませんが(1)、そのディスカッションに.Netフレームワークが含まれることは95%確実です(3)。新しい言語を設計していない場合、(1)を分離して(2)と(3)を無視することは難しく、通常は無意味です。これは、IDEおよび標準ライブラリは「快適性の要因」であり、特定のツールの使用体験に直接影響するものだからです。

ここ数年、私もGoogle Code Jamに参加しました。入力を読み取るための素晴らしいサポートがあるので、私は初めてC++を選択しました。たとえば、C++の標準入力から3つの整数を読み取ると、次のようになります。

_int n, h, w;
cin >> n >> h >> w;
_

C#では、同じようになります:

_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#では、状況はさらに複雑になります。たぶん当時はもっと良い方法を見つけられなかっただけかもしれません。とにかく、ラウンド終了前に修正できないバグがあったので、最初のラウンドはパスできませんでした。皮肉なことに、入力読み取りメソッドはバグを難読化しました。問題は単純で、入力に32ビット整数には大きすぎる数値が含まれていました。 C#ではint.Parse(string)は例外をスローしますが、C++ではファイル入力ストリームが特定のエラーフラグを設定し、警告なしに失敗して、疑いを持たない開発者に問題を知らせません。

どちらの例も、言語構文ではなくライブラリの使用方法を示しています。最初の1つは冗長性を示し、もう1つは信頼性を示します。多くのライブラリは複数の言語に移植されており、一部の言語はそれら用に特別に構築されていないライブラリを使用できます(Python)に関する@vartecの回答を参照してください)。

これを締めくくるには、適切なアルゴリズムを知ることが役立ちます。特に、実行時間やメモリなどのリソースが意図的に制限されている場合は、コーディングコンテストで非常に重要です。アプリケーション開発ではそれは歓迎されますが、一般的に重要ではありません。そこでは保守性がより重要です。これは、適切な設計パターンを適用し、優れたアーキテクチャ、読み取り可能なコード、関連ドキュメントを用意することで実現できます。これらの方法はすべて、社内およびサードパーティのライブラリに大きく依存しています。だから、私はすでにどのような種類の車輪が発明されているのか、そしてどのようにそれらがどのように合うのかを知ることがより重要で、自分の車輪を作る方法を見つけます。

4
Emperor Orionii

任意のアルゴリズムを任意のプログラミング言語で実装できます。結局のところ、それは重要な構文ではありません。しかし、Pythonのような高水準言語を使用すると、独自の利点があります。作業が少なく、コーディング量も少なくなります。そのため、Pythonでアルゴリズムを実装するには、 Cのような低水準言語.

Pythonのライブラリには、ほとんどのデータ構造が組み込まれています。しかしCでは、ゼロから始めて、構造を使用してそれをすべて構築する必要があります。確かに、高水準言語と低水準言語の間には違いがありますが、この言語がアルゴリズムの実装を妨げるものであってはなりません。

2
Robin Thomas

「40 LoC vs 200 LoC」の例を外挿しながら、「まあ、全LoCの5分の1だけが明らかに高速で書かれているので、それが優れているに違いない」と思わせるかもしれませんが、そこには真実はほとんどないと思います。

最小限のLoCに最適化することは、私の考えではほとんど決して良いアイデアではありません。はい、書かれたすべてのLoCはバグの可能性があり、自分が書いたことがないものなどをデバッグする必要はありません。ポイントは、可読性と分離性を最適化することです。 1k LoCのモジュールを作成するのではなく、20行の大きな正規表現を使用して問題を解決するかどうかは関係ありません。正規表現は不透明な壁になり、非常にバグが発生しやすく、理解が困難で、悪夢のように、変更できない方法で動作を変更せずに変更できます。

値を追加しないボイラープレートと冗長性を取り除くことはすべてうまくいきますが、一方でJavaまたはC#のようなものを使用し、設計パターンとresharperのようなツールについての知識を持っていますSOコードのリファクタリング、時間の経過に伴うクリーンアップ、分解などの柔軟性が非常に高いため、はるかに小さいコードを記述した場合、はるかに困難になりますpythonスクリプトまたはRuby app。

非常にわかりやすい比較:20k pythonアプリだけではなく、戦略パターンやファクトリーなどの "過剰な"もので満たされた、テストでカバーされた分離されたC#コードの100k LoCが欲しいコードを5倍以上にするかどうかにかかわらず、アーキテクチャは毎日成功します。

一部の言語では一部の種類の作業がより簡単で便利であることに完全に同意しますが、必要なツールと要件が何であるかに基づいて言語を選択することのほうが信じられます(近い将来になるかもしれません)。

2
sara

時限プログラミングコンテストに参加したい場合は、コンテストで許可される最も表現力豊かな言語を学ぶ必要があります。おそらくPerlが最適で、次にRubyまたはPythonが続きます。アルゴリズムには優れた機能が必要ですが、少なくとも、

Integer prev = b.get(k)
if (prev == null) prev = 0
Integer v = a.get(k);
if (v == null) v = 0;
b.put(prev + v);

の代わりに

b[k] += a[k]

複数のライブラリを学習する必要はありません。それらはすべて非常によく似ており、ドキュメントはオンラインです。より表現力豊かな言語に堪能になると、表現力の低い言語でより優れた(しかしおそらくイライラする)プログラマーになります。反対は真実ではありません。

N.B.

200行のコードと40行のコードの違いは非常に大きく、200,000行のプログラムと40,000行のプログラムの違いはさらに大きくなります。次に、5人のチームと1人のマネージャーのチームの違いです。

2
kevin cline