第3回「ふつうのHaskell読書会」@CSNAGOYA 開催しました。

4月 14th, 2008 admin

4月13日に名古屋の芸術創造センターにて「ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門」の読書会を行いました。前回に続き雨の中、8人の人に集まっていただきました。

内容

今回は4章と、5章を勉強しました。以下印象に残った点のまとめです。

第4章 Haskellの基礎(3) モジュールと総合演習

  • Haskellプログラムはモジュールという単位に分割されている
  • 関数や変数は必ずなんらかのモジュールに所属する
  • mainはMainモジュール、Mainは省略が可能
  • 基本的な型や関数はPlreludeモジュールで定義。自動でインポートされる
  • ある式だけに有効な定義を導入するときはwhereを使う
  • whereで定義された関数は外の関数の引数を参照できる(逆はできない)

第5章 遅延評価

  • 関数の適用を定義で置き換えることを簡約という
  • 簡約には最内簡約と最外簡約がある(Javaとかは最内簡約)
  • 遅延評価を行う言語は少ない(遅延評価 -wikipedia
  • 引数を一度だけ評価する、グラフ簡約という方法が採用されている
  • データ構造も遅延評価だから、無限リストをあつかうときも必要なだけしか評価しない
  • Haskellは参照透明
  • 参照透明を貫くのはむり->そのためにモナドがある
  • 副作用ってのは、式の値以外の結果のこと(出力とか)

遅延評価の利点

  • 不要な計算を減らせる(必要な計算しかしないから)
  • 無限の長さのリストが扱える(自然につかえちゃう!)
  • インターフェイスが統一できる(全部リストであつかえる)

遅延評価の欠点

  • 思った順番で操作を実行するのが難しい
  • デバックしにくい

まとめ

まず、僕は関数型言語というのは遅延評価をするものだと思っていたので、Haskell特有のものだと知って驚きました。また、無限リストを扱えるということがどういうことなのかが今回の勉強でわかりHaskell勉強会の目的をまたひとつ達成できました。

教材について

これは「ふつうのHaskell」の話になりますが、著者である青木さんの説明はちょうど僕レベルの人間にぴったりなようで、読んでいくうちに「あれ?これって高階関数じゃね?」とか「え!もしかしてこれが遅延評価か!」と自分で発見させてくれるような書き方になっていて、読んでいるだけでとてもうれしい気持ちにさせてくれます。もともと日本語でのHaskellの入門書というのはこの本以外には「入門Haskell―はじめて学ぶ関数型言語」というのしかなくて、両方とも良書という評価にはなっているんですが。先に読み始めたのがこっちの本で本当によかったなと思いました。

おまけ

本書に出てきた「たらいまわし関数」というのをみんなでいろんな言語で実装してみました。
投稿があり次第追加していきたいと思います。
対決!たらいまわし関数 -csnagoya

Rubyで数独(ナンプレ)を解く(材料編)

4月 13th, 2008 admin

追記 解決編として正しいソースコードを掲載しました

毎日コードを書くというルールを決めたから酷いコードでもアップします
Rubyの本ももたずに15分ぐらいでやったんだという言い訳をさせてください
リファクタリングのやりがいがあるという意味では良コード

アルゴリズム

ナンプレを解くためのアルゴリズムとして以下のようなものを考えた。
(1)縦方向に調べて、調査中のマスに置ける数字の候補をリストする
(2)横方向にも同様に
(3)1と2の結果候補が1つならその数字を置く
んで、1~3をマスの数*マスの数やればOK

成果物

RUBY:
  1. require 'pp'
  2.  
  3. def search_h(index,x,sheet)
  4.   offset = (index / 9) * 9
  5.   possible = Array.new
  6.  
  7.   search_array = sheet.slice(offset..(offset+8))
  8.   (1..9).each do |i|
  9.     unless search_array.include?(i)
  10.       possible.push(i)
  11.     end
  12.   end
  13.  
  14.   return possible
  15. end
  16.  
  17. def search_v(index,x,sheet)
  18.   offset = index % 9
  19.   possible = Array.new
  20.  
  21.   search_array = Array.new
  22.   (0..8).each do |i|
  23.      search_array.push(sheet[offset + 9 * i])
  24.   end
  25.  
  26.   (1..9).each do |i|
  27.     unless search_array.include?(i)
  28.       possible.push(i)
  29.     end
  30.   end
  31.  
  32.   return possible
  33. end
  34.  
  35. sheet = Array.new
  36. sheet.concat [3,7,0,6,2,0,0,0,1]
  37. sheet.concat [0,0,8,0,5,0,0,6,9]
  38. sheet.concat [4,0,0,0,7,0,0,8,0]
  39. sheet.concat [0,6,0,0,0,4,0,3,8]
  40. sheet.concat [8,0,0,0,3,0,0,0,6]
  41. sheet.concat [5,2,0,0,8,6,0,9,0]
  42. sheet.concat [0,4,0,0,1,0,0,0,3]
  43. sheet.concat [9,3,0,0,6,0,8,0,0]
  44. sheet.concat [6,0,0,0,4,2,0,7,5]
  45.  
  46. width = 9
  47. height= 9
  48.  
  49. 81.times do
  50. index = 0
  51. sheet.each do |x|
  52.   if x == 0
  53.     result = search_h(index,x,sheet) & search_v(index,x,sheet)
  54.  
  55.     if(result.length == 1)
  56.         p index
  57.     pp result
  58.         sheet[index] = result.pop
  59.     end
  60.   end
  61.   index += 1
  62. end
  63. end
  64.  
  65. count = 1
  66. sheet.each do |x|
  67.   print x
  68.   print "\n" unless count % 9> 0
  69.   count += 1
  70. end

まとめ

・・・駄目らしい。このコードでは解けませんでしたw
で、ひさしぶりに頭を使ってコーディングした気がする。学生の頃を思い出して楽しかった。
明日には解けるようにしておきます。

as3でWebカメラ画像の2値化(白黒化)

4月 11th, 2008 admin

白黒の顔写真を取り込みたかっただけなんだけど、思ってたより1ピクセルが大きくてギザギザになった。
これをスムーズにする方法があるんだろうか。
このWebカメラは100万画素ぐらいあるはずなんだけど、取り込み用のそういうのはどこかで設定できるんだろうな。
今日はもう遅いのでまた明日調べよう

成果物

しみやそばかすを自動で消してくれるフォトレタッチソフト(落書きっぽいのは後付です)
flash2.jpg
サンプルはこちら(画面をクリックで白黒画像がとれます)

コード

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.text.TextField;

	public class Main extends flash.display.Sprite
	{
		private var camera_width:int = 200;
		private var camera_height:int = 150;
		private var video:Video = new Video(camera_width, camera_height);
		private var tfView:TextField;

		public function Main():void
		{

			tfView = addTextField(220, 0, 200, 150);
			tfView.appendText("start\n");
			var camera:Camera = Camera.getCamera();
			if (camera == null) {
				//error
				return;
			}
			video.attachCamera(camera);
			addChild(video);
			stage.addEventListener(MouseEvent.CLICK, onClick);
		}

		private function onClick(event:MouseEvent):void {
			tfView.appendText("click!\n");
			var s:BitmapData = new BitmapData(camera_width, camera_height)
			s.draw(video);

			var d:BitmapData = new BitmapData(camera_width, camera_height) 

			var r:Rectangle = new Rectangle(0, 0, camera_width, camera_height);
			d.fillRect(r, 0xFFFFFFFF);

			d.threshold(s, r, new Point(0, 0), "<=", 90, 0xFF000000, 255, false);

			var img:Bitmap = new Bitmap(d);
			addChild(img);
			img.x = 0;
			img.y =  160;
		}

		private function addTextField(x:Number, y:Number, w:Number, h:Number):TextField {
			var textField:TextField;
			textField = new TextField();
            addChild(textField);
            textField.x         = x;
            textField.y         = y;
            textField.width     = w;
            textField.height    = h;
            textField.text      ="";
            textField.selectable=true;
            textField.border    =true;

			return textField;
		}
	}
}

まとめ

BitmapDataにthresholdっていうすべてのピクセルを特定の条件で色を変えるっていうずばりそのもののコードがあったのでできた。そしてずばりそのもののコードが載っているサイトがあったのでできた。Webカメラから取り込んでいるというところだけがオリジナル。Webすごい

参考サイト

Flash Player 9/ActionScript3.0/Flex2の勉強日記

BitmapData - ActionScript 3.0 コンポーネントリファレンスガイド


trick7.com blog: BIT-101 : BitmapData Threshold Explorer

as3でWebカメラ画像の取り込みの練習

4月 8th, 2008 admin

話が逆な気もするけど「Flash+WebCam+Web」って凄い組み合わせだと思う。
今後数年以内に爆発的に流行ると思うので今から取り込みの練習。
ビデオを取得してそれをビットマップにすればいいらしい。

成果物

買ったし安くなかった割に読んでない本を自慢できるswf
flash.jpg
画面をクリックする度にWebカメラの画像が取り込まれて下につながっていく。それだけ。

コード

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.text.TextField;

	public class Main extends flash.display.Sprite
	{
		private var camera_width:int = 200;
		private var camera_height:int = 150;
		private var bitmap_y_offset:int = 160;
		private var video:Video = new Video(camera_width, camera_height);
		private var tfView:TextField;

		public function Main():void
		{

			tfView = addTextField(220, 0, 200, 150);
			tfView.appendText("start\n");
			var camera:Camera = Camera.getCamera();
			if (camera == null) {
				//error
				return;
			}
			video.attachCamera(camera);
			addChild(video);
			stage.addEventListener(MouseEvent.CLICK, onClick);
		}

		private function onClick(event:MouseEvent):void {
			tfView.appendText("click!\n");
			var bd:BitmapData = new BitmapData(camera_width, camera_height)
			bd.draw(video);
			var img:Bitmap = new Bitmap(bd);
			addChild(img);
			img.x = 0;
			img.y =  bitmap_y_offset;
			bitmap_y_offset += bitmap_y_offset;

		}

		private function addTextField(x:Number, y:Number, w:Number, h:Number):TextField {
			var textField:TextField;
			textField = new TextField();
            addChild(textField);
            textField.x         = x;
            textField.y         = y;
            textField.width     = w;
            textField.height    = h;
            textField.text      ="";
            textField.selectable=true;
            textField.border    =true;

			return textField;
		}
	}
}

まとめ

次はサーバにアップロードされるようにしたいと思う。そうすればサイトにアクセスしてWebカメラをポンとクリックしてスマートURLが発行されて友達に送れるっていう、お前なんかいてもいなくても同じなWebサービスの完成です。

疑問

videoのCLICKイベントを拾いたかったけど拾えなかった、どうやってやるんだろうか?

参考サイト

Flash Player 9/ActionScript3.0/Flex2の勉強日記
AS3でDisplayObjectをBitmapDataに変換してみたよ。 - Humming Via Kitchen

30以上のプロジェクトを同時に行う最強のプログラマ

4月 7th, 2008 admin

今日から新学期の学校が多いようですね。
友達に先生をやっている人がいて、今年度は小学一年生の担任をもつそうで面白そうなので話を聞いたのですが面白すぎて驚きました。

小学一年生は・・・

  • 自分がなぜ学校にきているのかよくわかっていない
  • 教室は入るものということを知らない
  • 「自分の机」というものの意味がわからない
  • カバンは学校にきたら開けるということを知らない
  • トイレを自分でみつけるなんてもってのほかだし、使い方を知っているとは限らない

その友達は明日はまず「教室に入る」ということから教えると言っていました。

id:dankogaiさんが
注目している言語は日本語
って言ってましたけど、彼らは注目どころかまだ学び始めて5~6年ぐらいだし・・

日本語も通じないかもしれない相手にどうやって「まず学校ってのは勉強するところで、あなたたちは勉強するために学校に来てるんだから、、、んで、この学校では主に学習は教室内で行うからまずは教室に入ってくれ、そうしてくれるとすごく助かる」みたいなことをわからせるんだろうか、その辺はわからせなくてもいいんだけど、どの変で妥協すればいいんだろうか?僕にはわからない。

僕が仕事や趣味でプログラムするのは、各種演算や、プロトコルなどをがっつり勉強している記憶率100%のソフトウェアで、これは凄く簡単。なぜなら僕が書いたとおりに動くから。でも彼(女)らがプログラムするのは、なにを勉強してきたかよくわからない不安定で記憶力も個体差が激しくすぐに泣き出してフリーズするベタベタのウェットウェア、一度教えても覚えたとは限らない。しかも1年がんばってプログラムしたところで次の年から自分の仕事を楽にしてくれるわけでもないし。

しかもしかもそんなのを毎日朝から夕方まで30機以上を同時に相手って・・・すごいね先生!