今日から4日間は普通に過ごす

July 2020 · 7 minute read

こんにちはRockinWoolです。最近は仕事でもマークダウンを使用しているので、少々使い方に幅がでてきたかな・・・という感じです。マークダウンって凄い楽なので良いですね〜。
さて、今日はPythonやCに慣れる日と決めていたので早速実況しながら色々やって行こうと思います。

  1. Python3.8にアップデート

    「python3.8からf文字がデフォルトで入ってくるのではないか?」という噂を聞いていたので、そろそろアップデートしておこうと思ってやりました。f文字はprint文の書き方が楽になるやつ。例えば

    print(f'バラバシアルバートモデルを追加次数{m}で作成します')
    結果>>バラバシアルバートモデルを追加次数2で作成します
    

    といった感じで簡単に書き込むことができる仕組みのことです。噂では先頭のfを入れなくても対応してくれるようになったと聞いていたわけです。以下のコマンドを実行してanaconda(in Ubuntu)のPythonをアップデートしました。

    conda install python=3.8
    
  2. Atcoderに挑戦

    1. Atcoderへの登録

      前々から興味あったAtcoderに登録しました。で、最初の練習問題すら解けず(Pythonでもわからなかった)これは再修行が必要だなと思いAtCoder Programing Guide for beginnersをやることにしました。まあ、前々からC++に興味がありましたので、ここの恥はすぐに取り返して来月にはツヨツヨプログラマの仲間入りを果たしてやりたいですね()

    2. C++の修行の開始

      まず、C++のプログラムの基本形は

      #include <bits/stdc++.h>
      using namespace std;
      
      int main(){
      }
      

      らしいです(恥ずかしながらほぼコピペ)。もはやプログラマとして自信を持っていた自分が偉く恥ずかしいナウであるわけですが、この呪文の意味を知るところからはじめようと思います。たしかC言語では#include<stdio.h>て感じで標準入出力のヘッダファイルを読み込んでいたような・・・かすかな記憶ですが。調べたらこのヘッダファイルの本体は一般的には/usr/include/stdio.hにあるらしいですね。未だに/usrの立ち位置が分かっていない・・・。というより何も分かっていないんでしょうな私は。ということでbits/stdc++.hについても調べてみました。参考ページ
      ふむ。どうやら、普段使うようなc++の基本のライブラリであるlibstdc++(スタンダードC++ライブラリってことなのかな?)を改造してまとめてコンパイルしたプリコンパイル済みのヘッダファイルってことっぽいですね。つまりはこれを#includeしておけば大体使いたいライブラリは揃っているって感じなのでしょう。速さの利点があるため、競技プログラミングの世界では普通に使われているそうですが、linuxの環境以外(というよりGCC)では無いところではそもそもlibstdc++が使えないのでこの呪文もバグの原因になってしまうそう。ちょっと悩みましたが、今の自分の環境もubuntuなのであまり気にせずにどんどん#include<bits/stdc++.h>を使っていって慣れて行こうとおもいます。

    3. C++の出力

      実はこれが一番ビックリした内容かもしれません。出力がprintfで無い・・・だと?

      #include <bits/stdc++.h>
      using namespace std;
      
      int main() {
          cout << "Hello_World">>endl;
      }
      

      これはどういうことだ?C++はC言語の拡張だから互換性とかでprintfは使えるのでは無いのか?となったので調べました。
      その結果、どうやら2つの理由があるようですね。

      1. C言語のprintfは脆弱性がある
      2. std::coutは型チェックがあるので異常な出力が出にくい

      まあ、英語の資料ばっかり出てくるのでなんとなくの意味合いしかわからないのが多かったのですが。coutのほうが早いのならば納得できる部分もありますが、脆弱性回避の意味合いのほうが強いとするならば競技プログラミングではprintfを使う価値もあるのかしら?まあ、ここは先人のツヨツヨプログラマに倣ってcoutを使うことに慣れていこうと思います。

      そういえばこれを調べている時に気づいたのですが、2行目のusing namespace std;を入れることによってstd::coutを使うときにcoutだけで済むようになるらしいです。namespaceというのだからコンテナとかと関係があるのかしら?と踏んでいたのですが、どちらかといえばPythonのimport numpy as npのほうに近いのかしら?一応調べておきます。

    4. 名前空間

      ああ、またコイツか。仕事でも出会うヤバイヤツってイメージしか無い。名前空間はコンテナ化に必要な技術で、「こいつを正しく設定することによってシステムの頑強性を高めます!」って謳い文句を何も分かってなさそうなコンサルが上長にオススメしている印象しかない。この際だから慣れてしまおうか。
      まず、冒頭のusing namespace std;。こいつはどこからどう読んでも「stdってヤツ(namespace)を使うぜ!」って宣言しているようにしか見えない。解説サイトなどを読んでもstdという名前空間内に様々な関数などを登録しておけば、それをusing namespace stdすることによってstd名前空間内にあるものはそのプログラム内ではグローバル変数チックに登録されるという流れのように見える。
      つまり、本質的にfrom numpy import hogeとは異なるものの使い勝手としては大した差は無いという感じかな?個人的にはimport numpy as npのほうが、プログラム内の関数とnumpyの関数が同じ関数名になっても助かる可能性があるので後者のほうが好きなんですよね(トラウマ)。ですので、名前空間をまとめてusing namespace std;するのは流石のツヨツヨ先人の呪文とは言え採用は難しいです・・・。自分はstd::coutって宣言したいなあ・・・。ダメかなあ・・・。
      というか結局、基本的にこの程度の隔離がコンテナ空間の隔離にまで至る気持ちがあまりわからなかった・・・。

    5. コメントの記法

      これも「ああ、こんな感じだったね・・」ってなった内容です。Pyhtonのコメントは#であるのに対してCは//や/**/でしたわ。

    6. 細かい話

      さっき一生懸命(?)探した#include<bits/stdc++.h>using namespace std;の解説が乗ってました。哀れ自分。 coutは#include<iostream>と書くことによって個別に読み込むことができるそうですね。業務ではこちらが推奨されるとも書いてあるので、コンテストでもこちらを使って行こうかしら(気持ちのブレ)。using namespce std;も業務で推奨されないとか書いてあるので極力使わないで行こうかな。

    7. iostreamの罠

      ということで例題を解いてみたんですけど、ACになるまでめっちゃかかってしまって自分でも面白かったです。とりあえず今回かいてみた回答はこんな感じ

      #include <iostream>
      
      int main(){
          std::cout << "こんにちは" <<std::endl;
          std::cout << "AtCoder" <<std::endl;
      }
      

      ミスの一覧: \

      1. <iostream><iostream.h>と打ってしまってコンパイルエラー

      2. int main(){}が正解なのにintを抜いたり、()を抜いたりする

      3. coutのstdを抜く(なんでやねん)

      4. endlにstdが必要だったのに気づかなかった

        特にこれが一番悔しかっった。冷静に考えればendlは文字列ではなくendlineを意味する関数であるのは当たり前。iostream内のstdネームスペースのendl関数であったということ。

      とりあえず、ここで休憩をはさみつつ、次の勉強会の内容はこれにしようと思ったRockinWoolなのでありました。