在宅勤務始めました

昨年あたりから会社が在宅勤務制度を開始した。素晴らしい制度である。私も条件に合うので本年度より開始するよう申請しました。人事部の担当者との面談を済まし、無事承認がおりました。人事部の話では積極的に勧めていきたいようで、面談も厳しい質問等は一切なく、制度の内容や注意点を確認する程度でした。
私は共働きな上、夫婦そろって通勤距離が長い。おかげで結構家事等の家庭事情が圧迫されていた。子供の習い事も基本土日にしか入れられず、娘が文句を言っていた。在宅勤務が実現できればこのあたりが改善される。なにより往復3時間という無駄に長い時間が浮き、土日に回していた家事(主に掃除)も勤務前に済ましてもなお通常より早く業務を開始できます。まだ2日しか実施していないがこれから毎週取る予定なので妻と話し合って有効な使い方を考えていきます。

私の場合、ソフトウエア開発なので在宅勤務でも基本的に問題がありません。会社支給のノートPCから社内ネットワークにVPNで接続。メール等の社内システムを利用する分には全く問題ない。また、本業の開発に関しても開発用マシンにリモートアクセスすることにより実施。会社で開発しているのと基本かわりない。ただVPN経由でリモートアクセスなのでレスポンスがやや良くないです。最初は少しイライラしましたが慣れればなんてことはありません。他の社員とのコミュニケーションは基本電話です。これは少し不便なこともありますが、毎日在宅勤務というわけではないので別の日に出勤したときにコミュニケーションをとればよい。

在宅勤務の懸念点としてはやはり効率が落ちてしまわないかということがあります。自宅だからサボってしまわないか?他の社員とのコミュニケーションが取りづらくなるのではないか?等々。私の場合、前者は特に問題はないが後者は電話しかないのでこの先、少し不便になる可能性があるかもしれませんが、次の日に通常出勤した際に直接会えばよいわけですからせいぜい1日ロス程度で済みます、その間は別の仕事をすればよいだけです。

もっと全国的に広まっていくべきだと思います。もちろん業種によっては在宅勤務が無理な場合もあるが、そうでなければ本人が希望すればどの会社でも取れるようになればいいなと思います。

年度が変わったので不定期更新

特に面白いトピックがあるわけではないのですがいつまでたっても更新しなさそうなので一応更新。
年度が明けて仕事は特にかわりなく。ガチな開発仕事がなくイマイチつまらないです。
3月末は私が永年勤続ということで特別休暇がもらえた&嫁が遅い夏休み(?)をとれたので家族旅行に行ってまいりました。
明日は娘の入学式です。気が付いたら小学生です。光陰矢のごとし。

今年度の目標はもう少し仕事に集中することです。サボりすぎorg

面白いゲーム(?)見つけた

https://geoguessr.com/
開始すると世界の適当なところに放置されます。グーグルストリートビューなので移動することができます。色々動いて周りをみて最初の位置を推測します。推測した地点が近ければ近いほど点数が高くなります。
私の場合はあらゆる情報を駆使してピンポイントにその場所を当てて遊んでいます。えらい時間がかかりますが今のところかなり高い確率でピンポイントにあてています。たまに店の中だったりして極端に動けるところが少ない場合はどうしようもないですがそれ以外はほぼ確実に当てています。ただ、アメリカとかは数十マイルも直線が続いていたりしてそのど真ん中に放置されたらかなり大変ですが・・・。あと、マップが古くて道路案内が見えなかったりした場合も割と絶望的ですね。苦労して見つかったと思ったらキリル語だったことも何度もあり。今のところ、タイ語が一番苦労しました。

面白くてはまってしまいますが無尽蔵に時間を取られてしまうので何とか制御しなければ・・・。

数独solverの最小コードに挑戦

数独solverは昔作ったことがあるのでsolver作成という点では再挑戦ということになる。しかし今回少し趣を変えてコード量を減らすことに重点を置いた。なので速度と可読性はとりあえず度外視した。とはいえ、有用な時間に解けなければ意味がないのである程度速度も考慮に入れる。あとあんまり暗号化が酷いのも何なのである程度可読性も考慮しました。まあ中途半端です。
そして出来上がったコードが以下の通り。

bool Sudoku3x3(int* t, int i = 0){
	const static int b_[] = { 0, 1, 2, 9, 10, 11, 18, 19, 20 };
	for (; i < 81; ++i) {
		if (t[i] == 0) {
			bool c[10] = {};
			int h((i / 9) * 9), v(i % 9), b((i % 9 / 3) * 3 + (i / 27) * 27);
			for (int j = 0; j < 9; ++j, ++h, v += 9) {
				c[t[v]] = c[t[h]] = c[t[b + b_[j]]] = true;
			}
			for (int n = 1; n <= 9; ++n) {
				if (!c[n]) {
					t[i] = n;
					if (Sudoku3x3(t, i + 1)) return true;
				}
			}
			t[i] = 0;
			return false;
		}
	}
	return true;
}

実際に動かす場合は以下の通り

int table[] = {
	8,0,0, 0,0,0, 0,0,0,
	0,0,3, 6,0,0, 0,0,0,
	0,7,0, 0,9,0, 2,0,0,

	0,5,0, 0,0,7, 0,0,0,
	0,0,0, 0,4,5, 7,0,0,
	0,0,0, 1,0,0, 0,3,0,

	0,0,1, 0,0,0, 0,6,8,
	0,0,8, 5,0,0, 0,1,0,
	0,9,0, 0,0,0, 4,0,0,
};

Sudoku3x3(table);//上書きされる

20行程で完成。まあ改行はいくらでも減らせるので行数での比較は意味ないですけど。
本当に総当たりなので結構重いと思いきや、意外と速かった、ていうか以前作った物より速いんだけど・・・。ただし、試しに4x4や5x5を作ったらやっぱり重かった。しかし3x3なら十分実用的(?)な速度だと思います。

ついでに練習のためにswift3.0でも書いてみました。少し可読性を上げています。

func Sudoku3x3(table t:inout [[Int]], _ index:Int = 0)->Bool{
	//サイズ取り出し。9x9のはず
	let sy = t.count
	let sx = t[0].count
	//総当たり
	for i in index..<sy * sx{
		//現在の座標
		let y = i / sx
		let x = i % sx
		//0以外は既に埋まっているので飛ばす
		if t[y][x] == 0 {
			//縦と横とブロック内で存在する数値を調べる
			var c = [Bool](repeating: true, count:10)
			let bx = x / 3 * 3//ブロックの左上
			let by = y / 3 * 3
			for j in 0..<9{
				c[t[y][j]] = false//横チェック
				c[t[j][x]] = false//縦チェック
				c[t[by+j/3][bx+j%3]] = false//ブロック内チェック
			}
			//存在しなかった数値を順番に入れてみる。
			for (n, test) in c.enumerated(){
				if test {
					t[y][x] = n
					//次に進む
					if Sudoku3x3( table:&t, i+1 ){
						//最後まで埋まった
						return true
					}
				}
			}
			//どの数値もダメだった。前に戻る。
			t[y][x] = 0
			return false
		}
	}
	//最後まで埋まったので成功
	return true
}

なにげに初めてのswiftプログラミングです(^^;たったこれだけだけどえらい苦労しました。でもおかげさまでswift開発力が格段に上がりました。
ところでシンタックスハイライト、swiftはないんだな・・・。

ペンシルパズルsolver開発はプログラミングのよいトレーニングになり

最近はまってました。楽しかった。もう飽きたけどorz
作ったのは数独、お絵かきロジック、スリザーリング、カックロです。ソースの公開予定はないです(^^;
この手のパズルは基本的に総当たりで試してあっている入力を返します。ただし本当に総当たりだととんでもない組み合わせになるので動的計画法や枝刈りで総数を減らします。この総数をどうやって減らすかが高速化のカギになっていると思います。ちなみに後から知ったのですがこの方法、「バックトラッキング」という名前が付いていました。そーなのかー。

実際、これらのプログラムは既にいっぱい作られているのでほしければ持ってくれば良いだけですが実際に自力で作ることはアルゴリズムプログラミングのいいトレーニングになると思います。また如何に効率化を考えればより一層、論理的思考のトレーニングになります。もちろん、その言語そのものの実装力のトレーニングにもなります。今回でも少し技術力UPした・・・と思いたいです(^^;

11月も12月も2016年も終了し、1月も終了しそうです

忙しすぎて書けませんでした。まあいつものことですが。
最近にしては珍しく、開発で忙しかったのでそこそこネタはたまっています。ですがまとめる時間がありません。もう少し余裕が出始めたらちょくちょくネタだしします。

最近の変化としてはswiftの勉強を始めました。そのうちiPhoneアプリを作ろうと考えております。Mac Book Proを購入しようか考えていたところ、不具合のニュースを見て早速頓挫しましたが。

Macがなくてもswiftの勉強はできます。IBMがなかなかいいものを用意してくれました。
https://swiftlang.ng.bluemix.net
ここで適当なプログラムを書いて練習しております。
一通り文法が使えるようになったら本格的に始めようと思います。
しかし、肝心の作るアプリのアイデアがない・・・。まあとりあえず既存アプリでもなんでもよいから粗製乱造して経験を溜めるところからスタートですね。

今年中にそこそこ実用的なアプリがUPできるといいなー。

浮動小数比較の落とし穴

業務でリファクタリングを実施していた。演算結果が変わらないように毎回比較して違っていればエラーを吐くようにして、改良を進めていた。

if( std::abs( result - test ) > std::numeric_limits< double >::epsilon() ){
	std::cout << "error : " << result << " , " << test << std::endl;
}

浮動小数点は演算が一致する保証がないので、その差が非常に小さい値であるかどうかで評価する、まあ数値計算での基本ですね。
何の変哲もない上記のコード、実は大きな落とし穴があった。私はこれにはまってかなりの工数を無駄にしてしまった。

double型には普通の数値以外にいくつか特別な表現がある。例えば0割をした場合に∞になったりする。その特別表現の一つにNaNがある。NaNとは、Not a Numberという意味で、つまりは「数値ではない」という意味です。数学的には0/0等の不定形の演算を施すと出てくるおうです。
今回、改良中に何を間違ったのか結果がNaNを返すようになっていた。NaNの演算規則はよくわからないが、とりあえず数値比較演算は相手が何であれすべてfalseを返すっぽいです。なので上記のコードはresultとtestが異なるにも関わらずifをすり抜けてしまいます。エラーが出ないから演算結果が一致していると思って進めていて結果、全部やり直しになってしまいました。orz
とうわけで、上記コードをNaNにも対応できるように少し修正してみました。

if( !( std::abs( result - test ) <= std::numeric_limits< double >::epsilon() ) ){
	std::cout << "error : " << result << " , " << test << std::endl;
}

数学的には全く同じですが、NaNの場合は不等号が必ずfalseになるので、不等号の向きを逆にすることによりNaNの場合もifに入ることになります。

次回から気をつけます。