Trot

駆け出し前プログラマの学習記録

プランB

どこで読んだかは忘れてしまいましたが、先日読んだエンジニアのインタビューで「常にプランBを持つ」というTipsが紹介されており、自分の現状に刺さりました。モノづくりの現場では時間と完成度のトレードオフが常にあり、限られた時間の中で完成度を最大化するためにはとても良い考え方だなと思いました。

 

私が最近取り組んでいることのひとつに、自作アプリのECS/ECR環境へのデプロイがありましたが、それに囚われ過ぎていて全体が見えなくなっていたように思います。今の目標は「DockerizedされたRailsアプリを“何らかの環境”にデプロイ」なので、無理にECS/ECRに拘る必要はない訳です。別の方法で目的を実現した後、戻って来れば良いだけの話でした。

 

すぐに諦めては何もモノになりませんが、いたずらに時間を消費していても前進できません。今現在のスキルで解決可能かを見極め、時には損切りも必要だと思います。私の場合、どうしても一度手を出してしまうと「解決したい病」に罹患し、その技術に執着してしまいます。確かに粘り強さと言えば聞こえは良いですが、期限内での成果という点では非常によろしくないと思います。やはり時間は無限ではないので、定期的にリソースの配分を見直す機会は必要かもしれません。

 

具体的な解決案として「常に期間制限を設ける」を思い付きました。「〇〇日取り組んで駄目なら別の方法を検討する」という方法であれば、時期尚早の損切りが避けられるうえに、「解決したい病」に罹患して目標達成よりも技術が優先されるといった自分の悪癖の改善にもつながりそうです。とにかくこれからは何か新しいことに取り組む際は、約1週間を目処にして作業をしていこうと思います。適度に緊張感が出て良い感じになりそうです。

atcoder ABC B問題埋め100問突破

毎日少しずつ進めてやっとABCのB問題埋めが100問突破しました。最初は1日1問で精一杯な感じもありましたが、ここ1~2ヶ月は、すぐに1問解けた場合には追加でもう1問解いたりすることもありました。一般的な難易度のB問題であれば、かなり自信を持って解ける感覚があります。今後も競技プログラミングの問題埋めは継続する予定で、灰色上位の問題や茶色の問題も解いていこうと思います。

f:id:twins-twins:20200318114208p:plain

 

また、atcoder以外にも、一応時間があるときにはAOJの問題も埋めています。atcoderが実力に直結する過去問演習とすれば、こちらは基礎力養成といった気分で進めています。今はまだ入門編の中腹あたりですが、決して簡単というわけではなく、多分プログラミング経験が無い人だと進められない気がします。本命はこの入門コースの次にあるアルゴリズム基礎の方ですが、この調子でのんびり進めていきます。

f:id:twins-twins:20200318114823p:plain

 

ほぼ毎日競プロしていますが、私の現在レートは酷いです。一応、現在までにABCに4回参加して3回はC問題を通しているのですが、レートはかなり低いです。原因は解答速度と間違い提出によるペナルティと思われます。しかし、自分の現在レートに不満はありません。A問題とB問題を素早く通し、6割程度確率でC問題を通せるようになれば茶色が見える」と言われているので、B問題埋め真っ最中の私のレートとして極めて順当だと思います。現在のレートは低いものの、個人の成長としては「順当」なので、この調子でゆるく続けようと思います。

f:id:twins-twins:20200318120542p:plain

 

「プログラミングやってます」と最低限言えるように、レート400(茶色コーダー)の壁は突破したいところです。早ければ今年中くらいの気持ちです。まずは、ほぼ確実に素早くB問題まで解けるレベル(レート300くらい?)に到達して、そこからC問題の勉強を並行しながらレート400を目指すコースになると予想しています。自己分析では、現在そのコースの40~50%くらいの位置、つまり半分より少し手前くらいにいると思っています。「毎日問題を解いて、隔週1度でもコンテストに出ていたら流石に届くでしょ!」と楽観的に考えてゆるく着実に精進します。

AOJが楽しい

 

今まではatcoder以外知りませんでしたが、AOJのおかげで新しい選択肢が増えました。atcoderの過去問埋めと違い、問題の順番が整理されていているので、段階的にじっくり実力が伸ばせそうな気がします。ベクトルと行列の積を出力するプログラなど、実践的で面白いです。

https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/6/ITP1_6_D

私はRubyでこんなコードを書きました。

f:id:twins-twins:20200312143406p:plain

 

そういえば、atcoder過去問埋めの状態を確認すると、「今まで結構な数の問題を解いてきたんだなあ」と思います。

f:id:twins-twins:20200312143916p:plain

そして、競プロ学習が進むに連れ、数学を復習したい欲が高まります。流石にC問題に入ったら、最低でも数列、順列、組み合わせなどは一度復習したいと思います。

~3/8 今週の振り返り

少し遅れてしまいましたが簡単に振り返ります。

 

メタプログラミング Ruby

 

メタプログラミング Ruby』を4章終了時点で一時休止を決定しました。理由は「今は必要性を感じないから」です。ブロックをオブジェクト化したProcオブジェクトの使い方やクラスメソッドを使って動的にメソッドを定義するなどは面白いのですが、今現在必要性を実感できていないことを訓練して身に付けようとするのは雲を掴むようなものなので、今必要に感じていることを優先しようと思います。本書で要求されるようなことが重要であれば別のことを進めている時に必要性を実感するタイミングがあるはずで、その時に再読すれば良いと判断しました。もし出会わないのであれば、さほど重要ではないとも言えます。

 

『メタプロ』が面白いことは間違いないのですが、必要性、興味、必要時間などをパラメーターとする優先順位的に考えると、他に勉強したいことよりもどうしても下位に位置付けられてしまいます。

例えば、『メタプロ』より優先したいこととしては、RubyRails競技プログラミング基本情報処理技術者試験、Kotlinの基本文法、Androidを使用したスマホアプリ開発Arduino、『CPUの創りかた』、数学など、無数にあります。

 

競技プログラミング

 

過去問サイトにあるB問題を埋める作業に終わりが見えてきたので、競技プログラミングの学習方針にも大きな変更を加えました。私は競プロerを目指している訳ではなく、思考をプログラムに落とし込む訓練として競プロを活用している感じです。競プロのおかげで配列やループを見ても何の恐れも無くなりました。「C問題までは自力で解けた方が良いなあ」という感覚があるので、そこまでは続けたいと思っています。「将来的には緑色くらいになれたらなあ」くらいの気持ちもあります。

 

以下の素晴らしい記事を参考に、B問題埋めに加えて、Aizu Online Judge(A0J)の基本問題を学習スケジュールに加えました。

https://qiita.com/e869120/items/f1c6f98364d1443148b3

https://onlinejudge.u-aizu.ac.jp/courses/list

 

一応、定番書とされている『プログラミングコンテスト攻略のためのアルゴリズムとデータ構造』を図書館で借りて読んでいましたが、大判で数百ページの書籍版は非常に重く、電子書籍版のサンプルを見ると検索機能が使えないなど不便に感じていた私にとってAOJは福音でした。atcoderと同じくネット環境とPCさえあればいつでも挑戦できます。この手軽さが学習ハードルを下げて、気軽に取り組める好循環を生み出しているように感じます。問題の質も今の自分の実力にちょうど良く、文句なしです。今は半分ほど終えたところです。このまま毎日1~2問程度を継続して解いていきたいと思います。

 

基本情報処理技術者

 

基本情報処理技術者はその試験範囲のみを参考にして読み物系の技術書を探してきました。なぜ参考書を読むという最短ルートを取らず範囲のみを参考にしたかの理由は、辞書のような厚さの参考書を書店で眺めた時にその物語性の無さに面白みを感じられなかったからです。なので「重要なことであれば別ルートを通ったとしても登場するだろう」と考え、たとえば『プログラムはなぜ動くのか』『よくわかるネットワーク&TCP/IPのきほん』など、個々のトピックについて多少物語性のある書籍を読んできました。しかし、最近になって、さまざまな書籍を読んで学んできた基礎事項を網羅的に復習したい欲求が出てきたので、改めて書店で基本情報の参考書を読んだところ望外に面白く、その勢いで基本情報の参考書を購入しました。随分と遠回りをして戻ってきましたが、30%程度は既知事項なので「接点が見つけられなくてつらい…」となることもありません。参考書の重量以外に不満はなく、上手く接続できた気がします。春試験の募集が終わっていたので、秋試験の合格を目指したいと思います。午後問題のプログラミング言語の選択については、取り越し苦労になりそうなので今はまだ決めていません。その頃にPythonを勉強していればPythonになると思いますし、Javaと同じJVM系のKotlinの学習が順調なら、Javaの選択もあり得ます。

 

そういえば出題傾向が変化すると発表があり、線形代数・確立・統計などの分野の出題が増えるらしく、良い感じに数学を勉強する必要が発生しています。毎日の競プロでちょうど数学を復習したい欲が出てきていたところなので数学を学習スケジュールに組み込むことも考えます。

 

 

今週全体の感想

 

最近は、「今の自分に難しすぎる問題を棚上げする勇気は必要」ということを実感しています。「難しい問題に固執して全体のペースが乱れるくらいなら思い切って棚棚上げして、適度な難易度の問題を解いて少しずつレベルアップを図った後に再挑戦する方が総合的にみてプラスが大きい」と感じています。ただ、難しい問題をなんでも棚上げしてしまってはレベルアップできないことも確かなので、適切な難易度の見極めが難しいところではあります。そして、難易度の見極めには一定時間・一定期間の投資が必要なので、積極的に挑戦して良い感じに難易度ラベル貼りができたらと思っています。前述の『メタプロ』を含め、購入したものの消化し切れていない教材がいくつかありますが、一度時間をかけて取り組んだ経験があるので、良い感じに難易度ラベルが貼れていると思います(信じます)。また機を見て再挑戦します。

 

書評『僕は君たちに武器を配りたい』 

このブログで扱う対象は技術系のことに留めるようと思っていましたが、そればかりではあまりに機械的なので「名刺代わりにするためには私という個人をもう少し公開した方が良いかな」と思いました。書評は趣味の読書の一環ではありますが、少なくとも週に1冊は読むので、その中から適当に書いていきたいと思います。

f:id:twins-twins:20200303202916j:plain

 

さて、本題です。

今回は『僕は君たちに武器を配りたい』の書評です。まずは簡単な要約から始めようと思います。本書のテーマは「資本主義が加速させるコモディディ化(没個性化)といかに戦うか」と言えると思います。コモディディ化した商品が市場に溢れると、価格や品質は均質化され、市場が買い手優位に傾き、売り手の首が締まります。たとえば、価格競争によってしか他社と差異化できない牛丼チェーンがそれに当てはまります。

 

そして、その論理は労働市場においても同様で、コモディディ化した人間が買い叩かれる、言い換えれば、過酷な環境で労働させられたり、交換可能な部品として軽く扱われてしまうわけです。本書が提示していた「労働(人間)の商品化」に抗う方法を自分なりに解釈すると、例えば、非常に豊富な資源があるが食い荒らされつつある土地に留まっていると、土地の資源が枯渇した際に八方塞がりになる可能性が高いので、リスクを負ってでも今いる土地が枯渇する前に資源のある新たな土地を探しに出る方が賢明、という感じでしょうか。市場を見極める目を鍛え、コモディディ化のリスクを避け、その代わりに反コモディディ化のためのリスクを負え、ということでしょう。

では、実際にどのようにして新たな資源を発見する眼力を身につけるかと言えば、教養(リベラルアーツ)を学ぶと説かれています。月並みな結論ではありますが、本書で紹介されているイノベーションのプロセスに専門技術以外が大きく影響した実例を見ると、その主張には中々の説得力がありました。

 

簡単な要約も程々に、私の感想を書こうと思います。

著者の論理の明晰さには舌を巻きましたが、抽象論と具体論は別と思いました。確かに現実の具体例と照合してみても著者の主張に瑕疵はありません。私なりの要約にはありますが、「資本主義のもとでの自然淘汰の圧力に屈しない人間になるためには、日頃から良書に学び、知識と思考の両方をバランスよく養うことが肝要である。そうすれば、適宜自分で最善の意思決定ができるようになる」という著者主張は完璧です。

 

しかし、たとえば本書で盛んに推奨されている「教養を身につけること」についてですが、少なくとも私の知る範囲では、「教養を身に付けよう」と意思して古典的良書(ビジネス書や自己啓発本ではない本)を日常的に読む習慣を身に付けた人は極めて稀で、自宅に父親の書斎があるような所謂「良い環境」で育つうちに読書が日常の一部となった人が多い印象です。著者は学者を父として持つ「良い環境」に恵まれ、若くして本の面白さに気付き、教養を身に付けたと思われますが、持たざる者として成人した一般人にとって、「良書を読め」という著者の主張は「正しいが再現性が高くない」と思いました。

 

人間は「〇〇が必要だよ」と勧められ、本人がその重要性を理解したとしても継続的行動に結びつけることは難しいです。なぜなら、たとえば読書といった教養につながる行動が、行動を起こした本人にさほど大きなメリットを感じさせないからだと思います。労力に見合っていないと感じてることを無理に継続すると精神が摩耗し、いずれ擦り切れてしまいます。したがって、教養以前に、行動の継続に必要な「ご褒美発見力」*1を身に付ける必要があるわけですが、それは教育や好奇心といった当人には手の付けようのない要素に大きく依存しているような気がします。しかし、「生まれが全てで無理じゃないか」と嘆いていても状況は好転しませんし、自分のできる範囲から少し外れたところにある挑戦を続ける以外ないのかなと思います。幸い、脳には可塑性という未知の領域が残されていて、何か挑戦するうちに脳が覚醒する可能性も十分にあります。将来的に可塑性の限界が判明する可能性があるものの、賭けて損することはありませんし、とりあえず賭けてみるのが賢い選択という気がします。「パスカルの賭け」論法です。

 

ちなみに、批判めいた感想になりましたが、同著者の『読書は格闘技』も続けて読みましたし、著者の主張には概ね好意的です。両書ともに「耳に優しい一元的な答えに逃げるな」というメッセージを感じました。著者が昨年に夭逝されてしまったことをとても残念に思います。

f:id:twins-twins:20200303203102j:plain

 

*1:任天堂の前社長、岩田聡さんの受け売りです

『CPUの創りかた』との格闘

『プログラムはなぜ動くのか』で、教科書的に「CPUはコンピュータにおける処理の中枢を担う装置である」と知り、続いて「メモリから命令をフェッチして、それをレジスタに記憶してetc…」と覚えましたが、どうにも具体的に動くモノがないために漠然とした理解で、もう少し踏み込んだ理解をしたいと感じていました。そうなると、自分の手で作ってみるしかなくなるわけですが、そこで手に取った本が『CPUの創りかた』です。私のような駆け出しエンジニアには明らかに無用な代物という自覚はありますが、「好奇心を刺激する勉強は全体のモチベーションをあげるからトータルで見ればプラス」と前向きに考えています。好奇心は私の独学が今まで続いてきた最大の要因なので、無視するわけにはいきません。

 

そういえば全くの余談ですが、一般向けの脳科学書を多く上梓されている池谷裕二先生の著書『受験脳の作り方』を最近暇つぶしに読んだ際、LTPと呼ばれる長期記憶に重要な現象は、いわゆる復習は勿論、強い好奇心によって発生するとありました。以下の記事にも同様のことが書かれています。

こうすれば記憶力は高まる!~脳の仕組みから考える学習法(東京大学・池谷教授)2014/6/6 | WAOサイエンスパーク

 

さて、本題です。『CPUの創りかた』を読み始めたまではよかったものの、回路図の読み方がわからず、P.100辺りで少し詰まりました。このまま強引に進めても良いですが、先のページにある完成図を見ると、CPUが「回路の集まり」のようなものとわかります。「回路図が難しい」とは少なからずの人が感じることらしく、『CPUの創りかた』のファンの方によるサポートページに「回路図の意味がわからん」の項目があるくらいです。したがって、このまま回路図の理解なしに強引に進めると、「何の成果も得られませんでした...!!」となる可能性が高いです。 

私は一度棚上げして、電子工作(?)の知識を多少身に付けてから再挑戦することにしました。そして、次なる策を考えていたところ、以前読んだ『コンピュータサイエンス図鑑』にArduinoというちょうど良い製品があったことを思い出しました。入門サイトを覗いてみたところ、抵抗器、回路のH/L、LEDの点灯、コンデンサなど、まさに『CPUの創りかた』に登場した面々が登場しています。さらに、幸いなことに、ArduinoがサポートしているC言語は、私が最近勉強し始めたKotlinにどことなく文法が似ています。今の私に理想的な製品です。

 

ということで、Arduinoを注文しました(まだ届いてはいません)。毎日30分ほどではありますが、『CPUの創りかた』の代わりにArduinoをしばらく勉強してみることにします。

 

正直なところ、Arduinoは大きな目標のひとつとしているアプリ制作の最短ルートには全く必要のないことだと思いますが、どの知識がどのような場面で役に立つかを予測することは困難で、目標達成に必要な知識だけを綺麗に抜き出してピンポイントに勉強することはできないのではないかと感じています。例えば、スタティックリンクという言葉をアプリ制作には直結しない『プログラムはなぜ動くのか 第2版』で知りましたが、“アプリ制作に直結する”Dockerの本でも登場しました。そうした経験から「コンピュータ関連分野の基本的な知識は押さえておいて損はない」という思いが強くなりました。コンピュータをハードとソフトから構成される電子機器と定義するならば、簡単な電子工作も「コンピュータ関連分野の基本的な知識」に加えるのが自然に思いますし、そんなに悪くない選択と思います(そう思いたいが本音)。

 

わからないなりに色々と考えてみていますが、全くの見当違いという可能性も十分にあります。しかし、恐れず勉強を続けていくしかなさそうです...!

 

余談の余談

CPUの創りかた』刊行から16年経った古い本ですが、なんと今年の3月1日に電子版が出版されたようです。コンピュータの本質的な知識は10数年程度では錆びないのかもしれません。私はArduino経由で戻る予定ですが、また読める日がより楽しみになりました。

~2/23までの学習記録

まずは小さなところから書こうと思います。

 

競技プログラミング

atcoderB問題埋めのゴールが見え始めたので、『プログラミングコンテスト攻略のためのアルゴリズムとデータ構造』の学習を開始しました。~P300までの基本編までは気長に読み進める予定です。競技プログラミングと検索すると、「役に立たない」が候補に表示されますが、私個人としてはatcoderの効能を明確に感じているので、緑コーダーになれるまでは頑張りたいと思います。

 

ハッカーと画家

ハッカーと画家』を読みました。プログラマ界隈で定評の書籍のようで、近所の図書館で借りて読みました。うろ覚えですが、コンパイラといった完全に機械的な部分の技術の実装に人間性は要求されないが、人間と直接的接点のある技術の実装に関わるプログラマには人間性が求められるとの記述が印象的でした。また、ハッカー(=優れたプログラマ)に共通する特徴として、常識をベースに物事を考えないことが挙げられていたことも印象的でした。ハッカーは、演繹的に全体を構築することを好むのかもしれません。

 

 

さて、細々としたところは以上です。

 

『Practical Object-Oriented Design: An Agile Primer Using Ruby (2nd Edition)  (以下POODR)』

今週の大きな進捗は、『Practical Object-Oriented Design: An Agile Primer Using Ruby (2nd Edition)  (以下POODR)』の読了だと思います。先月から少しずつ時間を使い、良い感じで読了することができました。英語で読んでいるため、どうしてもペースが遅くなりましたが、それほど難しい単語が出て来るわけではないですし、大きく詰まることはありませんでした。

意味理解に重要で頻出する単語についてはAnkiで管理し、公共交通機関の利用中やコンビニのレジ待ち時間などを使って適度に復習しています。専門書は文学作品に比べれば倒置や省略が少なく、非常に読みやすいと感じます。個人的感覚ですが、技術書は、言葉の定義に厳密さが要求されるためか、無用な言い換えが少なく、説明には基本的に同じ言葉が好んで使用される傾向があるように感じます。

 

正直なところ、読了はしたものの学習効果を大きく実感している訳ではありません。普段はRailsというフレームワークを使用しているため、それに従っていればOOD(Object-Oriented-Design)を意識する必要を感じないからだと思います。しかし、あくまで憶測ですが、その内部構造に踏み込むとなると、やはりその背景にはOODが隠れているのではないかと思います。私は、「マニュアルに従って、とりあえず使えれば良い」ではなく、将来的には自分でgemを開発したり、既存gemの不具合を自分で直せるといったところを目標としています。そのためにOODが役立つかどうかは定かではありませんが、とりあえず道具箱に入れて置く知識としては悪くない選択だったと思います。何より、入門書の50ページほどの理解に留まっていたオブジェクト指向と向き合う良いきっかけとなりました。

 

今後も英語の技術書を読む習慣を捨てたくないので、常に1冊は英語で書かれた技術書を読みたいと思います。何か良い本が見つかると良いのですが、まずは本の探し方から考える必要がありそうです...

 

Kotlin学習開始

Kotlinを選択した理由はいくつもあります。Androidの開発言語としてGoogleに公認されたなど、世間的潮流から大きく外れていることがなさそうですし、仮に今後Kotlinが下火になったとしても、これまで蓄積されたJVM系言語資産にアクセスしやすくなるのではないかという狙いもあります。

 

最も大きな理由は、静的型付け言語かつ00年代以降に誕生という条件を満たしていたことです。「90年代」に誕生した「動的型付け言語」のRubyと全く異なる特徴を持った言語が理想的でした。その点で、Kotlinはまさに理想的でした。それら特徴を有する言語としてGolangも選択肢にありましたが、Railsを使用してWebアプリをした経験があることから、次はスマホアプリの経験をしてみたい気持ちが強く、Android開発言語として確固たる地位を確立しつつあるKotlinに落ち着きました。

 

Rubyとは異なる特徴を持つ言語を選ぼうとした理由は、『コーディングを支える技術』に書かれていた「比較して学ぶ」を意識してのことです。このままRubyを伸ばしても良いのですが、異なる性質を持った言語を学ぶことでRubyの理解を向上する段階に差し掛かっているのではないかと感じています。例えば、Rubyは0(ゼロ)を含むほとんどのオブジェクトの真偽値がTrueとなりますが、Javascriptでは0(ゼロ)の真偽値はFalseです。こうした微妙な違いを覚えられたのは、両者の比較による部分が大きいのではないかと思います。

 

定着が甘いうちに複数言語を学習することは「記憶の干渉」という明確なデメリットがあり

、非効率かつ危険だと思いますが、私の現状としては、「Rubyの基本は定着した」と言って良い気がしています。AtcoderのB問題が比較的すらすらと実装できるようになりましたし、Rubyは多重継承を制限しており、Moduleによって多重継承問題の補完をしているといったことも理解しています。私にとってのRubyは、他言語を学ぶための比較材料として使える程度には熟成しているのではないかと思います。実際、全く学んだことがないPythonについて、「PythonRubyと異なり多重継承が可能である」という情報を記憶しています。Rubyの基盤が固まっているからこそ、無意識的に記憶できたのだと思われます。

 

色々と理由を述べましたがRuby学習がメインであることには変わりなく、Kotlinは毎日30分ほど学ぶサブ的な扱いです。今しばらくの中心はRubyです。『POODR』を読了して空いた時間は、『メタプログラミングRuby』に当てます。

 

余談

https://www.tiobe.com/tiobe-index/

上のサイトを見る限り、今後Rubyという言語が生き残るかどうかは定かではありませんし、むしろ数字を見る限りかなり厳しいことが予想されますが、Rubyで学んだことが、今後の学習の良い材料となることは確かだと思います。全くの素人考えですが、結局のところ、言語はアイデアを表現するための道具に過ぎず、アイデアを理解できていれば、実装は瑣末な問題に過ぎないのではないかと考えています。例えば、文字における書き順に近いかもしれません。各々の文字の特徴を押さえておけば、書き順が変化したとしても、大きな問題にはならないはずです。したがって、より多くの概念に親しむ(<=>異なる性質を持った複数言語に親しむ)ことが、重要ではないかと考えています。