Hatena::ブログ(Diary)

亀岡的プログラマ(?)日和。

にほんブログ村 IT技術ブログへ
にほんブログ村

2012-02-23

英文要約の心得をちょっと勉強してきた。途半っていうかまだまだ歩き始めです。

| 22:15

今日は英会話教室で英文要約の問題をいくつかやって来ました。表現の幅が増えてなかなかに面白かったので簡単にまとめ。

(一応断っておきますが、これは某英会話スクールでの内容を個人の整理のためにアウトプットしているものなので、文法上の正確さの保証はしかねます。あくまで、参考に、肩肘張らず、どうぞ)

態を変える

能動受動を反転させる。特にit説なんかが入っている場合にはかなり有効な手段になります。

形容・副詞表現の充実

形容詞句、副詞句を似たような意味を持つ一語に置き換えてしまいます。また裏技として、ハイフン("–“)で区切って造語するのもあり。easy-to-useとか。

直接・関節表現の変換

特に有効なのは比喩表現をうまく用いること。逆に言い回しがすぎる比喩表現を直接的に言い換えることもできますね。

複数分の関係詞・分詞で一本化

複数文の一本化テクニックにまります。

例題

17語 → 9語

基準となる文は、こちら

The microscooter first hit the stores in the late 90s and became a craze around the world.

この17語の文章をなんとか9語にしてみます。結局andでつないでつ箇所がダラっとしている原因っぽいので、そこを分詞構文にしてみましょう。"hit the stores" = 「店頭に並ぶ」はいかにも字数稼ぎ過ぎなので、たとえば「出現する」 = “appear"を使ってみます。

また、"became a craze around the world" =「世界中で流行する」も、もうちょっとさっくりした表現でいいでしょう。world-famousとかで。んで。。。

The microscooter, appeared in the 90s, became world-famous. 

このあたりが普通に考えつく当たりですが・・・・。例えば態を変えて主客逆転させてみましょう。主語となるのは、“the late 90s”です。「時代が目撃した」みたいな感じのニュアンスになるんでしょうか。こうなります。

The late 90s saw the microscooter booming worldwide.

これはよいですね。先生の参考回答でしたが、こういう転換はまだできない。

もうひとつくらい見ておきましょう。

18語 → 9語

基準となる文は、こちら。

It was the perfect way to get to the store, but I got some strange looks back then.

これも二文結合なので分詞構文で短くすることを考えます。後段のbut以下をなんとかしたい気分ですね。「〜を除けば」だと"Expect for 〜"ですが、できればもうちょい短くしたいところ。よし、"Ignoring"でどーでしょ??

Ignoring the strange looks, it was ~

ふむ、収まりは良い感じです。しかし第一文目が長いので5語以内に収めます。要はもう近距離移動なんでしょ?ということで。。。

Ignoring the strange look, it's perfect for short distances.

んで、やっぱり普通に考えられるのがここまでで、そっから先は先生が書いた文章でため息を2つつきました。まず一つ目。先程と同じ主客逆転。分詞句"Ignoring the stange look"をそのまま主語化します。そうするとですね・・・

Ignoring my looking strange makes short-distance trip perfect.

使役を使って、綺麗に主客が入れ替わりました。

さらにもう一つの先生の回答は、さらに面白くて

Strange looks were which I paid for convenience.

否定→肯定というこれも態の入れ替えですね。「奇異に見られることを無視すれば・・・だった」→ 「奇異に見られるのを代償に・・・を得た」。確かに、その通り。こういう変換もあるんですねぇ。。。

2012-02-22

GoogleSiteに掲示板を設置する(やや強引)

| 00:00

ちょっと私用でGoogleSiteを使用しています。そこで掲示板がほしい、との要望があったので、ちょっと調べてみました。

Google Groupを使う。

Google Groupを使うのが最も推奨される方法なんでしょうね、やっぱり。

【001】Google Sites にフォーラム( Google Group(new UI) )を組み込む - すべてはグーグル - All Powered by Google!

んでも、若干面倒臭いです。というわけで、超簡易的にやる方法をご紹介します。

tal.kiを使う

tal.kiはかなり簡単なステップでフォーラムを追加できるサービスです。

方法はほんとうに簡単で、まず登録ボタン → フリープランを選んで、ログインします。

ログインはグローバルなID系はほぼ使えるといっていいくらい豊富です。Twitter, FBはもちろんのこと、Live ID、Googleアカウント、なんでもござれです。

f:id:posaunehm:20120222195859p:image


とりあえずTwitterログインするとトップページに戻ります。そこで「Get Embedd Code...」とか書いてあるボタンを押すと、もうこの画面です。

あとはGoogle Siteのアイコンをクリックして表示されたページから”View Source”で飛ぶアドレス(xml)をコピーしてきます。

(ボタンとか押したくなりますがどうもバグのよう。おとなしくソースのアドレスをもらいましょう)

あとはGoogleSiteで、ガジェットの追加 → URLを指定して追加で、さっきのXMLのアドレスをとってきたらOKです。

f:id:posaunehm:20120222235644p:image


こんなかんじで最初に設定を要求されますが、めげずに進みましょう。

とまぁ、こんな感じで作成が完了します。非常にさっさとできるのが良い感じですね。

というわけで、軽いTipsでした。

参考

Googleサイトに掲示板を設置する方法 - ウェブカツ!(ホームページ制作のWeb500)

2012-02-21

TDDで作るBrainFuck実行機 5(最終回):リファクタリングをしないとTDDとは言えんのですよ。

| 21:31

なんとなくインデックス作っておきます。

TDDで作るBrainFuck実行機

それでは、最終回。リファクタリングをします。

リファクタリングをするかしないかがTDDかどうかの分かれ道

みたいなことがTDDer(なんて読むんだこれ)では常識らしいですね。まぁ僕も最近はそう思い始めてます。TDDの利点は安心してコードがいじれること。だとすると書いたまんまいじらないで放置してしまっては、一体何のためのテストコードなんだか、ということになってしまいます。

ということで、リファクタリングです。

括弧の位置くらい覚えておけばいいんじゃないの??

さて、どこをリファクタリングしましょうか。とはいえもう明らかに無駄なコードがあります。括弧の探索ですね。BrainFuckにおける括弧はループのためのみに存在しています。ということは、イコール何度も繰り返すということ。それなら、辞書にでも放り込んでおきましょう。というわけで、括弧の位置を見つける関数を呼ぶ前に、辞書を探索するようにしました。

		// 入力を括弧位置のインデックスとする
		int GetIndexOfEndBrucket(int currentIndex)
		{
			if(!_brucketPairs.ContainsKey(currentIndex))
			{
				_brucketPairs.Add(currentIndex, FindIndexOfEndBrucket(currentIndex));
			}
			return _brucketPairs[currentIndex];
		}
		
		int FindIndexOfEndBrucket(int index)
		{
			//まずひとつ進めて・・・
			index++;
			//括弧閉じのカウンタも1に初期化
			int brucketCounter = 1;
			//括弧閉じカウンタが0になるまで入力文字をパース
			while(brucketCounter > 0)
			{
				if(index >= _input.Length)
				{
					throw new ApplicationException("括弧が閉じられていません");
				}
				
				//開き括弧なら括弧カウンタを加算
				if(_input[index] == '[')
				{
					brucketCounter++;
				}
				//閉じ括弧なら括弧カウンタを減算
				else if(_input[index] == ']')
				{
					brucketCounter--;
				}
				index++;
			}
			//必ず一つ行き過ぎているので、一つ戻しておく
			return index - 1;

閉じ括弧も同じですね。

		//入力を括弧閉じのインデックスとする
		int GetIndexOfStartBrucket(int currentIndex)
		{
			if(!_brucketPairs.ContainsValue(currentIndex))
			{
				_brucketPairs.Add(FindIndexOfStartBrucket(currentIndex),currentIndex);
			}
			
			return _brucketPairs.First(dict => dict.Value == currentIndex).Key;
		}
		

		int FindIndexOfStartBrucket(int currentIndex)
		{
			//初期化
			currentIndex--;
			int brucketCounter = 1;
			//前に戻りながら括弧を見つける
			while(brucketCounter > 0)
			{
				if(currentIndex < 0)
				{
					throw new ApplicationException("括弧が閉じられていません");
				}
				
				if(_input[currentIndex] == '[')
				{
					brucketCounter--;
				}
				else if(_input[currentIndex] == ']')
				{
					brucketCounter++;
				}
				currentIndex--;
			}
			//必ず行き過ぎてるので戻しておく
			return currentIndex + 1;
		}

とまぁ、素直に実装したので、テストを走らせておきます。よし、OKOK。

しかしこれ、閉じ括弧から戻るときには全探索かける必要があるんですよね。。。ちょっと時間はしかも。まぁ閉じ括弧は最後だから一回だけ・・・ではなくて、むしろ開き括弧から閉じ括弧に飛ぶケースのほうがかなり稀です。というかループを抜ける一回のみです。わひゃあ。

それにまぁあり得ないかもしれませんが、閉じ括弧で抜けた時には辞書から削除しておいても問題はないはずです。バカみたいにる

ル-プさせたときは若干ながらメモリを食うし、なんとなくもう使わないものは削除しておきたいですねぇ。。。

いやいやそもそもそもSwitch文なんて邪悪な構文は腹を切って死ぬべきなんじゃないの?


、、、と。かように書いてから悶々とすることはやっぱり多いわけです。こうした時に安心してさわれるようにユニットテストを整備しておくのは重要ですね。ほんとに。


最後にシナリオテストを

といってもそんな大げさなものではなく。Wikipediaの各言語Hello Worldに乗っているBrainFuckHello Worldをテストしておきましょう。

		[Test]
		public void ハローワールドテスト()
		{
			var compiler = new BrainFuckCompiler.BrainFuckCompiler("+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+.");
			var answerList = new System.Collections.Generic.List<byte>();
			compiler.OutputEvent += output => {
				answerList.Add(output);
			};
			compiler.Run();
			answerList.Is(
				"Hello, world!".Select(ch => (byte)ch));
		}

f:id:posaunehm:20120221211652p:image

よし、OK!(・∀・)

なんとなくTDDやってみて感想とか。

だらだらと簡単な課題でTDDしてみました。実際問題、ひとまとまりのプログラム全体をTDDしてみるというのは初めての景観だったりします。まぁコード行数的にとんでもなく少ない課題ではありますがw

簡単なネタが思いつかず、とりあえず記事になるからやってみるかぁ、位のノリだったのですが、実際にやってみると自分の中でTDDをどう消化していくか、という指針はできたかなぁ、という気はします。


TDDはできないプログラマのためのもの

じつは会社の尊敬する先輩が、だいぶ前から「TDDは実装効率落ちるし、あんま最近はやってない」と言われていたのがずっと引っかかってはいました。でも自分でやってみて、ハタから見るとこんなに馬鹿らしい作業すら間違える自分を発見して納得した次第です。僕は現実世界でもかなりのミスりキャラで、まぁドタバタしてます。んで、今回コードを書いたら基本的なものを間違えてること間違えてること。Whileループの中で停止条件のインクリメントを忘れてたりとか、forループのインデックス変数を取り違えてるとか、もう色々。散々でした。

んで、そういう時にテストは冷酷に赤くなってくれるんですよね。もちろんデバッグの動作確認でそこら辺は分かるんですが、新機能追加によるデグレードなんかは拾いきれなかったりします。というかそもそも間違いに気づくのが遅すぎてなかなか発見出来なかったりとか、ね。とにかく、TDDやってると自分のミスを自分でカバーできます。それだけでも僕にとってはかなりのありがたみです。

んで、やっぱある程度以上出来る人はそこに時間とか手間を割きたくないんだろーなー、というのはわかります。間違えるはずのない事をわざわざ確認してるわけですし。

とりあえず、しばらくはテストコード書く癖を定常的につけようと思います。ダメな自分を認識できて、それを正す手段も分かったんだから、やんないとダメですよね。

というわけで、これを読みます。英語の勉強を兼ねてね!

The Art of Unit Testing: With Examples in .net

The Art of Unit Testing: With Examples in .net

2012-02-20

TDDで脳がトロトロになるコンパイラ作りその4 イベントのテストとか。

00:24

ちょっと開きましたが、例の脳が溶ける言語コンパイラをちょいちょいつくっていきますよっと。

まぁそもそもさっさと作れって話ですが

さて、BrainFuckには入出力がありまして、今回はそれを両方共イベントで定義していました

		public event Action<byte> OutputEvent;
		public event Func<byte> InputEvent;

こいつのテストですねー。まぁ、とりあえず力技で書いてみましょうw

		[Test]
		public void 出力テスト()
		{
			var compiler = new BrainFuckCompiler.BrainFuckCompiler("+++.");
			var answerList = new System.Collections.Generic.List<byte>();
			compiler.OutputEvent += output => {
				answerList.Add(output);
			};
			compiler.Run();
			//一個しか出力されてないことを確認。
			//Chainning Asserition最強説
			answerList.Is((byte)3);
		}

まぁ、普通にイベントに登録して、出力をリストに放り込んで、最後に比較です。ChainningAssertionがあるとこれがまた強力です。非常に便利です。

んで、実装です。まぁ実は実装事態は超単純でして。

	case '.':
		if(OutputEvent != null)
		{
			OutputEvent(_memoryStream[_programPointer]);
		}
		i++;
		break;

んで、Inputも確認しましょう。テストは、普通に入力イベントを走らせた後に、値を確認してみましょう。

		[Test]
		public void 入力テスト()
		{
			var compiler = new BrainFuckCompiler.BrainFuckCompiler("+++,");
			compiler.InputEvent += () => 10;
			compiler.Run();
			compiler.CurrentValue.Is((byte)10);
		}

こうこう。んで、こっちも実装は超単純。

	case ',':
		if(InputEvent != null)
		{
			_memoryStream[_programPointer] = InputEvent();
		}
		i++;
		break;

これで、大体の実装は出来ましたかねー。

2012-02-19

ちょっとコマンドバトルのクラスを考えてみるよ。

| 00:51

今、会社内の勉強会でC++の勉強をしてます。んで、課題として出されたのがC++的なコマンドラインバトルだったので、そのクラス設計をする様子をツラツラと書いていこうかと思います。ちなみに、書き始めてる時点で頭はまっさらです。つらつらふらふら迷いながらプログラミングしますので、そこらへんに付き合ってやるという奇特な方を対象としてます。

要は、自分用のメモに近いです、はい。

まずはザクッとしたクラス図から

そいでは、まずは最初のクラス設計。まぁ、こういうのは普通Gameクラスみたいのにキャラクターを放り込みますよね。というわけで、まずはこうじゃないですかね。

f:id:posaunehm:20120219222024p:image

とはいえ、コレだとあんまり宜しくないです。まずGameクラスってなにをするんでしょ?何か役割が大きすぎる気がします。GameじゃなくてBattle位のほうが分かりやすそうです。

Battleクラスの責務は、まず敵・味方それぞれのインスタンスの攻撃を管理すること。ここではドラクエみたいなターンバトルをとりあえず前提にしようかと思ってるので、「ターンを進める」みたいなメソッドが必要でしょう。

また、ドラクエみたい、と考えると敵や味方も複数人いることが必要でしょう。なので、ちゃんと多重度も書いておきます。それに、それぞれの敵に対してクラスを作るのもアレですので、共通のインタフェースを定義しておきましょう。てなわけで。

f:id:posaunehm:20120219223659p:image

あとは各クラスが持つべきプロパティメソッド、すなわち書くクラスの外部設計をもう少し考えてみましょう。

Battleクラスの外部設計

Battleクラスは敵と味方キャラを複数人ずつ受け取り、それを外部から駆動されるターン進行処理によりターンごとに戦わせる、というようなモデルと考えましょう。そうすると、まず戦闘の終了を意味する何かがほしいです。ProgressTurnの返り値にboolを指定して、進められなければfalseにするって方法もあるかと思いますが、あんまり返り値に処理の結果ではなく状態を返すのは個人的にあんまり好きじゃないです。HRESULTみたいで。てなわけで、プロパティを設けましょう。IsBattleEnd、とかですかね。

あとは現在のターン数とかはほしいかも。追加しときましょう。

IPlayerの外部設計

基本的には、攻撃を受けることと攻撃を与えることが出来ればそれで良いはずです。つまり攻撃力とHPが有ればとりあえずOK。。。ですが、やっぱり防御力はほしいですよね。RPG的には。

というわけでこの3つをプロパティとして設定できればそれでよさそうです。

他には・・・、あ、取りうるコマンドが有りますね。

IEnemyの外部設計

基本的には、攻撃を受けることと攻撃を与えることが出来ればそれで良いはずですが、やっぱり防御力も、ってあれ?IPlayerと同じですよね。。。そうか、ここをインタフェースとして分ける必要性は無いですね、今のところ。かりに別のInterfaceがあるにしろ、共通部分を抜き出すことはしておいたほうがよさそうです。

そいじゃこんな感じ?

f:id:posaunehm:20120219225442p:image


ふむ、とりあえずスッキリとはしたかな・・・。

コマンド選択どうするよ?

ん?しかしもう一つ気になることが出てきました。コマンド選択事態をどうしましょう。いまだとBattleクラスに一任しちゃいそうですが、さすがにそれはなんか違いそうです。まず、コマンド自体が持つべき責務を考えてみましょう。単純に考えると、

  1. ターゲットに対して
  2. 何か操作を行い、パラメータを変更させる

という特徴が有りそうです。んじゃ、そういうインターフェースを持たせてみればいいのかな。

んで、それを各キャラクターが持っている、と。こんな感じでしょうか。

f:id:posaunehm:20120220004602p:image

とりあえず、こんな感じまで来ましたが、コレ思ってるほど単純じゃないですね。。。

明日までにはちょっとできそうにないなぁ。まぁ設計にこだわらなければサッと出来るんだろうけど。