Home > 2009年03月

2009年03月

ブログの文字色を濃くしました

最近目が悪くなってきたのか、自分でも見づらかったので…。

デザインをできるだけ壊さないよう、色合いはそのままで暗くした。
(16進数の各桁を2ずつ減らすという微妙な作業によって)

color: #8c8c8c; /* default */

color: #6a6a6a; /* dark */

こんな感じ。

若干ダサくなったけど、まぁしかたないでしょう。
※ テンプレート作者さん、すいません。。。

初めてのPerl:ディレクトリ内のhtmlファイルに含まれる英単語数を数える(ついでにgoogleのapiで翻訳)

  • 2009-03-07 (Sat)
  • Perl

(ようやく)Perl始めました。

ちょっと前から入門書とかは読んだりしてたんだけど、
発売前から楽しみにしてた、

photo
モダンPerl入門 (CodeZine BOOKS)
牧 大輔
翔泳社 2009-02-10

by G-Tools , 2009/03/07

が、あまりにもわからなくて凹んだので。
やっぱプログラミングはコーディングして覚えないとね。

ちょうど記事タイトルのようなことがやりたかったこともあり、Perlで頑張ってみました。

というわけで、以下がPerl入門~サンプルコードによるPerl入門~(便利すぎ!!)を参考に作ったソースです。

ディレクトリ内htmlの英単語をカウント

ちなみに環境は、VMWare Playerでお手軽にVista上でLinux(Ubuntu) - Born Neetで入れたUbuntu。
perlやるならやっぱUnix系かな、と。(perlもcpanも元から入ってて楽だったし)

#!/usr/bin/perl

use strict;
use warnings;

my @files = glob '*.html';
my %count;

foreach my $file ( @files ) {
	open( my $fh, '<', $file ) or die "Can't open $file: $!";

	my $content;
	{
		local $/ = undef;
		$content = readline $fh;
	}

	$content =~ s/<head>.*<\/head>|<[^>]+?>//gs;

	my @words = split( /\W+/, $content );
	foreach my $word ( @words ) {
		if( $word ) {
			$count{ lc $word }++;
		}
	}
}

my @sorted = sort { $count{ $b } <=> $count { $a } } keys %count;

foreach my $key ( @sorted ) {
	print $key ."\t" . $count{ $key }, "\n";
}

Google Language APIで翻訳

CPAN・モジュールのお勉強を兼ねて、Google AJAX Language APIで翻訳してみる。
参考→Google AJAX Language API で翻訳する/楽

#!/usr/bin/perl

use strict;
use warnings;

use WebService::Simple;

my $api = WebService::Simple->new(
	base_url => "http://ajax.googleapis.com/ajax/services/language/translate",
    	response_parser => "JSON",
    	params => { 
		v => '1.0',
		langpair => 'en|ja',
	},
);

sub translate {
	my $response = $api->get({
		q => shift,
	});
	return $response->parse_response->{ responseData }->{ translatedText };
}

print translate('test'); # 試験

これを1つ目のコードとマージして、

foreach my $key ( @sorted ) {
	print $key ."\t" . translate($key) . "\t" . $count{ $key }, "\n";
	sleep 1; 
}

みたいにすれば英単語を数えつつ、翻訳も出来る。
(googleに怒られないように一応1秒待つようにした)

結果と微調整

結果がこちら↓

$ head -20 analyze.txt
the	その	7280
quot	quot	4476
a	1つの	4280
to	?へ	4120
is	なる	3192
of	の	3088
and	および	2367
it	それ	2073
that	あの	1902
this	この	1804
in	インディアナ	1627
function	関数	1604
be	存在する	1322
can	?できる	1165
are	なる	1158
for	?のために	1093
you	あなた	1044
not	?でない	901
The	その	897

…とここで、大文字/小文字を区別しちゃってることに気づく。
(例:theとThe)

そう何度もgoogleにリクエストを送りたくないということで、
以下のような急造スクリプトで対応。
(全部小文字にして単語数を合計)

#!/usr/bin/perl

use strict;
use warnings;

open( my $fn, '<', 'analyze.txt' ) or die '$!';

my %lower;
my %ja;

while ( my $line = readline $fn ) {
        my ( $en, $ja, $c ) = split( "\t", $line );
        $lower{ lc $en } += $c;
        $ja{ lc $en } = $ja; 
}

foreach my $word ( sort { $lower{ $b } <=> $lower{$a} } keys %lower ) {
        print $word . "\t" . $ja{$word} . "\t" . $lower{$word} . "\n";
}

微調整した結果がこちら↓
ちゃんとtheとTheが合計されてる。

スクリプトには無駄が多そうだけど、初めだし、期待通り動いてるのでまぁよしとする。

$ head analyze2.txt
the	その	8177
a	1つの	4499
quot	quot	4476
to	?へ	4240
is	なる	3198
of	の	3106
and	および	2439
it	それ	2403
this	この	2249
that	あの	1944

つまづいたとこ

perlcodesampleがかなり充実してたので、コーディング自体は特に困らなかった。

一番時間かかったのはCPANのモジュールを使うところ。
以下その時のメモ。

まずは、

$ cpan

で設定。
全部Enter連打で。
Enterで駄目なところは地域・国・サーバの指定ぐらいなので、そこは適当に番号で選ぶ。

設定が終わると、プロンプトが

cpan>

になるので

cpan> install WebService::Simple

等、インストールしたいモジュール名を入れる。
あとは依存してるモジュールとかも勝手に入れてくれるので、(またもや)Enter連打で答えていく。

インストールが終了したら、

cpan> q

で終了。
とここまでは特に問題はなかった。

が、モジュールを使用したファイルを実行すると、

Can't locate WebService/Simple.pm in @INC

と怒られた。

(いろいろ苦労しつつ)結局、

$ perl -I/home/ユーザ名/.cpan/build/WebService-Simple-0.15/lib ファイル名.pl

でいけたけど…
なんか面倒くさい、本当にあってるのか?

2009/03/08 15:40 追記

やっぱ間違ってました。

perlcodesampleさんからコメントもらった(ありがとうございます!)ので改めてやり直してみると、
テストで、

#   Failed test 'param is uri escaped'
#   at t/01_escape.t line 16.
#          got: '?param=%E7%8C%AB'
#     expected: '?param='
# Looks like you failed 1 test of 2.

なんてエラーが出てた。

ダメもとで、'param is uri escaped'で検索したら、
URI::Escapeってモジュールがあったので、これだ!と思ってinstall。

sudo cpan
cpan> install URI::Escape
cpan> install WebService::Simple

無事、

perl ファイル名.pl

だけでいけるようになりました。

モジュール自体に必要なものは自動でインストールされるけど、
テストで使ってるやつはそうじゃないってことなのかな?

やっぱわからないことだらけだなー。
頑張ろーっと。

2009/03/08 16:00 追記2

インストールされた場所を確認しようとしたら、

perldoc -l WebService::Simple
You need to install the perl-doc package to use this program.

なんてエラーが出るので、

sudo aptitude install perl-doc

とかやる必要有り。

perldoc -l WebService::Simple
/usr/local/share/perl/5.8.8/WebService/Simple.pm

Ubuntu(debian)特有っぽい。よくわかんないけど。

ActionScript再挑戦!Flexで人工無脳作ってみた

2009/06/20 20:10
 誤字脱字修正。

2009/03/06 22:45
 htmlのソースとプロジェクトファイル一式を追加しました。

たぶん、今までで一番長文です。

1年以上前に書いた、
 ・ Hello, Flash!:ActionScriptを初めて使ってみたらお絵かきが簡単にできてびっくりした - Born Neet
は今だに僕のブログで一番の人気記事です。
HolyGrailさんのおかげでしょうが…)

にもかかわらず、それから一年以上ASの話題を扱わないという体たらく。
(地味に勉強してたりはしたんですが、記事にするまでにはいたりませんでした。)

というわけで改めて学びなおすべく、新しい言語の学習にはもってこい(?)の人工無脳を作ってみました。

以下に手順をメモしますので興味があればどうぞ。
ソースのライセンスも(使用ライブラリに合わせて)修正BSDにしとくのでご自由に。

前やった時は、FlexのFの字もわかってなかったのでたいした説明はできませんでしたが、
今回は本読んだり、(だいぶ前ですが)セミナーに行ったりもしてたのでいくらかはマシだと思います。

Flexとは

Flexは、Flashの技術を利用したリッチインターネットアプリケーション(RIA)です。
Flexならデザインセンスのカケラもない僕でも、プログラミングするだけでFlash Player上で動くアプリケーションを作ることができるのです。

と、僕は理解してます。

まぁ細かい定義なんかはどうでもよくて、FlashPlayerがあればどこでも同じように動く、
つまり、「Firefoxで開発→IEで確認→動かない→直す→Firefoxで変に」みたいなことをしなくて済むのです。

ということで僕は勝手にFlexはRIAの本命なんじゃないかと思ってます。

準備

まずは環境を整えます。
やったのは半年以上前なので抜けてるかもしれません。

開発には、FlashDevelopを使います。
補完がないときついので。(テキストエディタでJavaを開発するぐらいのしんどさです)

というわけで、以下のサイトあたりを参考にFlex SDKとFlashDevelopを(ないならJavaも)インストール。
(自分が参考にしたサイトは忘れちゃったので適当に検索しました。)

 ・ Adobe Flex SDK超入門 (treasuring misc.)
 ・ フリーのFlash統合開発環境 FlashDevelop (+flex 3 SDK)を入れてみました:■ 音楽方丈記 ■

他にも情報は山ほどあるのでここは省略。

Flexプログラミング入門

Flashはどうやって作ってるのかさっぱりわかりませんが、
FlexはWebプログラマにとって非常にわかりやすい構造です。
(カッコ内参照)

作成するファイルは以下の3つ。

 ・ mxml(htmlの役目)
 ・ ActionScript(JavaScriptの役目)
 ・ CSS(そのまま)

HTMLベースのアプリと同様に、
mxmlで構造、ASでイベント等を設定、CSSで装飾します。

さらにASとJSは型とclassがあること意外ほとんど同じなので、
mxmlだけ覚えればもう何でも作れちゃうのです!
(実際は以前の僕の記事のようにmxmlなしでも作れますが…)

FlashDevelopのプロジェクトの作り方

さて、そろそろ飽きてきましたが。。。

FlashDevelopは高機能なので初めて使う時若干とまどいます。
特に新規プロジェクト作成の選択肢が多すぎる!

ってことで僕の作成手順を書いときます。

 1. AS3のEmptyProject(なんか2個あるけど上の方)を選択
   ・ Nameは適当(一応ラクダ文字が規則みたい)
   ・ packageは空で
   これで余計なものが何もない空のプロジェクトが作られます。

 2. Projectの箱を右クリックしてmxmlを追加
   さらに
   ・ 追加したmxmlを右クリックしてAlwaysCompileにチェック
   ・ プロジェクトのプロパティ(右クリック or メニューから)で
    「No output~」のチェックを外し、ファイル名を適当に入力

FlashDevelopがちゃんとインストールされていれば、
これでコンパイルでき、Flashでおなじみのswfファイルが作成されるはずです。
(参考サイトにもありますが、External Playerの設定大事)

あとはASなりCSSなりサブのmxmlなりをガシガシ追加していくだけです。

SWFObject

もう駄目だ…長文すぎる…。
というわけで、ソース以外はこれで最後です。

Flashを公開する時はHTMLに埋め込むことになります。
しかしこれが、objectタグやらembedタグやら実にややこしい。

そこで、swfobjectです。
このライブラリを使えばid指定とjs1行で済みます。

詳しくは、

 ・ 八角研究所 : FlashをHTMLに貼るライブラリ swfobject 2 を使う
 ・ SWFObject v2.0 ドキュメント日本語訳 : Media Technology Labs (MTL) : メディアテクノロジーラボ ブログ
 ・ nondelion.com - 続・swfobject で flash を Window 内に全画面表示

等をどうぞ。

Flexな人工無脳

ようやく本題です。
もう説明する気力は残ってないのでコメントを参照してください。

僕の試行錯誤の結果です…。

動くサンプルはここに置いときます→Flexで人工無能 - tnantoka.net
(はじめは空っぽですが、会話を覚えていきます。
またstudyタブからテキストをaddすれば賢くなるかもしれません。)

プロジェクトファイル一式も置いとくのでどうぞ。

Main.mxml

画面構造

<?xml version="1.0" encoding="utf-8"?>
<!-- 
	Applicationにwidth,heightを設定すれば、-config.xmlをいじらなくても大きさ指定できる 
	creationCompleteはwindow.onload的存在(as内からは設定できないので属性で)
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
	
	<!-- as,css外部ファイル化 -->
	<mx:Script source="init.as"/>
	<mx:Style source="style.css"/>
	
	<!-- 大枠 -->
	<mx:Panel width="100%" height="100%" title="Flexで人工無脳" horizontalAlign="center">
		
		<!-- 
			タブ切り替え
			creationPolicy="all"にしないと初期化時にイベント設定できない 
		-->
		<mx:ViewStack id="viewStack" width="100%" height="100%" creationPolicy="all">
			
			<!-- 会話画面 -->
			<mx:VBox label="talk" horizontalAlign="center">
				<mx:HBox width="70%">
					<mx:TextInput width="90%" id="msgInput" />
					<mx:Button label="send" id="sendButton" />
				</mx:HBox>
				<mx:TextArea width="70%" height="85%" id="historyArea"></mx:TextArea>
			</mx:VBox>
			
			<!-- 学習画面 -->
			<mx:VBox label="study" horizontalAlign="center" styleName="study">
				<mx:TextArea width="70%" height="87%" id="sourceArea"></mx:TextArea>
				<mx:HBox width="70%">
					<mx:Button label="init" id="initButton" />
					<mx:Spacer width="100%"/>
					<mx:Button label="add" id="addButton" />
				</mx:HBox>
			</mx:VBox>
			
		</mx:ViewStack>
		
		<!-- タブメニュー(各要素のlabelがタブに) -->
		<mx:LinkBar dataProvider="{viewStack}"/>
		
	</mx:Panel>
	
</mx:Application>

init.as

イベントを設定したり、Munouクラスを使ったり。

import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import mx.events.FlexEvent;
import mx.rpc.http.HTTPService;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;

// グローバル使わないために関数内で処理
private function init():void {
	
	var munou:Munou;
	
	// テキストを読み込んで学習
	// XMLHttpRequest同様に使える
	var http:HTTPService = new HTTPService();
	http.url = 'test.txt';
	http.resultFormat = 'text'; // デフォルトはXML

	// 成功
	http.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void {
//		munou = new Munou(event.result as String);
		munou = new Munou(''); // 今回は白紙で
	});

	// 失敗
	http.addEventListener(FaultEvent.FAULT, function(event:FaultEvent):void {
		Alert.show(event.fault.faultString);
	});

	http.send();
	
	// sendクリックで話しかける
	sendButton.addEventListener(MouseEvent.CLICK, send);
	// エンター押下にも同じイベント設定
	msgInput.addEventListener(FlexEvent.ENTER, send);
	
	// 初期化
	initButton.addEventListener(MouseEvent.CLICK, function(event:Event):void {
		// 
		munou.init(sourceArea.text);
		sourceArea.text = '';
	});
	
	// 覚えさせる
	addButton.addEventListener(MouseEvent.CLICK, function(event:Event):void {
		if (sourceArea.text) {
			munou.learn(sourceArea.text);
			sourceArea.text = '';
		}
	});
	
	// 話しかける
	function send(event:Event):void {

		var msg:String = msgInput.text;
		
		// ちょっとだけhtmlが使える
		historyArea.htmlText += '<p>あなたの発言:<br/>\t' + msg + '</p>';
		historyArea.htmlText += '<p><font color="#0000ff">munouの発言:<br/>\t' + munou.response(msg) + '</font></p>';
		msgInput.text = '';
		
		// スクロールバーを最終行に設定
		// (遅延実行?しないと更新前の位置になる)
		callLater(function():void {
			historyArea.verticalScrollPosition = historyArea.maxVerticalScrollPosition; 
		});

	}

	// かぎカッコ内のテキストを抽出(不使用)
	function getTalk(text:String):String {

		var talk:Array = text.match(/「[^」]+?」/g);
	
		for(var i:int = 0; i < talk.length; i++) {
			talk[i] = talk[i].replace(/[「\s 」]+/g, '');
		}
		
		return talk.join('\n');
	}
	
} // init

Munou.as

人工無脳(簡易形態素解析+マルコフ連鎖)で会話するclassです。

/**
 * 人工無脳(簡易形態素解析+マルコフ連鎖)で会話するClass
 */
package {

//	import org.coderepos.text.TinySegmenter; // CodeRepos
	import uwi.tinysegmenter.TinySegmenter; // SparkProject
	
	// mxml名と被るとダメ
	public class Munou {

		// 文頭・文末識別子
		private const START:String = '__START__';
		private const END:String = '__END__';
		
		// 初期化テキストを一応保存
		private var text:String;

		// 形態素解析マシン
		private var segmenter:TinySegmenter;
		
		// 学習した結果
		private var dic:Object;
		
		// コンストラクタ
		public function Munou(text:String) {
			this.text = text;			
			segmenter = new TinySegmenter();
			init(text);
		}

		// 初期化
		public function init(text:String):void {
			dic = {};
			learn(text);
		}
		
		// 学習
		public function learn(text:String):void {

			if (text) {
			
				// スペース・タブは1字に圧縮
				// 改行で区切る(スペース・タブは残したいので\sは使わず)
				// そのほかの記号は無視
				var a:Array = 
					text.replace(/([  \t])+/g, '$1')
						.split(/[\r\n]+/);
				
				// Vistaならtraceログは以下に
				// C:\Users\<user>\AppData\Roaming\Macromedia\Flash Player\Logs
				// trace(a.join(','));
				
				for (var i:int = 0; i < a.length; i++) {

					var b:Array = morph(a[i]);
					trace(b.join('|'));
					
					b.unshift(START);
					b.push(END);
					
					for (var j:int = 0; j < b.length - 1; j++) {

						var s:String = b[j];
						if (dic[s]) dic[s].push(b[j + 1])
						else dic[s] = [b[j + 1]];
						
					}	
				}
			}
		}

		// 形態素解析
		private function morph(text:String):Array {
			return segmenter.segment(text);	
		}
		
		// マルコフ連鎖で文章作成
		private function markov(text:String):String {
		
			if (!dic[START]) return '';
			
			var s:String = dic[START][Math.floor(Math.random() * dic[START].length)];
			var r:String = '';
			
			while (s != END) {
				r += s;
				
				// 文末っぽい記号が出ても終了
				if (s.match(/[。!!??]/)) break;
				s = dic[s][Math.floor(Math.random() * dic[s].length)];
			}
			
			return r;
		}
		
		// 応答
		public function response(msg:String):String {
			
			var func:Function;

			learn(msg);

// 今回はマルコフのみで
//			switch(Math.floor(Math.random() * 10)) {
			
				// 1/10の確立でオウム返し
//				case 0:
//					func = echo;
//					break;
				// 1/10の確立で定型応答
//				case 1:
//					func = random;
//					break;
				// その他はマルコフで
//				default:
					func = markov;	
//			}
			
			return func(msg);
		}
		
		// オウム返し(不使用)
		private function echo(msg:String):String {
			return msg;
		}

		// ランダム応答(不使用)
		private function random(msg:String):String {
			
			var a:Array = [
				'',
			];

			return a[Math.floor(Math.random() * a.length)];
		}

		// 初期化テキスト表示(不使用)
		public function getText():String {
			return text;
		}
		
	} // class
	
} // package

style.css

見た目を調整。
htmlほど自由には設定できません。

@charset "UTF-8";

Application {
	background-color: #fff;
/*	width: 300px; 効かない */
}

Panel {
/*	width: 100%; %指定はエラー */
/*	padding: 10px; 効かない */
	padding-top: 20px;
	padding-bottom: 20px;
}

HBox {
/*	text-align: center; TextInputの中身がセンタリングされちゃう */
	padding-top: 10px;
	padding-bottom: 10px;
}

.study {
	padding-top: 10px;
}

index.html

swfを全画面表示

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Flexで人工無脳 - tnantoka.net</title>
	<meta http-equiv="Content-Style-Type" content="text/css" />
	<meta http-equiv="Content-Script-Type" content="text/javascript" />
	<link rel="stylesheet" type="text/css" href="style.css" media="all" />
	<script type="text/javascript" src="swfobject.js"></script>
	<script type="text/javascript">
swfobject.embedSWF('Munou.swf', 'swfArea', '100%', '100%', '9.0.0');
	</script>
	<style type="text/css">
/* for Firefox */
html, body {
	height: 100%;
}
html {
	overflow: hidden;
}
/* common */
body {
	margin: 0;
}	
	
	</style>
</head>
<body>
<div id="swfArea" style="width: 100%; height: 100%;">
</div>
</body>
</html>

読んだ本

photo
Flex3プログラミング入門
宮田 亮
秀和システム 2008-08
おすすめ平均 star
star思わず続編を探してしまいました。
starこれからFlexを触る方へ

by G-Tools , 2009/03/04

だいぶ前に読んだ時はイマイチと思ったんだけど、
AIRプログラミング入門と内容を使い回しすぎだし)
今回作るにあたってリファレンスとして結構役に立った。
初Flexのお供に是非。

photo
ActionScript3.0のドリル (Workbook in Programming)
佐藤 信正
ソシム 2009-02

by G-Tools , 2009/03/04

ホントはFlex3.0SDKで学ぶActionScript3.0入門が欲しかったんだけど、
どこにもないので(発売後1年足らずなのに…)しかたなく、同じくFlex SDK(Builderではなく)で作るこの本を購入。
(安さにつられたわけじゃ…)

プログラミング初心者用の本のため、他言語の経験者にはあまり向かない。
僕はE4Xを触ったことがなかったので多少はためになりました。
(本は対象読者を見てから買いましょう、ですね!)

あと、ところどころに、ん?と思う説明が。。。

関数名だけで利用される関数をクロージャともいいます(p.168)

…いいません!(笑)

とかね。

その他参考

 ・ TextArea自動スクロール
   FirefoxのTextAreaと同じくtextを追加するとスクロールバーが先頭に戻っちゃう対策。

 ・ [Air/Flex]ViewStackの落とし穴 - 秘密結社ぎゅう☆ぎゅう倶楽部
   スムーズな画面遷移と引き換えにイベント設定ができなくなるとか…。

 ・ たまご日記(別館) [flex] テキストの改行が余分に付く
   改行の扱いにわりと苦労させられました。

 ・ /air/TLife/src/uwi/tinysegmenter/TinySegmenter.as - Spark project
 ・ /lang/actionscript/as3tinysegmenter/src/org/coderepos/text/TinySegmenter.as -- CodeRepos::Share -- Trac
   TinySegmenterのAS移植版。
   僕はなんとなくSparkProjectの方を使ってます。

GoogleのTwitter初発言をJavaScriptで読めるように

遅い(※)。しかもしょうもない。
が、自分が読むために作っちゃったので公開しとく。
※ googleがじゃなく僕がブログのネタにするのが…ね、一応。

2進表記を文字に直すのは、

String.fromCharCode(parseInt('01100110', 2)); // f

でOK。

というわけで、Googleの発言を読めるようにしましょう。




できました。

答えは…
最近何かと話題のGoogle日本のトップ画面からいつのまにか消え去ったあの機能です。

あぁあのシンプルな画面がなつかしい。

一応ソース

<textarea id="decodeGoogle" cols="30" rows="3"></textarea><br />
<input type="button" value="変換" onclick="(function(){ 
var chars = document.getElementById('decodeGoogle').value.split(/\s/);
for(var i = 0; i < chars.length; i++) {
	if (!isNaN(chars[i])) chars[i] = String.fromCharCode(parseInt(chars[i], 2));
	else chars[i] = chars[i] + ' ';
}
document.getElementById('decodeGoogle').value = chars.join('');
 })()" />

以上です。

Home > 2009年03月

Page Top