プログラミング初心者がreduceしか見えないのは変なのはわかってるけど・・・

プログラミングの練習をしてたら,配列があって,配列の中身全部の最大公約数を求めるコードを書くことになった。

で,古いPythonだから最大公約数を求める関数はfraction.gcdとして(今だとmath.gcd),

import fractions
from functools import  reduce
list1 = [4,12,28]
reduce(lambda a,b : fractions.gcd(a,b),list1,list1[0])

のようなのしか思いつかない。たぶん重症。

普通のループを書けば良いんだけど,ループを書くのがおっくうといういう病理。

Pythonを使い始めれば少しはその傾向が変わるかと思いきや,あまり変わらない。リスト内包記法でかなりのループがまかなえる,ということに日々気付く方向になってるし。

病理の原因?

最初に使った言語がRだったせいか,普通のループを書くのがずっと苦手。次に使ったのがRubyなので,その傾向が変わるわけもなく。

自分の感覚,たぶんおかしすぎる。

例えば,超初心者の頃から無名関数を使うことにも全く抵抗がなかった。Rのちょっとマニアックな本で,apply系関数に引数にfunction(x){なんとか}でその場で関数の内容をべた書きして与える例を見て感動してから(感覚おかしい!),これは便利ということで抵抗なく使ってるし。。。

その流れでいくとRubyのブロックはごく自然に使えるようになるし,色々使たり本とか読んだりでたりするうちに,関数に関数を渡すという概念も自然になり・・・

世間ではこういうのを関数型になじみのある人っていうんだろうけど,再帰とか全然わかんないし,そんなに数学得意じゃないのにおかしいな。。。

しかし,こういう人が初心者にプログラミングを教えるのはだめだとは思ってる。ほんと,自分の感覚のおかしさにあきれる。

オートモードのシーフードサラダが意外とよかった

f:id:baruku07:20200510024606j:plain

スーパーでいか(輪切りになってる)のとアスパラがおいしそうだったので,調理法は後から考えるかで買って帰った。

いかはソフト蒸しにするとして,時間を考えるのが頭痛いと思ってたとこに,オートモードがあるのを思い出す。

説明には,ソフト蒸し75度16分で代替できるとのことだったのでたぶん思った通りの仕上がりになるとふんで蒸す。アスパラもこれに入れてしまえば良いと気付いて同時にいれてボタンを押す。

で,試食をしたんだけど良い。2/3が一瞬で消える。

ただ,アスパラが200円,いかが400円。原価が高すぎる・・・自炊は節約になるといったのはどこの誰だと最近つくづく思う。

3つのサイコロの最小値は定義通り素朴にやっては・・・

本をばさっとScanしようとしたら、よくある問題に目が止まった。

サイコロが3つあって(誘導付きで)最小値が2である確率を求めよと。

通常は、P(最小値が2以上)-P(最小値が3以上)が普通。最大値が2以上は、全部2以上が出るとできるので、結局  \left( \frac{5}{6} \right) ^3 で簡単に計算できるし,最小値が3以上でも簡単なので,結局そうやれば簡単にできるでしょ,という考え方である。ただ、個人的にこの考え方、知ってるか知ってないかだと思って好きではない。

なので,普通にできないの?とかふと思ったりすることがある。この問題,最大値の定義ということを踏まえて考えれば

 P(最大値が2) = P(全部2以上) \times P(少なくとも1個2を取る \mid 全部2以上)

で計算できるはずで、

 P(最大値が2) = (\frac{5}{6})^3 \times ( 1-(\frac{4}{5} )^3 )

とすれば、普通に式がたつ。展開すれば結果的に同じ式にはなるけど。

ただ,この解法,「全部2以上の世界で考えて余事象」を考えるのが厳密じゃないとか言われればまあそれまでなんだけど。個人的には,最大値の定義をストレートに考える考え方のほうが素朴だと思うんですけどね。。。

教科書の配列順の関係や、一般人受けの関係で、条件付きの考えははよほど必要な時以外は全面に出さないことになってる,というのはわかる。特に,制限した世界で全事象を取るということは相当に抵抗感があるみたいで。条件付き確率を計算する問題ですから,全事象を条件付きの世界に取り換えて計算することなく,もとの事象の世界で考えて、ばかばか大きな数のまま計算して定義に代入、ってスタンスで書かれているのがほとんどだし。

Pythonはじめました

2月ぐらいで短時間でとある教科書のプログラミング教材について話す講義をすることになった。その算数教材について,講義しないとならない事項が多すぎてブロック言語では間に合わない。そこでブロック言語とテキスト言語を両方示しながら講義するという案で行くことにした。

Google BlocklyのDemoにあるCode Editorがいい感じでブロックを作ってくれるので,ブロックのサンプルはこれで良い。テキスト言語は慣れているRubyにしたかったのだが,Code EditorがPythonをブロックからの自動変換で吐いてくれるので,Pythonを使うことにした。

個人的にはPythonのインデント命が嫌いで仕方がなかったので避けていた。ただ,いざ読ませる方になるとインデント教のほうが良いなと思いだした。かっことかendが省略できて縦の幅を取らずにコードがかけることが,講義資料を書くときに相当にありがたいのである。特に,紙に書くときやディスプレイが縦長でないことを前提とするときにありがたい。

AtCoderのAB問題で練習中

そのうちPythonを使って計算やデータ系のお勉強はしたいけど,そこまでの基本を身に着けるのにどうしようかということで,AtCoderのABCのA, Bをここ数日解いている。

やってるうちにリスト内包表記もなんとなく使えるようになってきて,いい感じ。初心者が基本的な練習するのには,ほんと良くできてるとつくづく思う。

あとは,Pythonで解くことでPythonの解答コードも読むようになってきて,そうするとRubyより回答数が多いので自分にとって読みやすいコードに触れられることも多くなって,そういう意味でも良い感じ。

マイルドにマイルドさを重ねて書いても

いや怖いと思う。

最上級マイルドでないとしても,だいたいマイルドになるかどうか確認して書いても,攻撃食うことって世の中あるんだなと思いつつ。。。。もうちょっとエクスキューズ書かないといけないのかね。さすがにそのレベルでチェックかけて書くとしんどいので,これぐらいでいいかで自分は止めたりするけど。

さすがに微にわたり細にわたり最上級のマイルドまで意識しては書いてないけど。要は意図せずどっかにとげがのこってないかを詳細に詰めるチェックまではしてないと。

まあ自分はいいとして,いや,さすがにその話題でそれ書いてこの攻撃がくるのか,というシーンを見てしまうと怖すぎる怖すぎると思う。。。。

いろいろみながらびびってるけど,いや,そういわれてそういうなら最初からそう書いておけよという思いが強い。だいたい,それは私が読み取ってる文脈そのものだし,暗黙の文脈わかってればそれが読めるけど,ても表面的に見てれば普通はこれそうは読めない人いるんじゃない,とオブラートに包んで書いたら,そうじゃないってばしってやる。恐ろしい世の中だ。

あとは,こっちの立場で論評風に書いて主張するのは無理だしそこまでの確証がないから主張はしないし,コストはかけられないけど,とりあえず記録として印象論でこうかなでも書いておこうかぐらいでも宣戦布告的に取られるとか怖い怖い。

理系の学問という対象は嫌いではないけど,それに集まっている理系の人は嫌いな人が多い,という理由で文系やってる私としては,そのおぞましさを久々に見た思いがする。文系と決めた後で,意外とおぞましくない理系の人も数々みてきてるから昔よりかは理系に対するおぞましさは薄れるけどね。。。。

ちょっと忙しくてばしっと書いた記事をさらすのは怖いので。。。いや,それでこういう攻撃されるなら書けないな。。。ほんと。。。。

とりあえずは茶色にしたが・・・

とりあえず,かなりの回数参加して,あまり努力せずにAtCoderを茶色にしてみたが・・・

とりあえず自分の勉強用としては,相当にマッチしているサイトで良かったと思う。ただ,その前提って高校数学が少しだけわかり,大学数学はほんの少しみたことあって,経済学にかすかに触れて最適化の感覚になんとなくなじんでいるから,という特殊背景があったような気がしないでもない。

茶色までは楽できると期待は外れたとこがある。例えば,緑まではc++いらないって書かれていたことを信じてたのが裏切られたとか(ACしているのを見ると可能だが,私には面倒で無理な話だったということ。)。仕方がないと,少しだけc++も使うことが何回かあった。このために公式提供のサイトで少しだけc++を勉強した(これは良かった・さくっとできたので),というかコンテスト中に公式提供のc++の書き方を見ながら書いたことが何度もあった(というか今も)。

あと,世間のforとifがわかってほんの少しだらだら勉強してたら茶色になれるも信じてた。だったらノー勉で茶色までいけるならだらだらとやるかと始めた。ただ,それが当てはまる人と当てはまらない人がいそうだというのが最近の実感。以下,それについてだらだらと書いてみる。

パフォーマンス400のライン

ここ3回のパフォーマンス400の境界をざっと目視で確認すると。

  • 158 : Cまで, 約60分
  • 157 : Bまで, 約20分
  • 156 : Cまで, 約30分

となる。普通にやったらCまでは解かないと茶色にはなれないと言えそう。

ここ3回の400のラインで求められていると思われるもの

158

8%消費税と10%消費税の額が与えられて,元の額の最小値を求める問題。

少なくとも制約を見て,支払う金額のループで解けるということを思いつく必要がある。それか切り捨ての不等式を真面目に考えられる算数的能力。

157

3x3のビンゴの判定を20分以内に解く or 条件を満たす最小の整数(C問題)を解く。

Cは制約考えると1から順番に考えていって解けるらしいが・・・私は,桁数で場合分けして解いて,ちょっと痛いミスをして解けなかったが。。。

156

C は,x_iの列が与えられたときの(x_i -m)2の和を最小にする問題。

mはx_iの最小と最大の間にあるということに気付いて実装する(20分以内に!)か,確率・統計(最小二乗法の感覚)の常識で,mが実数ならmの値は平均値なので,その前後の整数を試せば良いことに気付くか,さらに2次関数の知識で整数に近い方が解答になることに気付くか。制約読んで,総当たりでも行けると気付く解法もある。c++以外で間に合うかはわからないが。

D は,教科書レベルの組み合わせ + 指数・2項係数の高速化(D問題)が必要な問題。

プログラミングのお勉強で茶色に行けるのか?

私がずっと思ってることとして,出題者・参加者双方,中受算数か大学受験数学をくぐっているか,高校数学ぐらい苦労せずに身に着けられる頭脳を持っている人のような気がしてならない。

156のCは,たぶん本当の進学校とかだと数1の段階で授業で触れられてる話だと思う。しかし,高校生の自分が,知識として(x_i-a)2の和を最小にするようなaは平均値,という知識を知らずにこの問題を解けるかと言われると怪しい。そういえば,過去には|x_i-a|の和を最小にするのはaが中央値のとき,という知識も必要な問題もあった記憶がある。

最小を取るaは両端の間にある,なら求められる知識はいらないといわれると思う。しかし,それも式の形を見て最小にあたりをつけるというある種の高校数学的感覚がないとでてこない発想だと思う。常識で思いつくと言えばそれまでだが,その常識がある人もそれなりの知能がある人だと思う。

そもそも偏差二乗和の和を求める式は,x_iを定数とみてmを変数と見て1変数関数ととらえる感覚の有無が解答のしやすさに大きく効いてくると思われる。しかし,それを高校数学で偏差値50切る人がわかってる感覚とは思えない。少なくとも自分には,知識とか訓練なしであの式を1変数関数とは見れない。

157のBのビンゴは確かにforとifの典型題だと思う。これを20分ならまあまあお勉強と言える。しかし,そういう早解きでなくCの2項係数で考えると,これは競プロ自体のお勉強が必要になる。

158は算数だと思う。ただ,元の支払額のループで考えて良い,ということは何回か過去問を解いてるとわかってくる感覚かな・・・

以上3つは,(私は文系だが)理系の世界に住んでいれば,こんなのわからない人いるの?と言われる話で,算数や数学と呼ぶことすらはばかられる話だと思う。しかし,文系の一般の人にこれプログラミングの練習してれば茶色になれますよ,とは言えるというかと言えない。

算数・数学を通した得たふわっとした感覚が求められている

算数・数学を勉強すればなんとかなる,とも言えない。こういう数学が典型で頻出,というわけでなく,いろいろなところを断片的につまんでばらばらに出題している感じだから。こういうのは,知識の増強で対処できるものではなく,受験数学のような教科書の類題の単純あてはめっぽくない訓練をした経験が求められている感じである。それも,できるだけ誘導少ない問題で。あるいは,それを訓練せずともできる地頭があるか。

また,最適化のような考え方になじんでいるかも影響しそうだと感じている。自分はほんのわずかだけ経済学に触れたことがあるので,その経験からするとこれ常識よね,と思えることは何回かあった。しかし,それが高校以前にわかったとか,本で勉強して身に着けたか?と言われると疑問である。最適化の数式によるかっちりとした理解,というよりも言葉でふわっと最適化を考える感覚を使ってる感がある。自分は,この感覚を経済学部に存在しているだけで,勉強なしで自然と身につけた自覚がある。しかし,文系の一般人にお勉強で身に着けろ,と言われると?となる。

茶色は文系の一般人が「お勉強」でなれるものだと思っていたが,茶色でもそれが無理なんだというのが今の自分の実感。

勉強として使うには

レートとか気にせずA,Bを入門の問題集として解いていくのは算数微妙な人も含めて強くおすすめできる。Pythonとかでやれば良いと思う(自分はPythonでなく別のスクリプト言語使ってるけど)。本当のプログラミング初心者がA,Bをc++で解くことにこだわるのは,あまり意味がないと思う。

ただ,Cは数学っぽい問題とそれ以外の問題が混ざっているので,仕分けしながら解いていかないといけないかなといった感じ。

文系で数学が少しだけ得意とか,少しでも理系っぽい人は,特殊な勉強をしなくてもCぐらいまでは良い練習問題として使えるような気がする。だから,茶色ぐらいになるようにすれば?は正しそうな気がする。

世間のプログラミング入門で絵をかいたり何かを作ったりというのがおすすめされるが,それは万人に向いているようで向いてないと思っている。絵とかゲームに興味のない人には自分で作りたいものが考えられないので,自分で考えて何かを解いた経験がいつまでたってもできない。それと同じで,このサイトは数学やパズルのようなものになじんでいない人には自分で考えることができない学習サイトである。しかしそれらになじんでいる人には適したサイトなのだからそれで良いよね,と思う。

今年の入試問題を解いていて

お手軽な某国立大学の文系の問題を解いていたら,こんな問題があった。

f:id:baruku07:20200301133612p:plain

 \cos B = -4/5とする。このときにBHの長さを求めよという問題。


 \displaystyle
 AC^2= 16^2+25^2-2 \times 16 \times 25 \times \left( -\frac{4}{5} \right) = 1521

になるので,AC=39となって後はBHが出るという構図らしい。

こうすれば典型なのはわかる。しかし,1521を39に直せるなんて気付くのか。すごいな。。。

ここまでの誘導

そもそもこの問題,色々な紆余曲折を経て前問では


 \displaystyle
(\cos B, \sin B ) =  \left(-\frac{4}{5}, \frac{3}{5}  \right)

を導かせて,この問ではACとBの点と直線の距離を求めよという形式での出題である。しかも,BC=25, AB=16はこの問のためだけに急遽与えらた数値てある。急遽数値を与えるということは,計算が簡単になるように与えるはずである。したがって,16と25という数値を与えてきた時点で,162 + 252 などという計算をさせることが想定解法だとは思わない。回避を考えるのが自然である。

また,辺の長さの25にcosやsinかければ座標はきれいな値になることは数値を見た瞬間わかる。そうなるように25という数値を与えてきたのだなとも読む。とりあえず,Cは座標設定しておいてゆっくり考えてよさそう。ということは,座標設定して点と直線の距離の公式に持ち込めというのが誘導だと思った。Bを原点においてしまえば,計算量など知れているし。

図を描いてると余弦定理導出と同様にできることに気付く

ただ,それすらも直線の式計算するのは嫌だな。2桁の数の引き算なんかしたくないしと考えた私は図を描いていくうちにひらめいた。余弦定理の導出相当の図を描けば,sinAが求まるのでこれ簡単だと。すなわち,次の図が思いついたということ。

f:id:baruku07:20200301140905p:plain

この図より, \mathrm{CH}:\mathrm{AH} = 15:36 = 5:12であることがわかりこれは5,12,13の直角三角形だから斜めは13。三角比は縮小した三角形で求めて良いので


 \displaystyle
 \sin A = \frac{5}{13}

であることがわかる。これさえわかってしまえば,


 \displaystyle
\mathrm{BH}=  \mathrm{AB} \times \sin A = 16 \times  \frac{5}{13} = \frac{80}{13}

となることがわかる。この解法のポイントは,三角比を考えることで比の部分でうまく数値が小さくなるということである。また,出題者は5:12:13をうまく使って問題を作っていることもわかる。

ただ,この解答は書きにくい。だったら,表の式は余弦定理導出で計算してACの長さを導出してしまったことにして答えを書けば良い。さきほど,1/3の三角形に縮小して考えたので,ACは3倍してあげれば良い。答えさえわかってしまえばやり放題である。

今後の教訓としては,今のプロセスを一般的な式にすれば,


 \displaystyle
\mathrm{BH}=  \left(\mathrm{AB} + \mathrm{BC} \cos B \right)^2 + \mathrm{BC} \sin ^2 B = (16+20)^2+15^2 =3^2(12^2+5^2)

のような感じにすると,2乗の箇所が2か所で済むので計算が楽になることもあるぐらいか。ただ,コンピュータ時代には全くの不要な知識なのだが。。。

普通に座標に置くとしてもそんなに難しくない

f:id:baruku07:20200301143051p:plain

ACの式は


 \displaystyle
 y = \frac{-15}{16-(-20)} (x-16)

で傾きがうまく約分できて,いい感じで変形すると


 \displaystyle
5x + 12y -5 \times 16 = 0

になって,点と直線の距離の公式を使うと


 \displaystyle
 \frac{|-5 \times 16|}{\sqrt{5^2 + 12^2}} =  \frac{16 \times 5}{13} = \frac{80}{13}

となり,普通に肩がつく。この解法でも,傾きのとこで約分が効くことと,5,12,13が出てくることで計算が楽になっている。