グレインの備忘録

プログラミング関係とかをつらつらと。

Ubuntu16.04にTex環境を整える

LaTeXを使ってみたかったのでUbuntuに入れてみた。

基本苦労することはなかったが入れ方を一応メモ。

インストール手順

必要なのは、

の二つ。

Ubuntuの場合は

$ sudo apt -y install texlive texlive-lang-japanese

で済む。

使い方

まずは入門サイトなど参考にTeX文書を作る。

LaTeX入門 - TeX Wiki

完成したら保存する。

コンパイル

例えば「test.tex」に保存したとすると、

$ platex test

でdviファイルが生成される。

あとはこれをpdfに変換すればいいので、

$ dvipdfmx test.dvi

でpdfが生成される。

若しくは、一発でpdfに変換するには

$ ptex2pdf -l test

とすればよい。

Cmake+Ninjaでビルドをやってみる

最近プログラムをビルドするのにCmakeを使い始めてみた。

Cmakeでは、軽量な動作で有名なNinja用のファイルを生成できるらしいので試してみる。

Ninjaのインストール 同名のパッケージにご用心

早速入れてみようと、安直に以下のコマンドを実行。

$ sudo apt -y install ninja

ところが、

$ cmake . -G Ninja

とするとエラーが。

-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler using: Ninja
CMake Error:
  The detected version of Ninja (0.1.3) is less than the version of Ninja required
  by CMake (1.3).


CMake Error: Internal CMake error, TryCompile generation of cmake failed
-- Check for working C compiler using: Ninja -- broken

バージョンが古くて怒られている模様。確かに、

$ ninja --version
log: ninja version 0.1.3 initializing

と出るので、バージョンが低いらしい。apt提供のパッケージが古いのか?と思い

$ apt search ninja

とすると、

ninja/xenial,now 0.1.3-2 amd64 [インストール済み]
  GNU/Linux 用特権昇格検知システム

ninja-build/xenial,now 1.5.1-0.1ubuntu1 amd64 
  small build system closest in spirit to Make

ninja-build-doc/xenial,xenial 1.5.1-0.1ubuntu1 all
  documentation for ninja-build

ninja-ide/xenial,xenial 2.3-2 all
  integrated development environment (IDE) for Python

と出てきた。どうやらさっきのninjaはビルドツールではなかったらしい。

気を取り直して

$ sudo apt -y remove ninja
$ sudo apt -y install ninja-build

として入れなおす。これでうまく行くだろう。

ツールチェインの切り替えにご注意

ところが、

$ cmake . -G Ninja
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler using: Ninja
CMake Error:
  The detected version of Ninja () is less than the version of Ninja required
  by CMake (1.3).


CMake Error: Internal CMake error, TryCompile generation of cmake failed
-- Check for working C compiler using: Ninja -- broken

またもやエラー。今度はバージョンが検出されていない模様。

調べてみると、以下のページに行き当たった。

github.com

以下引用

"if previously build dir already configured , but ninja executable is moved, cmake didn't report command not found ,but reports "The detected version of Ninja ("") is less than the version of Ninja required by CMake ("1.3") which is confused."

要するに、残骸が残っているとダメということらしい。ということで、

$ rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile
$ cmake . -G Ninja

というふうに残骸を消してやるとうまく行った。

確かに軽量だが出力がログみたいに残らずに消えてしまうのが少し残念かもしれない。

リンクが倍速くなるらしい「lld」を試す

最近、ビルトインのldによるリンクの遅さが気になってきた。

そこで、もっと高速なリンク方法がないか探してみたところ、いくつかの新しいリンカに辿り着いた。

GNU goldよりも2倍早いlld

高速なリンカとしてはGNU goldが割と有名らしいが、それよりも更に高速なlldというものを見つけた。

https://lld.llvm.org/

このページ曰く「GNU goldの2倍高速で」動作するらしい。

lldのインストール

Ubuntu 16.04 (Xenial Xerus) にはパッケージがあるようなので入れてみる

sudo apt -y install lld-4.0

これでld.lldが利用可能になる。

ついでに、ldのシンボリックリンク切り替えの設定もしておく。

参考: qiita.com

sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.lld" 30
sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20
sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.bfd" 10

これで登録は完了で、あとは

sudo update-alternatives --config ld

とすることでldの切り替えができる。

実際に使ってみた感じとしてはやはり数倍早くなっている感じだ。
少し待たされるようなジョブも一瞬で終わるようになった。
おそらくconfigureの速度を大きく改善するであろう。

構造体のDictionaryでは直接値を変更できない

コンテナの返値が値型か参照型かに気をつけましょうねという話。

シチュエーション

例えば、以下のようなコードを書いてみたとする。

public class Program
{
    struct MyStruct
    {
        public int val1;
        public int val2;
    }
    
    public static void Main()
    {
        var dic = new Dictionary<int, MyStruct>();
        
        dic[0].val1 = 1;
        dic[0].val2 = 2;
    }
}

自前の構造体をDictionaryに格納し、その値を変更するコードである。

しかし、これはコンパイルエラーになる。

error CS1612: 変数ではないため、'Dictionary.this[int]' の戻り値を変更できません

Dictionary内の要素に値を代入することができていないようだ。

dic[0]の返値は参照型ではなく値型

実は、これはMyStructが値型であることが原因である。

つまり、dic[0]というのは、dic内の0番目の要素のコピーであって、それに対していかなる操作を行ってもdic内の要素には一切影響しない。

上記のように[]で参照したものの値を直接書き換えたいならば、MyStructをclassにするしかない。

public class Program
{
    class MyStruct
    {
        public int val1;
        public int val2;
    }
    
    public static void Main()
    {
        var dic = new Dictionary<int, MyStruct>();
        
        dic.Add(0, new MyStruct());

        dic[0].val1 = 1;
        dic[0].val2 = 2;
    }
}

これならdic[0]はdic内の0番目の要素への参照となり、正しく動く。


C++ならコンテナは必ず参照型を返してくれるので、原因が分かるのに時間がかかった。

コンテナのイテレータを保持するのは避けよう

STLとかのコンテナが吐き出すイテレータをポインタ代わりに持っとくのはやめましょうねというお話。

コンテナへの非const操作はイテレータを破壊する(可能性がある)

「可能性がある」だから余計厄介だったりする。

テストケースではうまく動いても実環境では動かなかったり。

詳しい話はこちらのページに投げさせていただく。

qiita.com

neosnippetに自分のスニペットを追加する

前回の記事ではneosnippetを導入したが、自作のスニペットを使いたくなったので方法をメモ。

neosnippetの設定

まずは、スニペットファイルの保存先を指定する。

プラグイン起動時の設定に一行追加する。

let g:neosnippet#snippets_directory = ~/.vim/dein/repos/github.com/Shougo/neosnippet-snippets/snippets/'

したら再起動する。

スニペットの編集

まずは、スニペットを追加したいタイプのファイルを開く。

そして、「:NeoSnippetEdit」とコマンドを入力する。

すると、スニペットの編集画面が開く。

スニペットの構文は以下の通り。

snippet [識別子]
alias [略記法]
<インデント>スニペット内容
<インデント>スニペット内容
…

スニペット内容は基本は展開したい内容をそのまま書く。

また、Ctrl+Kで順にカーソルが移動できるような場所は「${数字:デフォルト値}」として書けばよい。

終わったら「:w」で保存する。


以上でスニペットの追加は完了である。

OOP初心者がブロック崩しを作ってみる その2

※この記事は「OOP初心者がブロック崩しを作ってみる その1」の続きです

衝突判定を考える

さて、衝突判定のやり方を考えよう。

衝突はボールとReflectorの間で起こる。とりあえず以下のようにクラス分けしてみる。

f:id:grainrigi:20170902161501p:plain

ReflectorCollectionにReflectorを全て格納しておいて、Ball側から参照、衝突判定を行う。

move関数はBallに速度に従っての移動を指示する関数で、移動するたびに衝突判定を行う。

BallとReflectorのgetRect関数はそれぞれの専有する範囲を返す。(衝突判定に使用)

衝突判定を外に出す

これでも悪くはないが、Ballが「移動する物体」と「衝突する物体」の2つの役割を持っているので、分割したい。

ということで、衝突判定は外に出し、Ballは速度に従って移動することに専念することにする。

f:id:grainrigi:20170902163639p:plain

CollisionManagerが衝突判定を担当する。

流れとしては、

  1. Ballのmove関数が呼ばれる
  2. Ballが速度に従って移動
  3. BallがexecuteCollisionを呼ぶ
  4. CollisionManagerが全Reflectorと衝突判定
  5. CollisionManagerがgiveImpulseを呼び、ボールに力積を与える

という感じ。

Observerパターンを適用する

結合度の面から言えば、BallとCollisionManagerがお互いの関数を直接呼び出しているのであまり良くない。

そもそも、CollisionManagerはボールの移動をトリガーとして衝突判定を行うのである。

したがって、CollisionManagerがボールの移動を監視すれば良い。

つまり、Observerパターンを適用する。

f:id:grainrigi:20170902171012p:plain

move関数で移動した後、observerに移動を通知する。

これで多少はすっきりした。

Reflectorが衝突を知るには

ブロックのように衝突の有無を情報として必要とするReflectorが存在するので、それを通知する必要がある。

それもCollisionManagerが担当するのが妥当であろう。

以上のことを加味してまとめたクラス図はこうなった。

f:id:grainrigi:20170902171952p:plain

衝突判定に関しては概ねこのような感じでいいだろう。

次回予告

次回「OOP初心者がブロック崩しを作ってみる その3」は、この大まかな設計を基に実際にコードを書いてみることにする。