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


35

現在(2013年)のGoogle Code Jamコンテストでは、40行のコードのみを使用して同じ問題を解決したPythonの人々と比較して、C ++およびJavaの人々が200行以上のコードを必要とする問題がありました。

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

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


16
あなたが働いているプログラミング言語は、あなたが問題について考える方法に影響を与えると言われています(そして私は信じています)。これは、非常に異なるプログラミング言語がさまざまなクラスの問題に適していることを意味します。
ジョリスティマーマンズ

1
これの多くは、LOCを超えて作業している規模に完全に依存します。一部の言語は、速度または同時実行性のニーズをサポートしていません。アルゴリズムは重要ですが、言語xが言語zのy倍遅い場合、冗長性に関係なくxを使用できない場合があります。
リグ

注として、私が学校で学んだ唯一のことは、コードの行ごとに、使用されるコードに関係なく一定のままであるバグがあることです。したがって、より少ないコード行でそれを行うことができる言語がより少ないバグをもたらす場合、それをより速く市場に出すことができ、ユーザーがそれを使用しているときにバグが現れる可能性が少なくなります。したがって、私の意見では、そのプロジェクトに取り組むために必要な社内の他の誰もが知っている仕事に最適な言語を選択します。
トラビスペセット

5
@Travis:「SLOCレートごとの欠陥は、言語に関係なく一定のままです」とは言えません。ジョンの答えをご覧ください。
ベンフォークト

今度は、F#を言語として使用して次のコンテストに参加することを考えています。
code4life

回答:


73

明らかに、Google Code Jamなどのコンテキストでこの質問を検討する場合、アルゴリズムの問​​題を解決する必要がある場合、アルゴリズムの考え方が明らかに重要になります。

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

単なる反例:Javaでさらに200行が必要なのに、会社の全員がJavaを知っている場合、これは大したことではありません。5行のPythonまたは他の言語でそれを書くことができるが、その言語を知っているのはあなただけである場合-それは大したことです。実際、あなたはそうすることさえ許されず、代わりにJavaでそれを書かなければならないほど大したことです。

職人の観点から、我々は常に仕事のための適切なツールとアプローチを試みるが、単語そこには1つが簡単にそれは間違って得ることができるように注意が必要です。

それどころか、私は企業のアルゴリズム的思考がほとんどないことを発見しました。少数の選択した人だけがそれを所有していますが、平均的なジョーはしばしばループ、検索などの実行時の複雑さを推定するのに苦労しています。

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

最後に、アルゴリズムの競合コードと企業の生産コードの主な違いを理解してください。私は素晴らしいアルゴリズムのコーダーを見てきましたが、それは私が製品で受け入れることのない恐ろしいコードを書いたものです。


1
+「考慮すべきその他の数百万の要因」の場合は1
ozz

1
これに加えて、もしそれがあなたが解決しようとしている機能的な問題なら、天国のために、関数型言語を使用してください!だから、私はあなたが本当に主要なプログラミングパラダイムごとに1つの言語を固執すべきだと主張したいと思います。
マーティンヴェルブルク

6
最後の文に+1。
シヴァンドラゴン

4
+1行のコードはそれ自体がひどいメトリックです。コードの行ではなく、保守性を測定する必要があります。200行のタイプセーフコードは、50行のPythonよりもはるかに保守しやすい可能性があります。
フィル

2
@Phil:そして​​、200行のPythonは、50行のタイプセーフコードよりもはるかに保守性が高い可能性があります。よく書かれたコードを想定して、タイプセーフな言語でそのような明快さの利点を見たことはありません。
デビッドソーンリー

17

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

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

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

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


14

言語が重要です。

DARPAと米海軍は、ほぼ20年前に銃撃戦の実験を行いました。ダークホースの暴走の勝者はハスケルでした。AdaとC ++の両方が表されました。Javaはそうではありませんでした。

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

AtariはかつてFORTHを使用してビデオゲームを開発していましたが、FORTHを使用しているという事実は非常に独占的であると考えられていました。

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

ボーイング777のアビオニクスソフトウェアは、ほとんどすべてのAdaです。ある大手下請け業者が途中でやり直さなければならなかったにもかかわらず、彼らの経験は非常に良かった。

言語が重要です。


明らかに、リンク先の実験の後、javaがリリースされました。
toasted_flakes

この記事は1994年にリリースされました。Javaの最初の公開リリースは1995
。–アレッサンドロテルッツィ

重要なのは、特定のお気に入りの言語が特定の実験で表された、または表されなかったということではありません。ポイントは、その言語が重要です。多くの逸話的な研究があり、これはかなり決定的に示されています。また、アメリカのプログラマーにほとんど拒否されているにもかかわらず、Adaはヨーロッパ、特に高信頼性システムで依然として頻繁に使用されており、米国の特定のフィールドシステムで使用されていることも注目に値します。
ジョンR.ストローム

7

いくつかのポイント:

  • 最上位は、他の言語との違いがコードの行数に関係なく、C ++ / C / Javaになる傾向があります。これはおそらく、トップのコーダーが他のいくつかの言語よりもこれらの言語を選択する傾向があるということです。
    残念ながら、Google Code Jamでプログラミング言語を簡単に見ることはできませんが、いくつかの上位の言語をダウンロードしましたが、私が覚えている限りでは、これらはほとんどがC / C ++です。TopCoder(人気のあるオンラインプログラミングコンテストホスティングサイト)のほとんどの結果は似ています。

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

  • 適切なアルゴリズムが不可欠です。最初からすべての問題を(詳細に)解決する方法を知っていて、優れた高速コーダーであれば、コーディングする言語に関係なく勝つ可能性が最も高くなります(その言語の最適なソリューションを前提としています)十分に高速です)。

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

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

  • 言語を切り替えるのはかなり簡単で、長年にわたるアルゴリズム思考の知識を蓄積するのは簡単ではありません。ほとんどの優秀なプログラマーが、1週間以内に別の(漠然と似た)言語に切り替えることができると信じています。たぶん、彼/彼女はその言語でのプログラミング競技に勝つのに十分ではないかもしれませんが(さらに2週間与えます)、基本はダウンします。


虚偽:いくつかのコードコンテストサイトからいくつかのソリューションをダウンロードすることは、トップポジションがどのようなものであるかを実際に知っていると結論付けるのに十分な決定的な科学的研究です。
ライライアン

@LieRyan本当ですが、(おそらく)最も人気のあるそのようなサイト(TopCoder)で(私が持っているように)数十のプログラミングコンペティションに参加し、常にトップの位置の大部分をC / C ++ / Javaと見なすことはかなり重要です。また、「常にある」ではなく「傾向がある」と言いました。
ダケリング

「直線の数がそれほど大したことではない」ことに同意しない。コードは敵です
jk。

6
@jk。「そのような」を強調表示すべきでしたか?それは重要ですが、アルファやオメガではありません。読みやすさよりも数行少ないほうがいいですか?しないでください。非常にわかりにくい、判読できない、ビットシフト、乗算、除算、加算、減算、XOR、AND、多条件式については、いつでも簡単なifステートメントをいくつか取り上げます。おそらくあなたが話していたことではないかもしれませんが、それが行数を減らすことになることもあります。そして、数行で複雑なものを実装すること、または多くの行で単純なものを実装することについてもっと話していました。後者のほうが時間がかからないことがよくあります。
ダケリング

5

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

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

しかし、競争を別にすれば、実際の大きなプロジェクトについて話している場合、40行対200行ではなくなりました。大きなプロジェクトでは、巨大なコードベースが問題になり始めます。その時点で、次のことができます。

C ++ vs Python?

ここに画像の説明を入力してください

純粋なPythonは遅いです。標準のPythonインタプリタ(CPythonの)も容易に(VIA Cライブラリと組み合わせて使用することができる高度に最適化されたC. Pythonのように書かれた機能を内蔵して実質的にすべてのCで書かれている理由ですctypesの又は天然CPythonのモジュール)とCと++ライブラリBoost :: Python経由。このようにして、柔軟性の高い言語であるPythonで高レベルのロジックを記述でき、迅速なプロトタイピングと適応が可能になります(つまり、アルゴリズムの調整と改善により多くの時間を費やすことができます)。OTOH、低レベルのライブラリー関数をCまたはC ++モジュールで作成できます。そのようなアプローチの好例は、PythonライブラリーであるSciPyですが、内部ではATLAS、LAPACK、Intels MKL、AMDのACMLなどの高度に最適化された数値ライブラリーを使用しています。


あなたが書いているものは表面をこすっているだけです。誰もが共有するとは限らないという「より良い」という概念を想定しています。品質は常に自分の目標への適合性の問題です。C ++でのプログラミングは、すべての目標に常に適しているとは限りません。
reinierpost

1
@reinierpost:だからこそ、私は非常に高い努力について書いた。C ++は適切ではないが、実行できないためではないことを述べた場合。開発者のリソースが多すぎるため、あまり適していません。
バルテック

さらに、その場合は良くないだけです。
reinierpost

2
実際、これは多くの業界で起こることです。たとえば、ゲームには、パフォーマンスと生産性の両方のためにC ++コードを結合するLuaコードがたくさんあります。
gbjbaanb

4

私の意見では、人々が口語的に「プログラミング言語」と考えるものは、実際には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つは信頼性を示します。多くのライブラリは複数の言語に移植されており、一部の言語では、そのライブラリ専用にビルドされていないライブラリを使用できます(Cライブラリを使用したPythonに関する@vartecの回答を参照)。

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


1
準備は可能な限り重要です。Google Code Jamでは、入力を読み取り、必要に応じて出力を表示する小さなライブラリがあり、そのコードを提出物に含めます。
マークハード

2回目は、プロジェクトテンプレートとして似たようなことをしました。以下の入力クラスMainMainメソッド内のいくつかのもの(入力クラスと出力ストリームとケースループのインスタンス)を持つソースファイルを作成します。
オリオーニ皇帝13年

前回stdinを読んだときのことを思い出せません。JSONパーサーに貼り付けることができるファイルを教えてください。
gnasher729

2

時間制限のあるプログラミング競技会に参加したい場合は、競技会で許可されている最も表現力豊かな言語を学ぶ必要があります。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]

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

NB

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


3
(a)私は、C / C ++ / Javaがプログラミングの競争でトップの地位にある傾向があるという事実を知っています。(b)C / C ++は、「Perl / Ruby / Pythonを確実に上回る」多くの人から「最も強力な言語」と見なされています。(c)演算子のオーバーロードにより、C ++コードは2番目の例とほとんど同じように見えます。(d)このような広範なチェック(Javaで行われますか?)は、次の場合にのみ必要です:(1)何をしているのかわからない。(2)データの性質上、これは必須です(コーディングの競合では発生しません)。(3)他の人が使用するコードを書いている(該当なし)。
ダケリング

1
@Dukeling:この調査(page.mi.fu-berlin.de/prechelt/Biblio/jccpprtTR.pdf)によると、スクリプト言語を使用すると、開発を高速化し、ソースコードを小さくできます。別の調査(flownet.com/gat/papers/lisp-java.pdf)によると、Lispはスクリプト言語よりもさらに生産性を高めます。上記の2番目の調査によると、LispコードはC ++コードとほぼ同じ速度でありながら、作成にかかる時間は短くなります。
ジョルジオ

「200,000行プログラムと40,000行プログラムの間」:区別する必要があると思います。プログラミング言語の冗長性(構文)による違いはコードに複雑さを加えないため、必要な保守作業にほとんど影響を与えません。一方、言語機能が異なるため、行数を変えることができます。たとえば、Pythonではメモリを管理する必要はありませんが、Cではすべてのメモリ管理を自分で実装する必要があります。次に、Cコードではより多くの機能があり、間違いなく余分なメンテナンス時間が必要であることに同意します。
ジョルジオ

@Giorgio開発時間やソースコードのサイズについて議論しているわけではありません。純粋に重要な経験に基づいて、プログラミングのコンテストで実際に何が起こるかについてです。
ダケリング

1
私は2つの科学論文(IMOを見る価値がある)を引用していましたが、Webページの人々がそれについてどう考えているかについては話していませんでした。意見が広まっているという事実は、それが有効であることを自動的に示唆するものではありません。:-)少なくとも、厳密な方法で検証する必要があります。
ジョルジオ

2

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

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


2

「40 LoC vs 200 LoC」の例を外挿しながら、「全体のLoCの5分の1だけが明らかに高速に書けるので、より良いに違いない」と思われるかもしれません。

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

値を追加しないボイラープレートと冗長性を取り除くことはすべてうまくいきますが、一方で、JavaやC#のようなものを使用して、デザインパターンやreharperのようなツールについての知識があると、コードをリファクタリングするのに非常に柔軟性があります、時間をかけてクリーンアップしたり、物事を壊したりするなど、はるかに小さなpythonスクリプトまたはrubyアプリとして記述した場合は、非常に難しくなります。

非常にわかりやすい比較:テストでカバーされた分離されたC#コードが100k LoCあり、戦略的なパターンや工場などの「過剰」なものでいっぱいになり、20kのpythonアプリだけで「やる」ことができます。5倍以上のコードであるかどうかにかかわらず、アーキテクチャは毎日勝ちます。

いくつかの種類の作業が一部の言語ではより簡単で便利であることに完全に同意しますが、必要なツールと要件(近い将来)に基づいて言語を選択する方がよいと考えています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.