何かを書き留める何か

数学や読んだ本について書く何かです。最近は社会人として生き残りの術を学ぶ日々です。

『ホワット・イフ? -野球のボールを光速で投げたらどうなるか-』を読んだ。

みんな大好き紀伊國屋書店新宿本店の4Fを徘徊していたら本が目に入ったのでとりあえず購入した。xkcdの人だとは前書きあたりを読んでやっと気づいた。

www.kinokuniya.co.jp

読者からの突拍子もない質問に対して物理や数学を駆使して真面目に答える本でとてもよかった。 昔、こんなのを読んだなと思ったら空想科学読本に近いものを感じた。 真面目に読むならば筆者が計算した結果を逐一検討してその結論が正しいのかというのを考えるのもよいが、 科学的にまじめに考えると面白い結論になるというエンターティメントの1つとして楽しむのが良いと思う。

原著のサブタイトルは「Serious Scientific Answers To Absurd Hypothetical Questions」で「不合理な仮定による質問に対する真面目で科学的な回答」と訳せるか。 原著のサブタイトルの方が好みであるがこれは出版社(早川書房)の判断であろう。

個人的には、「海から水を抜く」の章でオランダが侵略を開始するネタがおもしろかった(オランダ人への偏見を見たようで)。

『Effective Debugging』Item 4: Drill Up from the Problem to the Bug or Down from the Program's Start to the Bug

『Effective Debugging』の続き。己の限界。

www.kinokuniya.co.jp

Effective Debugging

タイトルからしてどのように訳せばよいのか、己の英語力の限界を早くも感じてしまった。すでにItem 01で感じていたが…。 「問題からバグへのドリルアップ及びプログラムの開始時点からバグへのドリルダウンを行う」と無理やり訳してみたが、自然な日本語からは程遠い。内容はバグに対するトップダウンアプローチとボトムアップアプローチの使い分けの戦略である。

プログラムがクラッシュした、フリーズした、エラーメッセージなど原因が明らかに特定できるケースはボトムアップアプローチをまず採用する。 ブレイクポイントやメモリダンプを駆使して原因を突き止める流れとなる。 一方、パフォーマンス、セキュリティ、信頼性など原因が簡単に特定できない場合はトップダウンアプローチを取る。 全体を部分に分解して原因を調べる流れとなる。 また、一方の方法で行き詰ったら方向を切り替えてみることを勧めている。

冷静に考えてみれば、エラーメッセージが出るなど場所が容易に特定できないとボトムアップは自ずと限界を迎えるので確かにそうですねという話だが、当たり前のことを明文化して認識することが重要である。

僕には、デバッグに関するドメインの知識が足りず読むのに苦労しているのか、英語力がひどすぎるのか、両方か、どれだろうか。

ポケコインを効率よく買いたいので整数計画問題に落とし込む

Pokemon Goを始めた。 最初のポケモンピカチュウであった。 卵を複数入手し、10kmという長距離を歩かされるものもあり、インキュベーターは複数あった方が効率がよさそうだなと思い、初めてGoogle Playカードを買った。 1500円である。 いざチャージしたお金をポケコインに換金しようとすると、1円1コインではなく一度に換金するコインの量によって変わることがわかった。

さて、どのように買えば効率よく買えるのだろうか。パッと見、貪欲戦略で解決しそうな気がしないでもないが、整数計画問題に落とし込めば近似解ぐらいは得られそうである。 Pythonでは、SciPyかPuLPが線型計画問題のライブラリを備えているようなので、簡単にかけそうなPuLPで解いてみた。

import pulp

# Google Playの残金額
amount_of_money = 1500

# 線型計画問題の定義
problem = pulp.LpProblem('PokeCoinMaximised', pulp.LpMaximize)
x_1 = pulp.LpVariable('100pokecoin', 0, 10, 'Integer') 
x_2 = pulp.LpVariable('550pokecoin', 0, 10, 'Integer') 
x_3 = pulp.LpVariable('1200pokecoin', 0, 10, 'Integer') 
x_4 = pulp.LpVariable('2500pokecoin', 0, 10, 'Integer') 
x_5 = pulp.LpVariable('5200pokecoin', 0, 10, 'Integer') 
x_6 = pulp.LpVariable('14500pokecoin', 0, 10, 'Integer')

# 目的函数
problem += 100 * x_1 + 550 * x_2 + 1200 * x_3 + 2500 * x_4 + 5200 * x_5 + 14500 * x_6

# 制約条件
problem += 120 * x_1 + 600 * x_2 + 1200 * x_3 + 2400 * x_4 + 4800 * x_5 + 11800 * x_6 <= amount_of_money

status = problem.solve()
print("Status", pulp.LpStatus[status])
print(x_1.value(), x_2.value(), x_3.value(), x_4.value(), x_5.value(), x_6.value())

結果であるが、予想通りの結果であった。

Status Optimal
2.0 0.0 1.0 0.0 0.0 0.0

貪欲戦略でよいのでは、という結論である。