誰もが同じことを言います:「本物のプログラマは本当の問題を処理する方法を知っています。」しかし、彼らはこの能力をどこでどのように学んだかを忘れています。それは学校では教えられていません。
複雑なプログラミング問題に取り組む能力を向上させるにはどうすればよいですか?どのような戦略がうまくいきましたか?アルゴリズムや設計パターンなど、焦点を当てるべき特定の領域はありますか?
機能する場合と機能しない場合があるいくつかのテクニック:
必要に応じてRモードまたはLモードの考え方を使用します
Rモードは、私たちが潜在意識に一般的に関連付ける創造的で非言語的なアプローチです。 Lモードは、「内なる声」に関連する線形で論理的な口頭のアプローチです。
問題が扱いにくいと思われる場合は、誤った思考モードを使用して問題を解決しようとしているためと考えられます。プログラマーにとって、デフォルトの思考モードはLモードである傾向があるため、一時的にオフにしてRモードにアクセスするとうまくいく場合があります。
Rモードの考え方にアクセスする方法
多くの方法がありますが、おそらくポアンカレ法(有名な数学者にちなんで名付けられました)を試してください。
問題について知っていることをすべて書き留めます。 (もしあれば)それのすべての簡単な側面をすぐに解決します。残りの「難しい問題」のリストから1つのアイテムを選び、邪魔されたり気が散ったりしない散歩に出かけます。
散歩中に問題を分析しようとせず、頭の中をさまよい、問題に関連している可能性のある興味深い画像や感覚を観察してください。それらを合体させましょう。インスピレーションがストライキした場合は、すぐに散歩を中止し、戻ってあなたが得た洞察を書き留めます。
すすぎ、すべての問題に洞察が得られるまで繰り返します。次に、洞察の調査を開始します。
おすすめの本
また、 実用的思考と学習 を読むと、問題解決に役立つ場合があります。 (私は最近この本を頻繁に参照しているようです...)
他の人に聞いて...
真剣に。あなたの最大のリソースはあなたの隣に座っている人かもしれません。彼らに問題の答えを尋ねるのではなく、あなたの隣に座って問題を説明してもらいます。
多くの場合、あなたはそれを言葉で表現するときにそれを解決します。
時には、他の人が質問をしたり、精神的な水門の鍵を開ける詳細を指摘したりします。
最終的には、人形を使わずに頭の中で物事を言葉で表現する方法を学び、問題の主要な詳細をすばやく見つけることができます。
そして、他のすべてが失敗した場合、彼らはあなたがあなたが使うことを考えていなかったであろう技術をあなたに示すことができるかもしれません。
実際、私の短い答えは「より多くの問題を解決すること」です。しかし、要点は、本当に問題に集中し、あきらめないことです。 StackOverflowなどで助けを求めないでください。 (もちろん、StackOverflowを読んでも大丈夫です!)ほぼ機能するソリューションが得られるまで一生懸命試してください。そして、満足のいく解決策が見つかるまで続けます。
私にとって、問題解決は2つのことです。
ポイント2は、問題に悩まされている時間が長いほど考え方を変えざるを得ないため、私の意見では本当に重要です。また、問題解決により多くの時間を費やすことができ、スキルをさらに向上させることができます。 ;-)
ちなみに、エドワード・デ・ボノを読むことをお勧めします。私は主に物理学を勉強して問題解決のスキルを身につけましたが、彼の文章は本当に興味深いものです。
さて、私の問題解決ツールキットはこれです:
これらのツールのほとんどは再帰的に適用できることに注意してください。
そして私のアルゴリズムはこれです:
ステップ1.は難しい決断ですが、練習すればするほど、より良い決断を下します。
ああ、私は最も重要な成分をほとんど忘れています:
プロセス全体について前向きに考えます。 「XYZで問題が解決することを願っています」とは思わないでください。むしろ、「XYZが機能しない場合は、YZXが問題の原因になり得ないことを知っているので、ZYXが機能するかどうかを確認します。」特に問題を見つけるプロセスがエレガントで有益なものになる場合は、問題解決が楽しい場合があります。
問題を特定するスキルにも取り組み始めます。時には、問題を解決する前に問題があることを認識しなければなりません。学校では、生徒からの回答が多すぎて、質問が不十分です。
問題を解決するあなたの周りの人々を見つけ、彼らがどのようにそれについて取り組むのか尋ねてください。
間違いを覚悟してください。あなたがそれらをすべてあなた自身に保持し、あなたが何の役にも立たないならば、あなたは改善しないでしょう。
ソフトウェアエンジニア向けのコンピュータサイエンス教育の主な利点は、抽象化を作成および理解できることです。抽象化は、Stringクラスのメソッドなどの一般的な機能を、より大きな問題に集中できるようにするタイトで再利用可能なパッケージにカプセル化するために使用されます。
抽象化の認識と作成を学ぶ:
しかし、最も重要なこととして、抽象化は私たちに教えます問題をより小さく、より管理しやすいチャンクに分解する方法。科学的背景と組み合わせると、これらのスキルの組み合わせにより、ノイズを切り抜けて問題の核心に到達できるエンジニアを作成できます。
科学的方法を使用して問題を解決する方法を学ぶ:
見つけるのが難しい問題が存在する実稼働アプリケーションのトラブルシューティングを行う場合、1つを分離して排除するためにいくつかの変数を排除するために、実際に(非実稼働環境で)アプリケーションをさらに壊すことが役立つ場合があります。
要約すると、コンピュータサイエンスの学位に必要なすべての物理学の選択科目とその他の科学の選択科目から学んだ科学的方法は、まるで私たちが一連のボランティアでプラセボと新薬の試験を試しているかのように、これらの問題を解決するのに役立ちます。それをより良くするために時々何かをより悪くしなければならない科学者のように、時々私たちはエンジニアとして同じことをしなければなりません。
この方法で科学的に考えることは、一般的には、科学のバックグラウンドでの経験からのみ可能です。問題を解決することは、AからBへの直線的なパスとして認識できない場合があります。
つまり、コンピュータサイエンスを研究し、他の科学分野を研究し、関数型プログラミングを学びます。これらは、あなたが科学者のように考え、箱の外で考えるのに役立ちます。
あなたが探しているのは、コンピュータサイエンスのヒューリスティックです。
私たちの99%が塹壕でやっていることを考えると、太陽の下には何も新しいものはありません。したがって、問題を見て、それをDPの問題として認識するか、別の問題をメモ化などから利益を得ることができる問題として認識する可能性があります。
どのようにしてこの知識を得るのですか?適切なCSの学位は、開始するのに適した場所です...ソフトウェアエンジニアリングや情報システムではありませんが、ほとんどの学部生が「実用的でない」と不満を言うのはそのためです。
自分でこれを行うことはできますが、おそらくもっと難しくなります。私はこれらの2つのコースから始めます。
それはすべて、解決しようとしている問題の種類に依存しますが、すでに解決していない場合は論理的に考えることを学ぶのは良いことです。
結局のところ、あなたは私にそれを言って嫌いになるでしょうが、練習は完璧です。私は良い問題解決者になる方法を知っていて母の子宮から引き出されず、他の誰もそうしませんでした。自分で練習する方法を学ぶ必要があります。あなたがまだ学校にいて、プログラミング/コンピュータサイエンスタイプのクラスがない場合、数学と科学もこれらのスキルの育成を促進するのに非常に適しています。
私の答えは特にコーディングに関連していますが、何にでも適用できます。
練習に関しては、私が何をしているのかをお話しできます。私はプログラミングよりも応用数学に興味がありますが、コンピューティングに応用される応用数学は一種のプログラミングです。周りに問題と解決策があります。既知のソリューションまたは既存のコードライブラリにリンクする前(または私の仕事がタイムリーなソリューションを必要とする場合は後で)の前に、私は自分自身に質問したいと思います。缶詰の解決策、あなたはどのように進めますか?」答えがやや単純な場合は、ソリューション(分析、またはそれを解決するためのコンピュータープログラム)を作成することを検討してください。複雑なエンドケースを無視します。既存のライブラリを再発明するのではなく、アプローチとアルゴリズムを探索することに関心があります。ソリューションがあまりにも多くの労力を必要とする場合は、完全なソリューションをプログラムせずに、少なくとも使用するデータ構造とメソッドの種類について考えてください。また、代替方法についても検討してください。
私は科学のバックグラウンドを持っているので、問題を見るときは Scientific Method の戦術を使用する傾向があります。私は特に、仮説に基づいて「実験」を設定し、「コントロール」を使用するのが好きなので、何かを構築してから、それについて1つだけ変更/追加し、その1つの変更/追加の結果を確認します。 m必要な結果が得られないので、それを元に戻して別のものを変更します。これは、コードのトラブルシューティング/デバッグに適しています。求めている答えが得られることもありますが、失敗しても常に新しいことを学びます。私はまた、 還元主義 -すでに存在するものを理解するのが好きです(常に理解できないものから始めるのが良いですが、あなたは機能することを知っています)、私には複雑に見え、それを壊すことができるかどうかを確認しますそのコンポーネント部分にダウンして、それらが最初にどのように機能するかを学びます。全体的に問題に取り組むよりも、私の脳がこのような学習を処理する方が簡単な場合があります。その知識を使用して、他の同様の複雑なものを自分で構築できます。また、古典と現代の両方の思想家から作品を選択する論理と推論についての本を読むことをお勧めします(アリストテレスから始めて、上に向かって進みます)。これらは、コンピューターの問題解決に役立つ基本的なロジックの基礎のいくつかを提供します。そしてもちろん、問題を解決できず、しばらくの間問題に取り組んできた場合は、頭を休ませてください。問題の特定の側面について反省することは、時には有害です。みんな休憩が必要です:)
これには素晴らしい SO質問 があります。
私の答えは:
改善する最良の方法は練習することです!
http://www.mensa.org.uk/puzzles/ でRSSフィードを購読し、それらが出てくるのを完了するのに時間をかけてください。
パズル1日の卓上カレンダー(例 http://www.calendars.com/product.asp?PID=1&MGID=-1&IID=46387&cm_mmc=Affiliate_Program--performics--k137666-_-DDI%20Link )は、解決すべき通常の、一口サイズの、さまざまな問題を提供するので、良い考えでもあります。
これらはあなたが直面している問題から常に外れていますが、これまでにない方法で考えることを強いられるため、多様性は重要です。
編集:次の項目も確認してください http://www.mindtools.com/pages/main/newMN_TMC.htm は、問題解決のヒントとして役立ちます。
チェスをする
チェスをすることは、プログラミングの問題を解決するための優れたトレーナーです。問題の層と論理ツリーは非常にうまく関連しています。また、次善の道を進み、時間を無駄にする前に、前もって考え、計画するのにも役立ちます。
チェスでは、左右の「思考モード」のバランスも必要です。分析的になりすぎると、すべてを計算しようとするのに行き詰まることがありますが、これは不可能です。ただし、すべての創造的なインスピレーションは、それが状況の具体的な現実に適合していることを確認するために計算で確認する必要があります。難しい問題はこのようなものです。
チェスは、研究と実践が非常に直線的な方法で確実な改善にどのようにつながるかを示しています。これは、プログラムの問題解決にも当てはまります。
チェスをすることは、どれだけ学ぶべきかをよく理解するのにも役立ちます。 10年間プログラミング(またはチェス)をしていても、まだグランドマスターではありません。
私は最近 Project Euler で問題を解決しています。問題の難しさはさまざまです。ソリューションは通常、大量のコードを必要としませんが、アルゴリズムのランタイムなどの多くの要因を考慮する必要があります。答えを入力するだけなので、好きな言語を使用できます。多くの問題に対する最適な解決策の適切な説明があり、各問題について多くの議論があります。毎日1つの問題を解決してみてください。問題の解決と分析がどれほど改善されるかがわかるでしょう。追加のクレジットとして、手続き型言語(おそらくC++)、スクリプト言語(Pythonなど)、関数型言語(F#など)など、多くの言語で同じ問題を解決してみてください。
問題解決の最も難しい部分は「知覚的狭窄」です。
問題があると思われるものを選び、それを使い尽くして、何も進歩しないまで頑張ります。
これを行う方法は、問題を確実に理解することです。 「正しい問題の解決」は問題解決の最も重要な部分です。
時々彼らはこれを「箱の外で考える」と呼びます。 「箱」は、本当の根本的な問題を含まないかもしれない狭い視点です。ボックスの外側で考えることは、解決する適切な問題を探すことです。
間違った問題に時期尚早に焦点を合わせることによる狭窄を回避するための戦略に関する本は多数あります。
主なトリックは、実際の結果がどうなるかを特定することです。次に、その望ましい結果を妨げているものを見つけます。
アプリケーション開発では、私たちが直面する問題の多くは、独自の発明か、コードベースを台無しにした継承した馬鹿の発明のいずれかです。ほとんどの場合、問題の解決はソースの検索に帰着します。多くの場合、いったんwhereが見つかったら、単なる能力がsolveに必要なものです。
そのために:
世界のすべての脳トレーニングは、脳が使用するための情報がなければ役に立たない。問題を解決するには、最初に可能性が何であるかを知る必要があります!それでも、問題の説明だけでなく、適切な情報を扱う方がはるかに迅速です。
何かが実行に時間がかかりすぎる理由について、牛が帰ってくるまで推測するかもしれません。しかし、「最初にいくつかのデータを取得する」と言うと、多くの例外がスローされているのがわかり、代わりにifステートメントに変更できることに気付くでしょう。情報を収集する方法がわからず、プラットフォームで例外が発生するとかなりのオーバーヘッドがかかります。また、それを試す前に確認する方法があるため、問題を解決できません。
あなたの答えには2つの部分があります:
a)実際の問題解決のためのテクニック
b)思考と問題解決において脳を本質的に「より良く」する
技術については常にいくつかの素晴らしい答えがありました(問題を知っていると想定してください)ので、それについてはあまり取り上げません。脳のトレーニングに関しては、これらのシナプスを越えて相互接続を構築するためにできることがいくつかあります。
1)新しい言語、本当の言語を学ぶ(最近ではフランス語や中国語などがいいかもしれません)
2)新しい楽器の演奏を学ぶ
3)ペイント、描画、彫刻などの芸術的なことをする
4)スクラブルをプレイしたり、クロスワードを行う
5)あなたがそれを意味するようなダンス。いいえ、冗談ではありません。ダンスはあなたの脳と思考に 影響 があることが示されています
6)あなたの経験を広げる、革新的な解決策は、ある分野の理論を別の分野に適用することから生まれました。
7)運動、運動は非常に重要です 重要 思考プロセスを改善する
最後に、難しい問題を解決するための最善のヒントを提供します。長い散歩です。私はそれがあなたの頭をきれいにし、人に問題を熟考させるのに奇跡を起こすことがわかりました
プログラマが好きなプログラミング言語で問題を解決する方法を視覚化することにより、プログラマが問題を精神的に攻撃するのは簡単です。彼のお気に入りのツールがハンマーであるときにすべての問題を釘として見る古典的な大工のように。
実践的なレベルを上回って、「これが最適な方法で解決するために必要なこと」という観点で考えると、問題解決の最良の練習ができると思います。場合によっては、ソリューションを適用するために(多くの)新しいことを学ぶ必要があるかもしれませんが、重要な点は、ソリューションを作成する能力は、従来の技術と既存の技術に限定されるべきではないということです。
私の古い実践的な例は、問題が実際にはプリエンプティブスレッドを必要としないことに気付いたときに、効率的な協調マルチタスクを実装する方法を学んだことです。最終的にはいつかはいつか快適になるのをやめているようだ。
問題解決は、読むことによって教えることも学ぶこともできないものです。問題を解決するための唯一の方法は、問題を解決することです。
問題解決には、さまざまな techniques と methodologies があり、特定のドメインの問題を解決するために使用できるツールとテクノロジーについて読むことができます。問題について継続的に考えない限り、解決策を考え(すべての問題に対して複数の解決策を考え出し、それらを相互に評価して)、次に他の人が開発した解決策に対してソリューションを評価してみてください。解決。
実用的な思考と学習:アンディ・ハントによるウェットウェアのリファクタリング を入手することをお勧めします。それはあなたがどう考え、反応し、学ぶかを理解することについての本です。行動理論やその他の認知科学から関連する理論を取り入れています。特にソフトウェア開発者向けですが、ナレッジワーカーにも適用できます。
私のようなプログラミングの初心者には、「Think Like a Programmer」という本をお勧めします。最初の章では、あなたが知っていることから始めて、減らし、類推し、実験することから始めて、問題を再表現し、分割するような問題解決テクニックを扱います。
次に、C++の例を使用したより高度な手法があります。配列、ポインタ、動的メモリ、クラス、再帰、コードの再利用に関する問題の解決です。まだ難しすぎるのでコメントはできません。
私のアドバイスは本を捨てる!
もちろん文字通りではありません。つまり、既存のソリューションについて学習することなく、経験がほとんどないトピック領域を入力し、そこで難しい問題を解決します。あなたの創造性と批判的思考、そしておそらくリファレンス・マニュアルに頼ってください。
画像形式を設計する場合があります。またはWebサーバー。または圧縮方式。ファイルシステム。カーネル。人工知能。プログラミング言語。コンピュータービジョンシステム。
あなたが面白いと思うもの、それはかなり複雑で、あなたがこれまで学んだことのないもの。 しないでくださいそれについて読んでください:ただまっすぐ飛び込んでください。間違いを犯す。ホイールを再発明します。
助けを求めないでください。チュートリアルに近づかないでください。理論から離れてください。ソリューションをすぐに取り外さないでください。
どうして?
何回か試してみて、達成したことに満足したら、数か月間そのままにしておきます。次に、新鮮に戻って、新しい視点を見つけることができるかどうかを確認します。その後、問題について読んだり、他の人がどのように解決したか(または人々と話し合ったり)します。この時点で、読みながら自分に「はい、それは理にかなっています」と言う代わりに、「はい、正確に」、または「まあ、ある程度」、または「すごい、それは賢い」.
言い換えると、読んだ内容についてより批判的に考えることができ、アタッチする大きな「メンタルフレームワーク」がすでにあるので、理解と覚えがはるかに簡単になります。独自に発見したことについて気分が良くなり、新しい知識の山を離れて歩きます。
ソリューションを完璧にしようとしないでください。あなたがあなたにcan問題を解決したことを証明してください。 「できる」という態度を採用し、問題に気が遠くなる場合は、最初にそれを解決した人がおそらくあなたと同じくらい知っていたことを覚えておいてください(実際、彼らは解決策があることを知りませんでした!)。
正直なところ、私は誰もが異なると思うので、より良い問題解決者になるための全員のロードマップは異なります。他の人の経験から学ぶことができますが、最終的には自分の道を築く必要があります。これは本質的に何か「難しい方法」を学ぶことですが、この場合は効果的です。
これは私が問題解決を改善し始めた方法ですが、私はまだ優れた問題解決者ではありませんが、昨年よりも優れた問題解決者です。管理用に3つの新しいレポートを追加することにより、オープンソースの時間追跡ソフトウェアを拡張することを含む新しいプロジェクトが作業中に与えられました。このソフトウェアは、私が使用したことのない言語で書かれており、文書化が不十分で、非常に難読化されていました。私は掘り下げて大量の調査を行い、その後、基本的な機能が得られたら改善し、最後に機能を追加して、レポートをベビーステップで作成しました。
つまり、言い換えれば、シンクまたはスイムの実際のプロジェクトに取り組むことをお勧めします。現在プログラマーとして雇用されている場合は、プロジェクトを見つけるか、上司に依頼してください。このシナリオが不可能な場合は、仕事の外、契約/フリーランスの仕事などを見つけてください。私は必要なときに問題を非常に迅速かつ迅速に解決し、プロジェクトの集中力のためにその知識を保持しています。これがうまくいかない場合は、このスレッドの他の全員が提案していることを実行してください:)。
答えはそれ自体が質問にありますは、さまざまな解決策を考え出すことです。常に複数のソリューションがあります(たとえば、並べ替えはさまざまな方法で行うことができます。つまり、バブルソート、選択ソートなど)。効率的に実行(ソート)できる方法を選択するだけです。次回は別の方法で試してみてください.....そして問題解決のための本.....なし問題解決のスキルを本から学ぶことはできません。コードが増えるほど、実行する知識が増えます。幸運を