じばるどーね!

趣味、思想、妄想、学問、ごった煮ブログ

【プロジェクトオイラー】数学の難問をプログラムの力で解く!!Part3(個人的に面白かった問題)

  こんにちは、ここ数日インフルに倒れていたじばるどーねのとぼです。プロジェクトオイラーの記事です。またある程度解き進めるまでは、このシリーズはとりあえず今回で最後にしようと思います。

 

f:id:tb9810w124816:20180325171613p:plain

オイラープロジェクトについての詳しい説明は省きます。

 

今回は、個人的に序盤で解いて楽しかった問題、為になった問題を4つ紹介します。あ、ちなみに書き溜め記事ってのもあるし、なんだかんだこの記事ではC++を使っています。 

 

 

1. Problem12 Highly divisible trianglar number

f:id:tb9810w124816:20180409093206p:plain

  問題文は上記のようになっています。今回の問題は英語が比較的読みやすい気もしますが、分からなくても例のwikiが使えるので安心です。問題は「三角数の中で500を超える正の約数を持つ最小の数はいくつか」というものです。三角数とは、自然数nを用いて
n*(n+1)/2の形で表される自然数のことを言います。
 
<この問題の面白いところ>
 個人的にこの問題が面白いと 思った点は、計算量を工夫次第で減らせる点です。プロジェクトオイラーとしての問題というより、この類の問題が競技プログラミングで出題されたら少し工夫できていいな、と思ったまでです。
 まず、通常ある自然数Nの約数の個数を数えたい場合、
1から√N以下の整数全てでNが割れるか(約数であるかどうか)試せば十分です。なぜなら、Nがある数iを約数に持つならば、必ず同時にN/iも約数に持つはずであり、i≠√Nのとき明らかにiとN/iのうちの
一方は√N未満の数、他方は√Nより大きい数となるからです。したがって、√N未満で割り切れた整数の数を2倍して、最後に√Nで(for文の条件式をi*i<=Nとすればよい)割り切れれば1を足す、という作業をすればよいのです。
 さて、以上から三角数N=n*(n+1)/2の約数の個数を数えるのにかかる計算量はO(√N)=O(√n²)=O(n)と分かりました。しかし、Nが三角数であることに着目すれば、もう少しオーダーを減らせるのではないでしょうか?
 まず三角数はある自然数nによってn*(n+1)/2と書き表される数のことを言いました。整数論でよく用いられる性質でnとn+1は互いに素(1以外に公約数を持たない)という性質があるのですが、よくみると三角数は互いに素である2数を掛け算していることが分かります。さらにn,n+1のいずれか一方は偶数であることも分かるので、nが偶数の時、Nは互いに素な2数n/2,n+1の積であり、nが奇数のとき、Nは互いに素な2数n,(n+1)/2の積であると結論づけられるのです!互いに素ということは約数にダブりがないので、Nの約数の総数はこの互いに素な2数の約数の個数の積で表されることになります!
 以上の考察から、計算量はO(√n+√n)=O(√n)=O(⁴√N)にまで減らすことができました。この計算量の減少は問題が三角数であったからできたことであり、これで相当大きい三角数(n=10¹⁶)も高速で計算できるようになりました。
 
int main() {
     ll n1=1, n2=1 ;  //n1,n2は互いに素な2数の各約数の個数
     int t = 2;  //t*(t-1)/2=N(答え)
     while (n1*n2<=500) { //約数が500を超えない間
        n1 = n2;  //n1<n2とすると一個前のn2がそのままn1になる
        n2 = 0;  //n2のカウントをリセット
        int po = (t + 1);  //上限
        if (po % 2 == 0) po /= 2; //n/2 OR (n+1)/2の判定
        for (int i = 1; i*i <= po; ++i) if (po%i == 0) n2+=2;
        if(i*i==po) n2--;   //n2が平方数だった時の考慮
        t++;
      }
     cout << (t*(t-1))/2 << endl;   //答え出力
     return 0;
}
 なお、ll はlong long 型のことです!!
 細かいですがソースコードではO(2√n)からO(√n)くらいに減らす工夫をしています。
 

2.Problem33 Digit cancelling fraction

f:id:tb9810w124816:20180409100657p:plain

 お茶目な問題です。49/98=4/8となる理由を昔のアホな数学者が「49と98の共通の文字9を取ったからだ!」と勘違いしてしまったそうですが、40/50=4/5などの自明な(当たり前な)例を除いてこのような2桁/2桁の分数は4つしかないそうで、この4つを約分して積をとったときの分母の値を求めよ、というものです。

 

<この問題の面白いところ>

   「 9を取り除くから49/98=4/8」っていう問題の発想が単純に面白いですよね。気持ちとしては「40-32÷2=4!」並みの面白さを感じます。ただし、この問題、「自明な例(non-trivial examples)」の定義があいまいなんですが、おそらく44/33,20/10など、「10の倍数分の10の倍数」、「11の倍数分の11の倍数」の2パターンのことでしょう。これ以外にある解法を探していきます。全探索で十分でしょう。条件判定が少し難しいですが、手元で少し計算すると、

i) (10a+b)/(10a+c)=b/c

ii)(10a+b)/(10c+b)=a/c

iii)(10a+b)/(10c+a)=b/c

の3パターンは自明な例を除いてあり得ないことが分かります(証明略。)

よって残りのパターン

iV)(10a+b)/(10b+c)=a/c

のみを考えればよいことになり、分数のままでコンピュータが計算するのは難しいので、通分などして整数の条件に直すと

 10a(c-b)=c(a-b)

が成り立つことが条件であると分かります。これでほとんど問題が解けました。

 

<ソースコード>

int main() {
    int nu = 1, den = 1;
    for (int a = 1; a <= 9; ++a) {
        for (int b = 1; b <= 9; ++b) {
             for (int c = 1; c <= 9; ++c) {
                   if(a!=b&&b!=c) //自明な例11の倍数を除く
                   if (10 * a*(c - b) == c * (a - b)) {  //条件判定
                       nu *= a;  //答えを分子に掛ける
                      den *= c; //答えを分母に掛ける
                      cout << 10 * a + b << "/" << 10 * b + c << endl;
                    }
               }
          }
      }
     int t = gcd(nu, den);  //nu(分子)とden(分母)の約分
     cout << den / t << endl;
     return 0;
}
 ちなみにこの問題は答えも美しいので是非やってみてください。

 

3.Problem41 Pandigital prime

f:id:tb9810w124816:20180409103349p:plain

  「1からn(nは9以下の自然数)が1回ずつ各桁に現れる数をn桁パンデジタル数と呼ぶとき、最大のパンデジタル素数を求めよ」という問題です。英語圏の言葉遊び「パングラム」(a~zまでのすべてのアルファベットを1回ずつ使って文章を作る遊び)から由来しているのでしょう。

 

<この問題の面白いところ>

 この「パングラム数」という言葉、私はプロジェクトオイラーで初めて聞いたのですが、プロジェクトオイラーでは頻出のテーマで、「難しい整数問題を解いている感じ」がしてとても好きです。まあ、「難しい」のは人力で解いた場合なんですけども!また、以前ちょっと触れたnext_permutationが大活躍する問題でもあります。オイラープロジェクトやってたからnext_permutationを知れて、その結果AGC22のAが(実質Bもオイラープロジェクトのおかげで解けている)無事解けたと考えると感慨深いです。

 

<ソースコード>

まず、軽く考察を。パンデジタル素数なので当然3や9で割れてはいけません。しかし9桁のパンデジタル数、8桁のパンデジタル数は各桁の総和がそれぞれ45,36となり、9の倍数の性質から、確実に9で割り切れてしまいます。そこで、最大のパンデジタル素数の候補となるのは7桁のパンデジタル数であるということが分かります。

あとは1~7の組み合わせを全部試せばよいのですが、ここでnext_permutationというC++の機能を使うと簡単に順列の全通りの組み合わせが列挙できます。

 なお、コード中に登場するiota(v.begin(),v.end(),val)ですが、iotaは引数valが加算可能な型であれば、v[0]にvalを入れ、その後v.end()までv[i]にval+iを格納していきます。整数や文字型などに適用可能で、順列の初期値生成に適しています。

int main() {
     ans = 0;
     vector<int> v(7);
     iota(v.begin(), v.end(), 1); //最初は1234567
     do {  //next_permutationで順列ループ
           int f = 0; //素数判定
           int a = 0;
           int dig=1;
           for (int i = 0; i < 7; ++i) {
                a += dig * v[i]; //答えを組み込む
                dig *= 10;
           }
           for (int i = 2; i*i <= a; ++i) {
                 if (a%i == 0) {
                    f = 1; break;
                 }
           }
          if (!f) ans = max(ans, a);  //最大値の更新
      } while (next_permutation(v.begin(),v.end()));

      cout << ans << endl;
      return 0;
}
 

4. Problem59 XOR decryption

f:id:tb9810w124816:20180409105149p:plain

 この問題は滅茶苦茶面白い問題なのですが、英語よわの私には文面が辛すぎるので日本語wikiをガン見しました。

f:id:tb9810w124816:20180409105308p:plain

 すると、やはり滅茶苦茶面白そうな問題であることが分かります。

 

<この問題の面白いところ>

 「この問題を通して一つの実在の暗号をプログラムを使って解いている」っていう体験がなんかハッカーっぽくてかっこいい(くそこなみかん)。でも確かにワクワクする問題だと思います。また、XORの特殊な性質「(A XOR B) XOR B =A」が利用されているのも面白いです(この性質は真理値表を書いてみると明らかになります)。XORのこの性質から、Bを鍵とすることでAを暗号化し、再び複合することもできることが明らかになります。まずA XOR B=Xで暗号化して送信者が受信者に送り、受信者は鍵Bを用いて

X XOR B =Aとすれば元の文章(平文)を解読できるというわけです。

 プロジェクトオイラーにはこの他にも暗号技術にかかわる問題が出題されており、好奇心をくすぐります。

 

<ソースコード>

 でもこの問題は自分が鍵を知らない状態で平文を解読するものです。まあ、この方がハッカー感あっていいですよね(くそこなみ)。ただし、文章は一般的な英単語から構成された文章であること、そして暗号は3桁の英語小文字であることが分かっています。3桁とはザルですね!セキュリティがなっていません()。26*26*26で全探索されてしまいます。とはいえ、26*26*26のパターンをすべて人間の目で確認して正しく解読できているか判断するのは不可能ではありませんが、大変面倒です。そこで、英文におけるアルファベットの統計的な出現率を利用します。"e"が最頻出であることは知っていましたが、それだけでは解読にやや不十分であったので、以下のurlを参考に出現率が6%を超える上位8文字の個数を文中からカウントしていき、その合計が最大となった鍵を正しい鍵とすることにしました。

文字頻度表

上位8文字はe,a,t,i,o,s,n,rでした。eat Rosin. (松やにを食え。)

さて、ソースコードは以下になります。

int main() {
        FILE *fp;
        char gomi[20];
        int pass[200000];
        fp = fopen("in.txt", "r");
        ll sc;
        int pp = 0;
        while (fscanf(fp,"%d,",&pass[pp]) != EOF) {
           pp++;
           cout << (char)pass[pp-1];
        }

       cout << endl << endl;
       int ecounter = 0;
       char id[3] = { "" };
      for (int i = 0; i < 26; ++i) {
           for (int j = 0; j < 26; ++j) {
                 for (int k = 0; k < 26; ++k) {
                        int pip = 0;
                        for (int h = 0; h < pp; ++h) {
                            

                             if(h%3==0)pass[h] ^= (i + 97);
                             else if (h % 3 == 1)pass[h] ^= (j + 97);
                             else pass[h] ^= (k + 97);
                            

                            if (pass[h] == 'e'|| pass[h] == 'a'|| pass[h] == 't'|| pass[h] == 'i'|| pass[h] == 'o'|| pass[h] == 's'|| pass[h] == 'n'|| pass[h] == 'r') pip++;
                            }
                           if (ecounter < pip) {
                                ecounter = pip;
                                id[0] = i + 97, id[1] = j + 97, id[2] = k + 97;
                           }
                           for (int h = 0; h < pp; ++h) {
                                    if (h % 3 == 0)pass[h] ^= (i + 97);
                                   else if (h % 3 == 1)pass[h] ^= (j + 97);
                                   else pass[h] ^= (k + 97);
                            }
                     }
              }
       }
      ans = 0;
      for (int h = 0; h < pp; ++h) {
             pass[h] ^= id[h%3];
             ans += pass[h];
             cout << (char)pass[h];
      }
     cout << endl << endl;
     std::fclose(fp);
     cout << ans << endl;
     return 0;
}

 一部凄まじく汚いコードですが、許してください。

 また、Disucussionでは英文にほぼ確実に含まれている"a"や"the"といった冠詞をカウントしていく手法を取っている方もいました。様々な解読法があり、非常に面白い問題だと思います。

 ちなみに解読画面はこんな感じになりました。

f:id:tb9810w124816:20180409114734p:plain

 

 5.まとめ

  今回で、一旦プロジェクトオイラーの記事は区切りをつけようと思います。この記事で興味を持ってくれた方が一人でもいれば幸いです。私はこれからも少しづつProject Eulerを進めていくつもりです。

 

yadrfu.hatenablog.com

yadrfu.hatenablog.com

 

 

 

 

エビが食えるなら虫も食えるだろうと思った人の自己紹介

今週のお題「自己紹介」

読了時間:約2分(リンクは含めず)

今回は自己紹介風に最近あったことを語っていきます。

自己紹介

 初めまして!現在工学系の大学生で、ブログ書いているくりすぷです。特技は有名牛丼チェーン3店の味当てです。詳細は下のリンクにて。ちなみに3つの中で、松屋が好きです。牛の旨味と脂、醤油の風味のあのバランスがいいですよね。

yadrfu.hatenablog.com

 趣味は特にないですが、自分の中で新しい発見や新しいものが好きで、テーマを決めてそれについて体験したり考えたりすることが好きです。一週間前(上のリンクの、牛丼を食べ比べしていた時)は、牛丼の味というテーマを決めて、コンビニと有名3店の牛丼の味比べをしていました。そのときの感想は、牛丼って大体味は変わらないけどよく味わって食べてみると、ビーフジャーキーのように少し硬いけど旨味があったり、柔らかくて脂を感じたり、結構違いがあるんですね。そんなことを日常の中に見つけてブログに書いています。

本題

 さてそんなわけで、最近は虫食いました。米とサーカス(https://r.gnavi.co.jp/gam0700/)という店なんですが、飲み友人に勧められたので行きました。感想としては、甲殻的な虫は素揚げしてあって、食感はサクッとしているがもろく崩れる食感で、そこに香ばしさがあって、苦味はあまりなく、油の風味も相まって、複雑な食体験ができました。蚕は魚の内臓のようなコクがある。初めて虫を食べたので、詳しいことを書けませんが、深みを感じました。何回も食って味の深みを感じたいです。

経緯

 虫を食おうと思ったのは、コオロギが世界の食糧難を救うみたいな記事を友人に見せて店を勧められたことです。最初虫を食うことに対して抵抗感があったのですが、よく考えてみたらそんなに恐怖を感じなくなりました。

 虫を初めて食べることについてなぜ抵抗感を感じるか考えたとき、僕は未知への恐怖やイメージの悪さと見た目の悪さとが主な問題じゃないかと思ったんですね。

 そこで、具体的な解決策について考えてみました。未知への恐怖やイメージの悪さは食わないと分からないし、やってみればそういうのは克服されるものです。たとえば、初めて自転車に乗るときはこけるかもしれないとか考えますが、慣れてみたら、こけるかもしれないとは考えないですよね。サイクリング楽しい、となるかもしれない。それで、だんだん恐怖はなくなっていきイメージは良くなる。次に、見た目の悪さですが、普段食べているものは、見方を変えれば、見た目が悪いので、虫もまた食えるんじゃないかという自信をつかめました。

f:id:tb9810w124816:20180408215240p:plain:w300

 エビを例に考えてみると、もしエビが虫だとしたら、かなり嫌な特徴をもっていますよね。ゴキブリみたいに触覚が明らかに出てるし、ムカデのように足みたいなのがわしゃわしゃ生えている。それでもエビを、エビフライにしてまるごと食べたり生で食べるのは、おいしさを分かってたり身の食感がクセになるということを知っているからで、それって食わないと分からないから、結局は未知への恐怖が問題になるわけです。

 そんなわけで、エビが食えるなら、虫もいけるんじゃねと思い、見た目に惑わされずに舌で味わいながら食べました。おいしかったです。新たな珍味に出会えた日でした。

牛丼を集中して食べて味語り

「カレーをなぜ好きなのか」を説明したい!!!

 こんにちは。くりすぷです。早速質問ですが、ごはんを食べた時に出る感想はどんなものがあるでしょうか?

おいしい。うまい。甘い。辛い。口に入れたらとろける。

といった、一言で済むものが大半でしょう。こうやって言語化してみると、味に対して意外にボキャブラリーが少ないんだなと分かります。 僕は友人を誘って外食に行くことが多いのですが、そのとき食べた味が言葉で表現できないと、他の人においしさが伝えられないことに気づきました。まあ当たり前な話ですよね。おいしさを伝えるためにはどんな味か説明する必要があります。

 でも、いざとなると、他の人に飲食店をすすめるときに、だいたい、「あそこのお店はおいしいよ」程度の表現で終わってしまうため、他の人からすれば、どんな味なのか、本当においしいのだろうかと思われます。カレーライスが嫌いな人はいないと言われていますが、皆さんはカレーライスがなぜ好きかを説明できますか?なぜ、とはいかなくても、ある程度どんな味か説明できますか?  僕はイオンのビーフカレー辛口を以前食べたんですが、それを参考に、カレーライス(ビーフ)についてがんばって説明してみると、

「カレーライスというのは、ごはんにいわば野菜スープを濃縮したものをかけていたもので、このカレールーには、野菜的な甘さや牛のうま味に生姜のようなピリッとしたスパイスの刺激、うんぬんかんぬん」

というように、カレーって意外に深いことに気づきます。今回それを言語化する過程(ブログ)によって、舌に意識を集中して味覚を鍛えます。今回の題材は牛丼です。

牛丼の比較の難しさ

 材料は多分、砂糖、醤油、(出汁、)牛肉、玉ねぎ、ごはんでしょう。牛丼は味付けがだいたい同じです。僕が見る限り、有名牛丼チェーンはどれも同じだと思っている方が多いでしょう。ということは、明らかに尖った味は牛丼の比較をするとなると、舌に集中しないと牛丼について語るのは結構難しい。その差をなるべく言語化したいと思います。なお、「おいしい」は人の好みによって違うため、食感だとか、食材に対する印象について書いていきます。

味に対して感覚を集中させた結果

 吉野家すき家松屋のふつうの牛丼(松屋はプレミアム牛丼)、セブンイレブンの特製牛丼、ローソンの牛丼について味を書いていきます。

711の牛丼と吉野家:他の店よりも牛肉は脂肪分が少なめであるため少しかためで、玉ねぎはシャリとした食感。牛肉が少しかたいため噛む必要があり、するめのように、噛むと牛の旨味が味わえる。醤油や塩や砂糖の味はあまり目立たず、醤油の風味は特に感じられなかった。吉野家については米は他店よりもそんなに甘く感じなかった。711の場合は米が甘く感じた。

松屋すき家:牛肉はやわらかめで脂身が多く、噛めば牛肉の旨味と脂を感じ、玉ねぎはよく煮込まれた野菜のように甘くジュリとした食感。松屋と比べて、すき家の玉ねぎは少し甘味が少ないと感じた。醤油などの味付けに関しては、松屋は醤油の風味を強く感じるが肉の旨味や玉ねぎの甘さを感じられるが、すき家はつゆに甘さを感じた。すき家の牛丼は、すき焼きのように甘さを強く感じるようなつゆに感じた。

ローソンの牛丼:他の店よりも牛肉はかたく感じた。ビーフジャーキーのように、かたいが噛めば旨味を感じる肉であり、他店の牛肉よりも新鮮に感じた。すみません、あと、他に覚えてないです...

感想

 食べてみれば分かるんですが、正直わかりやすい違いはなくて食べまくっていれば、松屋は染み込んだら結構醤油の風味が強いなとか違いが分かってきました。今回は牛肉と玉ねぎの味に集中してたので、米についてあまり書けなかったです。食べ物の味の言語化は難しいですね。おいしいものを食べたら、言語化していこうと思います。

三月の目標の達成度と四月の目標

 じばるどーねのとぼです。これから「小さな目標」と「大きな目標」を立てていくって話を先月しました。

yadrfu.hatenablog.com 要は、

・「ブログ更新」という「週ごとのノルマ」...小さなノルマ

・「今月の目標」という「月ごとの目標」...小さな目標

・「今年度の目標」という「年ごとの目標」...大きな目標

 をしっかり立てて、それらの達成に向けて努力しよう、というものです。

うーーん、なんですけどね、4月入ったから「今年度の目標」を3つぐらい決めようと思ったんですが、どうも、なかなか決まらないです。。。なので今回は、先月の「小さな目標」に対する振り返り・反省と、今月の「小さな目標」の決定をしたいと思います。

 

1. 3月の目標の振り返り

 3月の目標は以下の3つでした。

 ・ブログを10記事書く

 ・AtCoderで水色レート(1200以上)になる

 ・タイピングを2週間続ける

...で結果としては、

 ・ブログを10記事書く ⇒ 達成!!(先月までに10記事投稿)

 ・AtCoderで水色レート(1200以上)になる ⇒失敗... (最終レート1134)

 ・タイピングを2週間続ける ⇒達成!!(というか毎日PCいじってればそれはそう)

ってかんじでした。まあ、一定の作業をすれば必ず達成できる目標は達成したって感じですね...。では、1つ1つの目標に対しての振り返り・反省をしていきたいと思います。(後述:振り返りは気づいたら「である調」になっていた...。)

①ブログを10記事書く (達成!!)

 まあ、3/31のお昼くらいに最後の10記事目を書いたんでギリギリですね。良かった点・悪かった点を以下にまとめる。

<良かった点>

・ちゃんと10記事を投稿したし、ただただ10記事投稿すればいいというわけではなく、ある程度どの記事も内容を自分なりに盛り込んだ(投げやりな記事はなかったと思う)。

・特に最後のPythonの記事は、手段と目的が入れ替わってしまうことがなく、良い振り返りの場としてこのブログという場を利用できた。

<悪かった点>

・10記事投稿を意識しすぎて途中の7,8記事目くらいは手段と目的が逆転してしまった。つまり、記事を書くために必死に何かすることを探していた。そうではなくて、あくまでブログは趣味や学んだことの振り返りに利用していきたい。

・「毎週月曜日の午前中に記事を更新する」という宣言も態々自分で自分を縛り上げて不自由にしているとの指摘を受けた。その通りな気もする。これも手段と目的が逆転しかねない。目標やノルマは、それが達成されたときに何かしらのメリット・成長が自分にあるものの方がいい。ブログの更新時間を目的にしてしまうと、ブログに自分が縛られてしまうので、もう少しこの制約は緩めようと思う。何もこのブログに全力を注ごうという訳ではないのだし,「毎週月曜日の午前中までに記事を更新する」といったはじめのスタンスに近いノルマで十分だ。まあ、折角はじめたブログを辞めてしまうのももったいない気がするので、1週間に1回くらいは更新しようと思う。ただ、春休みが明け「大学生」としての活動で忙しくなるので、もしかしたら1週間更新は難しいのかもしれない。授業が始まってからよく考えようと思う。

 

AtCoderで水色になる (失敗..)

 これが達成できなかったのは結構悔しい。後半2回のARC(特に最後)で酷い結果を残してしまったのが痛かった。ただ、最後のAGCではなんとか600点問題まで解けてパフォーマンスが自己最高の1700超えを果たした。正直、ARC参加しなければAGC終了時点で水色だったなどというネガティブな思考をついついしてしまうが、レートはあくまで複数回の成績から総合的に出されるものであって1回の成績のみに依存するものではないので1回1回のコンテストをもう少し大切にしたい。

<良かった点>

・最後のAGCでパフォーマンスが1700を超えた。実質青コーダーでは?(違う)。しかも、今回のAGCのA問題(300点)は、next_permutationを知っていれば少し楽に解ける問題であり、B問題(600点)もいわゆる約数に関する整数問題で、それらを解けたというのは、Project Eulerをコツコツやっていたことが活きたといってもいい。まあ、もう少し早く解けたとは感じており、やっぱまだ緑だなぁ...。

・コンテストは夜遅いので、始まる前に十分寝て、コンテスト直前は別の作業をあまりしないで精神を安静にさせた方がいいという、心理的なパフォーマンスのあげ方を確信できた。なお、以前「コンテスト前に花澤香菜の声を聴くとパフォーマンスが良くなる」と呟いているプロをTLで見かけたが、私はコンテスト直前に小倉唯の声を聴くとより安静になれる気がした。

<悪かった点>

・1回1回のコンテストに対する姿勢が甘い。最近はTwitterを以前より頻繁に利用するようになり、競プロの強い方ともぼちぼちFF関係にさせていただいているのだが、そういった「つよい人」たちはやっぱりいつも精進しているんだと深く感じる。自分はややもすればボーッと時間をつぶしてしまう所があるので、見習いたい。しかし、こういった方々の普段の努力や生活、競プロ界隈の雰囲気をいうのもある意味ではTwitterを使うようになったから知ることができたわけで、Twitterは意識付けにはとても良い道具だと思う。とにかく、普段からもっと問題を解いたり、理解したり、便利なライブラリを作るなどの精進をしなくては。

・コンテスト前にブログを焦って書いていた日があった。その日のARCが最悪の結果だった。これが最も最悪のパターンであって、やってはいけないことだ。ブログを目的にしすぎると他に悪影響が出る場合があるのだ。コンテスト前は、ゆっくり落ち着いた方がいいし、その日全体でみても一日で身につくことはそう多くないのでコンテストに備えてよく寝た方がましである。

③タイピングを二週間続ける(成功) 

 正直、この目標はよくわからなかった。少しタイピングが速くなったがあんまりかわらない。いわば、カタツムリ🐌の速度から亀🐢の速度になったという程度だ。

<良かった点>

・なんだかんだブログ書いたりプログラミングしたりe-typingしたりして毎日PCはいじる。それはそう。工学生として自明では?

<悪かった点>

・目標がクソ

・そんなに速くはならなかった。ブラインドタッチも、覚えたが見ないと遅いしなぁ...

 

2.四月の目標

 今月も三つ目標を掲げようとおもいます。意味があって、頑張ればできるもの、自分の為になるものを目標に設定しようと心掛けました。 

<今月の目標>

・「実践力を身につけるPythonの教科書」を用いてPythonの学習を一通り終わらせる。(4月の15,16までにこなしたい)

AtCoderで水色になる(今度こそ...!!)

 (その為にすべきことを考えて実際に取り組む)

・これからの自分の研究テーマをしっかり練って論文などを読み漁り決定する。

(そのための技術書も読み始めたい)

 

はい。いろいろな気持ちがうごめく今月の目標であります。

 

今月も頑張るぞい!!

今日も一日頑張るぞい!!

 

Pythonの勉強中

 Pythonはいいぞ、一緒に勉強しましょう~!

 こんにちは、じばるどーねのとぼです。普段(ほとんどCな)C++を使っているんですが、以前に書いたProject Eulerの記事↓

yadrfu.hatenablog.com

 の頃から「Python強くね?」って感じていまして、しかもPython機械学習やWebサイト作りに強い言語とのことで、大分興味が膨れ上がってきて、今更ながらPythonの学習を始めました。進捗はGitHubにも「T0B0o/Python学習その〇〇」って形で随時更新しているんですが、こちらでも少しメモ代わりにPythonについての思ったこと・ポイント・書いたコードなど挙げていきたいなと思っています。

gist.github.com

今の勉強の仕方なんですが、とりあえず1冊本を使って勉強しつつ、実際にコードを打って写経や応用して改変したものをgitに挙げていき、ときどき分からないことなどあればqiitaなどを見ていく...って感じでやってます。

使っている本は実践力を身につけるPythonの教科書」(クジラ飛行機[著])です。マイナビが出しているものです。

  ずいぶん前に、オラクルさんの出してるPython3の本を少しやってみたことがあったんですが、内容がどのページもびっしりで萎えてしまいました。

入門 Python 3

入門 Python 3

 

 ですが、今回この「Pythonの教科書」を読んでみるとサクサク進むのが楽しくて今のところ萎えないで学習できてます。

実践力を身につけるPythonの教科書」のいいところは、

 ・網羅性は高くはないが、重要なところを端的にまとめてあるからサクサク進める!

 ・具体例や絵での説明も結構あり、(本自体のサイズがA4ってのもあるが)ページもすっきりしていて読みやすい!

 ・割りと序盤からライブラリを利用した応用例みたいなのがあって面白い。最終的にはWebコンテンツや一種の機械学習体験までザックリ学ぶことができる!

 

...ってところです。要は「パパっと学習できて、パパっと応用できる!」ってことです!!

目標としては、とりあえず4月上旬(15,6日くらいまで??)までに「Pythonの教科書」を一通り終わらようと思っています。

 

めっちゃシンプルだけど好きなコード

 Pythonの教科書でリストの勉強しながら書いた「ナベアツ数判定プログラム」です。ナベアツがアホになる数(3で割れる数、または3がつく数)を入力された文字列の中から引き抜いて列挙するものです。シンプルですが、C++とかで書くよりもアッサリしている気がするし、なんとなく好きです。

#ナベアツ数Judge
nabe=[]
while True:
   f=input("整数を入れてね(入力完了はq) : ")
   if f=="q": break
   if f.isdigit()==False : continue
   fi=int(f)
   if fi%3==0 :
      nabe.append(f)
      continue
  while fi>=1:
      if fi%10==3 :
      nabe.append(f)
      break
      fi//=10
print("ナベアツ数は",nabe,"です")

   なお、関数isdigit()は、「変数.isdigit()」って書くと、変数が数字のみで構成されているときだけTrueを返します。

 実際に実行して色々やってみた結果がこちら。

f:id:tb9810w124816:20180331130652p:plain

日本語入力や全角数字入力にも対応してくれるisdigit()神。

 

最後に...

  なんだかオラクルさんの「Python3入門」を批判するみたいになっちゃってますが、実際のところ全くそんなつもりはなくて、これは個人の相性だと思います。「Python入門」の方がPythonを深く学ぶ上での網羅性は高く、書かれていることの権威みたいなのはより高いと思うので、じっくりPythonの本質(??)を理解したいぜ!みたいな方にはお勧めできると思うんです。ただ、飽きっぽい人とか、サクサク学習を一通り終わらせたい人にとっては少し長すぎるかもしれません。私は後者だったので萎えましたが、両方の本を比較して選んだ方がいいかもしれません。

 自分に合った本は自分の目で見極めよう!!

おしまい。