2012年5月13日
#
来週土曜日、わんくま同盟東京勉強会っす。
「.NETの一切出てこない勉強会やってもいぃんぢゃね?」
...言いだしっぺの法則発動、僕がディレクタやることに。
Lua と Java と C++ と Windows8 をネタに一日過ごします。
目玉は荒井さんのMetroなおハナシかなやっぱ。
WinRTとやらのおかげでXAMLなアプリがnativeで書けちゃうのね。
N種のカードをガチャする。どのカードを引くかはどれも同確率。
N種のカードをコンプするには何回ガチャすることになるんだろ。
やってみた:
#include <iostream>
#include <random>
#include <set>
#include <map>
#include <string>
using namespace std;
int main() {
const int N = 10; // カード数
const int trials = 1000; // 試行回数
mt19937 engine; // メルセンヌ・ツイスター
uniform_int_distribution<int> dist(0,N-1); // 0..N-1 一様分布
auto gacha = [&]() { return dist(engine); }; // 0..N-1 一様乱数
set<int> items; // 入手したカード種
map<int,int> hist; // 度数分布表
int max_trials = 0;
for ( int i = 0; i < trials; ++i ) {
int draws = 0;
items.clear();
// コンプするまでガチャを繰り返し、
// ガチャ数を度数分布表に累積する
while ( items.size() != N ) {
++draws;
items.insert(gacha());
}
++hist[draws];
if ( max_trials < draws ) max_trials = draws;
}
// 度数分布を出力する
for ( int i = N; i <= max_trials; ++i ) {
cout << i << ':' << string(hist[i],'#') << endl;
}
}実行結果はコチラ:
10:
11:
12:###
13:########
14:###############
15:############
16:##############
17:#############################
18:#######################################
19:#########################################
20:#########################################
21:##############################################
22:############################
23:######################################################
24:####################################
25:##############################################
26:##########################################
27:###########################################
28:##############################################
29:###########################################
30:################################
31:####################################
32:#####################################
33:##################
34:##########################
35:############################
36:####################
37:###################
38:###############
39:#############
40:####################
41:#################
42:##############
43:################
44:#############
45:#######
46:###########
47:########
...
N=10 のとき、23回あたりにピークがありますな。
一回100円としてコンプまでにおおむね2300円。
上の結果は途中で切ってるけど、7300円つぎ込んだバカがひとりいました。
2012年4月28日
#
レビューやらせていただきましたよ。
んで、せっかくだから「周回遅れにもほどがあんぞヲイ」なWPFに手を付けます。
いやね、Visual Studio 11でよぅやっとC++/CLIのインテリセンスが復活してくれたんで、
マンドクセーことやる気になったっちゅーのが本音。
てかさ、WPFアプリケーションてばC++の出番ナシなのが癪に障るんで、
ひな形生成だけをC#にやらせ、残りはぜーんぶC++/CLIで書いてみるココロミ。
おためしにこしらえたのは毎度毎度のカウンター。
「3.2.3 視覚的デザインツールの利用」にあったMVVMをほとんどそのままパクらせてもらいました。

<Window x:Class="DataBindingSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="データ バインディング サンプル" Width="193" SizeToContent="Height" Height="157">
<StackPanel>
<TextBox Text="{Binding Count}" FontSize="36" FontWeight="Bold" TextAlignment="Center" />
<Button Content="+" Command="{Binding IncCommand}" />
<Button Content="-" Command="{Binding DecCommand}" />
</StackPanel>
</Window>
XAMLはこんな↑カンジね、表示とボタンをそれぞれ CountとIncCommand/DecCommandにバインドしてます。
以降C#からはしばらくオサラバ、C++/CLIでCLRクラスライブラリを用意して参照させます。
ViewModel がコレ↓
#ifndef MAINWINDOWVIEWMODEL_H__
#define MAINWINDOWVIEWMODEL_H__
namespace DataBindingSample {
public ref class MainWindowViewModel : public System::ComponentModel::INotifyPropertyChanged {
public:
property int Count {
int get();
void set(int value);
}
virtual event System::ComponentModel::PropertyChangedEventHandler^ PropertyChanged;
void attachCommand(System::Action<Object^>^ inc, System::Action<Object^>^ dec);
void Update(int count);
property System::Windows::Input::ICommand^ IncCommand
{ System::Windows::Input::ICommand^ get(); }
property System::Windows::Input::ICommand^ DecCommand
{ System::Windows::Input::ICommand^ get(); }
private:
int _Count;
System::Windows::Input::ICommand^ incCommand;
System::Windows::Input::ICommand^ decCommand;
};
}
#endif
attachCommandでView(のIncCommand/DecCommand)からModelに、
UpdateでModel(のカウント値変更)をViewに飛ばします。
カウンタ本体:Counter と ViewModelに接続するための CounterModel はそれぞれ:
#ifndef COUNTER_H__
#define COUNTER_H__
namespace DataBindingSample {
public ref class Counter {
public:
void inc();
void dec();
int count();
private:
int count_;
};
public ref class CounterModel : Counter {
public:
// Model→ViewModel
event System::Action<int>^ CountUpdatedHandler;
// ViewModel→Model
property System::Action<Object^>^ Increment { System::Action<Object^>^ get(); }
property System::Action<Object^>^ Decrement { System::Action<Object^>^ get(); }
private:
void Notify();
void inc(Object^ dummy);
void dec(Object^ dummy);
};
}
#endif
CountUpdateHandlerとIncrement/Decrement がViewModelとの接続ポートになってます。
んでもって MainWindow, MainWindowViewModel, CounterModel をがしゃがしゃ繋ぐトコ
をC#側にねじ込みます。 MainWindowViewModel と CounterModel は App のstaticメンバ
にしちゃいました。
/*
* App.xaml.cs
*/
using System.Windows;
namespace DataBindingSample {
public partial class App : Application {
public static MainWindowViewModel ViewModel {
get {
if ( viewmodel_ == null )
viewmodel_ = new MainWindowViewModel();
return viewmodel_;
}
}
public static CounterModel Model {
get {
if ( model_ == null )
model_ = new CounterModel();
return model_;
}
}
public static MainWindowViewModel viewmodel_;
public static CounterModel model_;
}
}
/*
* MainWindow.xaml.cs
*/
using System.Windows;
namespace DataBindingSample {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
this.DataContext = App.ViewModel;
App.ViewModel.attachCommand(App.Model.Increment, App.Model.Decrement);
App.Model.CountUpdatedHandler += App.ViewModel.Update;
}
}
}
C++/CLI側の実装(.cpp)は割愛。ソリューションまるごとうpするから読んでやって。
白状すればMVVMってハジメテなの。おもきし我流だし。ガスガス突っ込んでやってくだせ。
2012年4月6日
#
本日の衝動買い:
プロコフィエフ 「ピーターと狼」
サン・サーンス 「動物の謝肉祭」
ブリテン 「青少年のための管弦楽入門」
小沢征爾/ボストン交響楽団
地獄のミサワ 世界のオザワが曲中のしゃべくりまで
やってくれちゃってるってんで買っちゃいました。
…いぃねぇ、小学校の音楽室で聴いたヤツよね♪
ボストンはらっぱが元気でよろしいな。
ベルリンとかもちろん超一流で文句のつけようもないけれど、
ボストンやフィラ管の威勢のいいスカッとした響きは好きですよー
もいっちょ:
ロードショー封切りで観たしDVDも持ってるけど、
マザボ交換ついでにBlu-ray driveに取り替えたくせに
data用にしか使ってなかったんで一枚くらいは。
うわー、Blu-rayの情報量ハンパないわ。
こんなの観ちゃうとDVDはショボいねー。
音も良いすねー、
サー・ネビル・マリナーの曲がツヤツヤしてます。
2012年3月30日
#
僕のお仕事は社内相談事よろず承り係みたいなもんで、開発絡みのヘルプ・デスクと申しましょうか、ライブラリやツールの調査/評価とか、お望みとあらばサンプルコード書いてあげたりとかもやってます。
先日社内に山とあるプロジェクトの各リーダーにアンケート投げて開発環境調査やってるヒトとお話ししてたらば、社内ではCでの開発が(かなり減ってはいるものの)未だ現役バリバリなんだとか。
それじゃこんなオモチャはどうだろう、ってんで作ったのが「CUnit用ハリボテ生成機:cusg」っす。
コマンドラインから
> cusg foo=fok1+fok2+fng1+fng2 > main.c
とかやると、fok1,fok2,fng1,fng2 の4つのテスト(ナカミはからっぽ)が定義されたfoo_test.cができます。
これと標準出力から拾ったmain.cをコンパイルし、CUnit.libとリンクすればとりあえずCUnit-testができちゃうです。
2012年3月28日
#
60GBのSSDにWindows 7 Ultimate 64 まるっとぶち込んで残り十数GB、しばらく使って何度かUpdateかけたらあえなくパンクしちまいましたよコノヤロー。
おかげで先の土日はせっせと再インスコ、OS入れてOffice入れてVisual Studio入れてVisual Studio入れてVirtualBox入れてVisual Studio入れてVisual Studio入れてたらお休み終わっちゃったヨ
そこいらへんに転がってた1TB-HDに引っ越して、余ったSSDにVisual Studio Solution群を納めました。うわーSSDにSolution置くとめっさ快適です。ビルドがやたらと早い。Solution丸ごとre-buildしてもあっちゅーまですわ(論理8coreはダテじゃねぇ)。
Visual Studio 11 Beta がなかなかに面白くて毎日くだらんコード書いてはコンパイラいぢめて遊んでます。いぢわるスタジオです。
ともかくも インテリセンス/CodeSnippetが使えるよになり喜ばしい限り。
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets
xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format ="1.0.0">
<Header>
<Title>C++ class decl.</Title>
<Author>επιστημη</Author>
<Description>C++ クラス宣言</Description>
<Shortcut>classdecl</Shortcut>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>CLASS</ID>
<ToolTip>クラス名</ToolTip>
<Default>CLASS</Default>
</Literal>
</Declarations>
<Code Language ="CPP">
<![CDATA[class $CLASS$ {
public:
$CLASS$(); // default ctor
$CLASS$(const $CLASS$& other); // copy ctor
virtual ~$CLASS$(); // dtor
$CLASS$& operator=(const $CLASS$& other); // copy op.
private:
};
]]>
</Code>
</Snippet>
</CodeSnippet>
<CodeSnippet Format ="1.0.0">
<Header>
<Title>C++ class impl.</Title>
<Author>επιστημη</Author>
<Description>C++ クラス実装</Description>
<Shortcut>classimpl</Shortcut>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>CLASS</ID>
<ToolTip>クラス名</ToolTip>
<Default>CLASS</Default>
</Literal>
</Declarations>
<Code Language ="CPP">
<![CDATA[// default ctor
$CLASS$::$CLASS$() {
}
// copy ctor
$CLASS$::$CLASS$(const $CLASS$& other) {
if ( this != &other ) {
}
return *this;
}
// dtor
$CLASS$::~$CLASS$() {
}
// copy op.
$CLASS$& $CLASS$::operator=(const $CLASS$& other) {
return *this;
}
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
こんなの書いてスニペット・マネージャにインポートしとくと幸せになれたり。

2012年3月27日
#
stateless lambda は関数ポインタに暗黙変換できるっちゅーんだから、
delegateだって作れるはずよね...
#include <iostream>
using namespace System;
using namespace std;
public ref class Counter {
public:
delegate void OnUpdate(Counter^ counter);
Counter() : value_(0) {}
void incr() { ++value_; handler(this); }
property int count { int get() { return value_; }}
event OnUpdate^ handler;
private:
int value_;
};
void print_fun(Counter^ counter) {
cout << counter->count << endl;
}
int main() {
Counter^ counter = gcnew Counter();
auto print_lambda = [](Counter^ counter) { cout << counter->count << endl; };
counter->handler += gcnew Counter::OnUpdate(print_fun); // OK
counter->handler += gcnew Counter::OnUpdate(print_lambda); // error
counter->incr();
return 0;
}
...ダメでした orz
くやしいのでConnectにfeedbackしたです。 voteしてくれさい。
2012年3月16日
#
Visual Studio 11 Beta にて:
#include <iostream>
#include <locale>
#include <Windows.h>
using namespace std;
int main() {
wcout.imbue(locale("japanese"));
// EnumWindows に与える CALLBACK に stateless lambda を。
EnumWindows([](HWND hWnd, LPARAM lParam)->BOOL {
TCHAR buf[256];
GetWindowText(hWnd, buf, 256);
if ( buf[0] != L'\0' ) {
*reinterpret_cast<wostream*>(lParam) << buf << endl;
}
return TRUE;
},
reinterpret_cast<LPARAM>(&wcout));
}
あらおもしろい。stateless lambda を Win32-callback に使えるのね。
ふしぎねー、コンパイラくんてば __cdecl か __stdcall かを判別して
善きに計らってくれちゃうのね。
2012年3月9日
#
C++11の新機能 range based for 、
C#でいうところの foreach ( ほげほげ in ぱよぱよ) でありんす。
幸いなことに VC++11β でも使えます♪
# 残念なことにインテリセンスが赤線引いてくれやがりますけど
オモシロイネー、コレ。
for_each(c.begin(), c.end(), [](int n) { cout << n << endl;});
でももちろんかまわんけども
for ( auto n : c ) { cout << n << endl; }
って書けちゃうんだねー。
lambdaと違ってautoを許すのがナイス♪
コンテナとして許されるのは フツーの配列はもちろん、
array, vector, list ... コンテナはみんなOKだし、
こんなの↓も許す。
map<int,string> c;
for ( auto item : c ) { cout << item.first << ',' << item.second << endl; }
ちょいちょいとあすんでみたところ、begin()/end() を持ってて、
そいつらが ++, *, != できるもんを返せばいいみたいね。
#include <iostream>
using namespace std;
template<typename T>
class iterap {
public:
iterap(T t) : value_(t) {}
iterap(const iterap& other) : value_(other.value_) {}
iterap& operator=(const iterap& other) { value_ = other.value_; }
T operator*() const { return value_; }
iterap& operator++() { ++value_; return *this; }
iterap operator++(int) { return value_++; }
friend bool operator==(const iterap& x, const iterap& y) { return x.value_ == y.value_; }
friend bool operator!=(const iterap& x, const iterap& y) { return !(x == y); }
friend bool operator< (const iterap& x, const iterap& y) { return x.value_ < y.value_; }
friend bool operator>=(const iterap& x, const iterap& y) { return !(x < y); }
friend bool operator> (const iterap& x, const iterap& y) { return y < x; }
friend bool operator<=(const iterap& x, const iterap& y) { return !(y < x); }
private:
T value_;
};
template<typename T>
class iterange {
public:
iterange(T first, T last) : first_(first), last_(last) {}
iterap<T> begin() const { return iterap<T>(first_); }
iterap<T> end() const { return iterap<T>(last_); }
private:
T first_;
T last_;
};
int main() {
for ( auto n : iterange<int>(0,6) ) {
cout << n << ' ';
}
}
2012年3月4日
#
Visual Studio 11 Express Beta ではどうなんだ、と。
残念ながらWin7にインスコ試みたところハネられました。Win8-onlyのようです。
Windows VirtualPC では Win8 が作れんかったので、OracleさんトコのVirtualBox
起こしてWin8 Consumer Preview ねじ込み、VS11 express beta をインスコ。

おお、これはスバラシイ。
ビギナ向け(?)なExpress版でUnitTestが使えることの意義は大きいよ。
2012年2月29日
#
「[]で始まり、lamda外のなにものもcaptureしていない
stateless lambda は function pointer に暗黙変換できる」
とあります。
さっそく試してみんよ。
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
const int N = 10;
int data[N] = { 9, 7, 5, 3, 1, 0, 2, 4, 6, 8 };
// qsortの比較関数にlambdaをねじ込む
qsort(data, N, sizeof(int),
[](const void* x, const void* y)->int
{ return *static_cast<const int*>(x) - *static_cast<const int*>(y);}
);
for ( int i = 0; i < N; ++i ) cout << data[i] << ' ';
cout << endl;
}
あー、おもしろいねコレ。C-functionのコールバックにlambdaを指定できちゃうです。
2012年2月26日
#
おやまぁ、Developer Preview 版 Visual Studio 11 が
C++-native な UnitTest Framework をサポートしてるぢゃあーりませんか。
雰囲気はWinUnitに近く、テスト・プロジェクトをDLLでこしらえ、
そいつを Visual Studio 備え付けの TestRunner で呼び出すよぉな。
まずはテスト・プロジェクトを用意:

しかるのちテストを書く。
#include "stdafx.h"
#include "CppUnitTest.h"
#include <Counter.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace TestCounter {
TEST_CLASS(TestCounter) {
public:
TEST_METHOD(test_initialize) {
Counter c;
Assert::AreEqual(0, c.get());
}
TEST_METHOD(test_incr) {
Counter c;
c.incr();
Assert::AreEqual(1, c.get());
}
};
}んでもってbuildし、UnitTest Explorer から実行すると:

おおぉ、やってくれっぢゃねぇか♪
2012年2月25日
#
ひさびさに一本、CodeZineに
「なぜsetを使っちゃいけないの?」 てゆー。
はてブやらTwiterやらにぼちぼちと反響いただいております、
ありがたやありがたや。
「コ難しくするくらいなら素直にset使っとけばぁ?」ってコメント、
少なくないっすね。うん、僕もそう思う。今どきのCPU/メモリ
ならそんなに遅くならんし少々大喰らいでも大した問題には
ならんですから。
てか、こんなコマケーことに気を「使える」とこが
C++の持ち味なのかなー思うですよ。
2012年2月7日
#
ちょー簡単。
スーパーの鮮魚売場で"たらこ"もしくは"めんたいこ"を入手。袋の割れた「バラ子」で充分。
それとバター。んでもってスパゲティ。いぢょ。
スパゲティ茹でる。その間にボウルにたらこ投入。指でしごいて袋(薄皮)から捻り出す。
バター投入してスタンバイ。茹であがったらボウルに放り込んで混ぜる。
パサつくようならバター(サラダ油も可)追加。できあがり。
うまいよー、「パスタにからめるだけのたらこスパソース」とか売ってるけど、あれよか数段ウマいす。
2012年1月21日
#
ひっさしぶりに boost 触ってみた。
最新版 1.48.0 におもしろそげなコンテナ: flat族を見つけたのね。
標準の std::set(およびその一味)は連想コンテナの実装に二分木を使ってるんだが、
boost::container::flat_set(およびその一味)はベタなvectorを使ってる。
そのため要素の格納の際、左右の枝のためのポインタを要するstd::setより省メモリ。
要素の挿入にはそこそこの時間がかかるけど、
lookup(検索)はバイナリ・サーチが使え、二分木のトラバースよか高速との触れ込み。
試してみんべ:
#include <iostream>
#include <set>
#include <boost/container/flat_set.hpp>
#include <boost/chrono.hpp>
using namespace std;
using namespace boost::container;
using namespace boost::chrono;
int main() {
const int N = 1000000;
std::set<int> s;
flat_set<int> f;
// [0..N) を set/flat_setに挿入
for ( int i = 0; i < N; ++i ) {
s.insert(i);
f.insert(i);
}
system_clock::time_point start;
duration<double> sec;
// [0..N) を set から lookup
start = system_clock::now();
for ( int i = 0; i < N; ++i ) {
s.find(i);
}
sec = system_clock::now() - start;
std::cout << "set " << sec.count() << " seconds\n";
// [0..N) を flat_set から lookup
start = system_clock::now();
for ( int i = 0; i < N; ++i ) {
f.find(i);
}
sec = system_clock::now() - start;
std::cout << "flat_set " << sec.count() << " seconds\n";
}
実行結果:
set 0.069004 seconds
flat_set 0.0480028 seconds
ホンマや。確かに速い。