C++ でハミング重みを求める その2
前回は自分でコードを書いて求めたのですが、そもそも <bitset>
使えば簡単に求めることが出来ます。
#include <bitset> #include <iostream> int main(){ std::cout << std::bitset<32>(100).count() << std::endl; std::cout << std::bitset<32>(9859712).count() << std::endl; std::cout << std::bitset<32>(0b10111110).count() << std::endl; return 0; } /* output: 3 9 6 */
C++ 的にはこれが一番楽そう
C++ でハミング重みを求める
ここに載ってる『1からNまでの数字を2進数に変換してbit 1 をcountする』って処理をもっと簡単に出来ないのか調べてみました。 こういう『シンボル列中の 0 以外のシンボルの個数』のことをハミング重みというみたいです。 で、まさに『bit 数から 1 の個数を求める』というアルゴリズムがありました。
[コード]
int popcount(int x){ x = x - ((x >> 1) & 0x5555555555555555); x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f; return (x * 0x0101010101010101) >> 56; } #include <iostream> int main(){ std::cout << popcount(100) << std::endl; std::cout << popcount(9859712) << std::endl; std::cout << popcount(0b10111110) << std::endl; return 0; }
[出力]
3 9 6
[参照]
OS X 10.9/10/11 7.4.2196 がリリースされた
ついこの間リリースされたばかりなんですが、また新しいのがリリースされました。
何か不具合でもあったのかな。
C++11/14 でテンプレートを使用する場面
C++03 ではせいぜいクラスや関数ぐらいでしかテンプレートを使う場面はなかったのですが C++11/14 でテンプレートを使う場面が増えたのでまとめてみました。
クラステンプレート(C++11)
クラスにテンプレート型を渡します。
template<typename T> struct holder{ T value; }; holder<int> n = { 10 }; holder<float> f = { 3.14f };
関数テンプレート(C++11)
関数にテンプレート型を渡します。
template<typename R, typename T> R twice(T t){ return t + t; } int n1 = twice<int, int>(2); int n2 = twice<int>(3.5); // 引数型を省略することも可能
関数の場合は、引数からテンプレート型を推論する事ができるので、引数のテンプレート型を省略する事が出来ます。
エリアステンプレート(C++11)
C++11 から追加された template aliases
という機能で使用します。
これは同じく C++11 で追加された using
を使用した型エイリアス対してテンプレートを定義します。
// std::string をキーにした std::map 型を定義 template<typename T> using my_map = std::map<std::string, T>; my_map<int> table = { { "homu", 1 }, { "mami", 2 }, { "mado", 3 } };
変数テンプレート(C++14)
これは C++14 から追加された機能ですが『すでに定義してる変数の型をテンプレートを使用してあとから定義する』ような機能になります。 例えば、『PI の値を任意の型で定義したい場合は次のように利用することが出来ます。
template<typename T> T pi = static_cast<T>(3.141592); int i_pi = pi<int>; // 3 float i_pi = pi<float>; // 3.14159
これは pi<int>
の場合は static_cast<int>(3.141592)
が返ってきて、pi<float>
の場合は static_cast<float>(3.141592)
が返ってきます。
他のテンプレートとは違い pi<int>
は型ではなくて値が返ってくるのがすごく奇妙に感じますね。
可変長テンプレート引数(C++11)
これは、特定の場面で使用するわけではないですが(むしろテンプレートが使える場面ではどこでも使えますが)テンプレート型を可変長に受け取る事が出来ます。
template<typename... Args> struct holder{ std::tuple<Args...> data; }; holder<int, float, bool> table = {{ 42, 3.14f, false }};
上記のコードは簡単な例ですが、今回上げた中では一番学習コストが高い機能だと思います。
他には関数で『型情報がある可変長引数を受け取りたい』場合などに利用できます。
まとめ
テンプレート自体は突き詰めると『型を引数として渡す機能』だけなので普通に使う分にはそんなに難しくはないと思います。
ただ、C++11/14 でテンプレートを使う場面はかなり増えたので学習コストは上がってきていると思います。
C++03 の頃は敬遠されがちだったテンプレートですが、今は C++ を使う上で必要な技術になりつつあると思います。
Ruby の func [] と func[] の違い
Ruby ではメソッドの呼び出しに ()
を省略することができるので、次のような奇妙なコードを記述することが出来ます。
def func *ary ["homu", "mami", "mado"] end p func [1] # => ["homu", "mami", "mado"] p func[1] # => "mami"
これは func [1]
が func
に [1]
を引数として渡しているのに対し、func[1]
は func
の戻り値に対して [1]
を呼び出しているからです。
明示的に括弧を書くと
def func *ary ["homu", "mami", "mado"] end p func([1]) # => ["homu", "mami", "mado"] p func()[1] # => "mami"
こんな感じになります。
DSL なんかを書いてる時にうっかりハマりそうなので注意する必要が有ります。
rbenv で gem install したコマンドが呼び出せなかった場合の対処
rbenv で Ruby を管理使用としたんですが、何故か bundle
コマンドが使えませんでした。
そういう場合は以下のように rehash
を使うと改善されるみたいです。
$ rbenv rehash
Vim 7.4.2170 で timer_info() が追加された
patch 7.4.2170 で timer_info()
関数が追加されました。
この関数は現在実行中の timer
の情報を返す関数です。
echo timer_info() " => [ " { " 'callback': function('<SNR>489_timer_handler'), " 'id': 2, " 'remaining': 420, " 'repeat': -1, " 'time': 500 " }, " { " 'callback': function('<SNR>489_timer_handler'), " 'id': 1, " 'remaining': 420, " 'repeat': -1, " 'time': 500 " } " ]
また、timer id
を指定することも出来ます。
let s:id = timer_start(500, function({ l -> \ execute("let l.value += 1 | echo l.value", "") \}, [{"value" : 0}]), { "repeat" : 5 }) " Timer ID を指定することもできる " この時にも戻り値は配列なので注意 echo timer_info(s:id) " => [{'id': 16, 'repeat': 5, 'remaining': 499, 'time': 500, 'callback': function('<lambda>7', [{'value': 0}])}] " ちょっと待機 sleep 1 " 残りの repeat 回数が減ってる echo timer_info(s:id) " => [{'id': 16, 'repeat': 3, 'remaining': 498, 'time': 500, 'callback': function('<lambda>7', [{'value': 2}])}]
あとから timer
を止めたい場合とかに便利そう。