英語のリスニングは難しい

最近、インターネットの発達によって英語を聞く機会が増えていると思う。
というか、うちにはケーブルテレビが来ていてディスカバリーチャンネルやらナショジオやらBBCやらがいつでも聞ける。
その他映画系のチャンネルを含めて副音声に切り替えればいつでも英語を聞く事ができる。
最近はニコ動にもリスニング教材タグで英語の勉強をすることができる。


ところで、英語の音声にいくら耳を澄ませてみても一向に聞き取れるようにならない。
知っている単語やら、サンキューやらThat's all! なんかの簡単な言い回しなら聞き取ることができる。
BBCなんかだと何が主語で何が動詞かなんてのもさっぱり。
英語字幕のある動画なんかを見ていると、 Now, put all your love into it.(ありったけの愛をこめて)すら聞き取れないことに気がつく。
ちなみに文章であれば、 put A into B だなー。というのはわかるのだけれども…。


そんな状態なので、TOEICの単語帳の例文やduo3.0の文章もいちいち読んで聞いてを相当繰り返さないといけなくてなかなか先に進まない。

さて、そんなこんなで本屋をブラブラとしているとこんな本を見つけた。
本屋のPOPカードには世界一受けたい授業で紹介されたとある。

魔法のリスニング (J新書)
リサ・ヴォート
ジェイ・リサーチ出版
売り上げランキング: 24,328


魔法の英語 耳づくり (J新書)
リサ・ヴォート
ジェイ・リサーチ出版
売り上げランキング: 32,145


とりあえず両方買ってみた。
この本は、thank you が、「サンク ユー」と読むんじゃなくて実際には「サンキュー」と発音されるよ。という感じのルールが120個。さらにそれぞれ例文が5個ずつ乗っている。
サンキューに限らず、中には経験則的にああーそういえばそうだなと思うものも多く、リスニングには必須じゃないかと思う。というかなぜこれを学校でやらないのか不思議なくらい。
例えば、should be → シュッびー とか Can I → キャナイ とか、高校で習った「昔は何々だったのに…」を表す used to → ユースとゅ〜 とか。
今までどうしてもこの文章の of が聞き取れない! と悩んでいたやつとか、この本を読んで kind of → カインだ だからあーなるほどそーなんだ。と納得するものが多い。


あとは日常会話的な表現が多いのが個人的には嬉しい。
こんなところかな → That pretty much sums it up. とか なんでそうなの? → Because why. とか。
例文自体は短めのものが多いのでまずはこれをきっちりと聞き取れるようになってから、他の書籍のCDに取り組んでみたらより理解が深まるかも。

泳ぎに行く

区民センターのプールがすごく安いかつ夜10時までやっていることに気がついた。

泳ぎたいなぁー。と漠然と思いついてからはや数年?
ふと区がやっているプールに行きたいと思った。夏休みだし土日ならそんなに混んでない時間帯を狙っていけば十分だろうと。
ところが、なんと屋内プールは年中利用できて朝9時から夜の10時までやっているではないか!? しかもお値段2時間400円。
頑張れば平日の仕事帰りに通えるんじゃね?
そして屋外プールは朝9時から夜の8時まで。しかもお値段200円!


というわけで早速水着を新宿に買いに行き、19:00から45分だけ泳いできた。
屋外プールは50m x 9レーン。 平日の終わり際なのであんまり人はおらず、そして運動不足の体で25mも泳げるわけもなく、フラフラになりながらのんびり水と戯れる程度。


水着はフィットネス用のぴったり目のものを購入。
ピッタリとしていてそれほど窮屈でもなくデザインもよい。性格にはfla2815の青いやつを買ったけど、アマゾンにはないみたい。


ゴーグルはこれ。小中学校の頃に使っていたすぐ曇ってゴムが硬い掛け心地の悪いやつとは違い、柔軟性があって目のあたりにとてもよくフィットする。
お値段1000円だったけれども、以前買った安い1000円のよりもずっと良い感じがする。…お店で買うよりアマゾンのほうが安いけどまあ仕方ないか。

ビュー(VIEW) FITNESSゴーグル ブラック BK V610
ビュー(VIEW)
売り上げランキング: 115


あとはスイムキャップ。レジャープールや海ならともかく学校のプールとか市営のプールはだいたい必須。
メッシュの安いやつだと髪がギシギシするらしいので、2way(メッシュとシリコンのいいとこ取り? 水着と同じ素材だと言われた)のスイムキャップを購入。
簡単に装着できて締め付けもなく、ゴーグルをかぶるときにも違和感がない。上がった後も髪は特にギシギシしてない。(ほとんど泳いでないから当然かも)

アリーナ テキスタイルキャップ ブラック ARN8609 BKSV
arena(アリーナ) (2012-06-15)
売り上げランキング: 8,498


さて、50mくらい泳げる体力をつけないと…。

英語の勉強

プログラムをやっていると大体SymfonyやらPHP系のフレームワークやらの情報は英語の公式ページかもしくは英語のBBSを読むことになる。
そうするとニュアンスが結構重要になってくる。


たまに公式のAPI説明でこんなのがある。
フォームの値をプログラム中で変えて、エラーだったら前のフォームで入力された値を表示して、そうじゃなければDBから撮ってきた情報を表示したいとき。

setField() 的な関数は…ないなぁ。
…じゃあbindした後にフォームの値が空だったらDBの値でbindしなおせばいいかな?
えーっとbindするには内部フラグ、bindFlagとかいうのがクラス内にあって、一度それを消してから再度バインドすればいいのかも。
でもsetBindFlag() なんて関数ないし、そもそもソレだと設計的におかしいなぁ。

getBindFlag()なんて関数もないし…、あ、getBindState()なんてそれっぽそう。えーっとAPIドキュメントはっと。

getBindStatus()
This function return BindStatus().

え?それだけ?公式ドキュメントなのに??
BindStatusってなんやねん! Nullしか帰ってこないぞ!これがどこのタイミングで変わるのか知りたいってのに…。

なんてことがあり、そんな時は英語の掲示板をググりまくる。

Q. How to set of one field while ... (処理中にフォームの値を変えたいんだけど→おお、この質問だ!)
A1. なにやら大量のvardump情報…。 OK? (何書いてあるかよくわからん! でもこれこれだからほら難しいでしょ?って書いてあるっぽい)
A2. I think so too, But the first solution seems ok to me. (やっぱりそうか。的な感じ? でも一つ目の方法でうまくいきそう??)

え? いけたの?イケテナイの??気になって夜も眠れない!!


という思いをしないために英語の勉強をしようと思い立つ。


TOEIC TEST英単語スピードマスター
成重 寿
ジェイ・リサーチ出版
売り上げランキング: 3,514


とりあえず単語は必須と思い購入。
appleapp storeで英語学習者用の英英辞書 Oxford Advance Dictionaryも購入。たまに落ちるけど十分使いやすい。文字も大きくなるし。


英語で経済・政治・社会を討論する技術と表現(CD BOOK)
植田 一三 上田 敏子
ベレ出版
売り上げランキング: 104,690


本屋でこれも面白そうだったので購入。
BBCとかCNNとかリスニングできるようになりたいものだけれどもさっぱり。
この本では経済用語やら言い回しなんかも英語でいちいち書いてくれるのでパラパラ読んでいるだけでも頭に入りやすい。

緑内障と勉強

僕らがまだ子供だった頃、親や教師によく言われること。
「今のうちにちゃんと勉強しなさい。大人になって後から後悔しても仕方ないよ。」


そうして、緑内障歴がかれこれ14年。そろそろ人生の半分を緑内障とともに過ごしていることになるが、最近良く思う。
「今のうちにちゃんと目薬差しておきなさい。見えなくなってから後悔しても仕方ないよ。」


元から視力が強制で0.5しかないために精神的ダメージが殆ど無いのが困りものだけれど、
やはり日常的に、あるいは潜在的に視野が欠けてきている影響は確実にある。
道に迷ったり、看板が見つけられなかったり、自転車にのるのが危ないと感じたり、見落としが多くなったり…、とにかく気力や生命力が減っているように思う。


左目視力0.1 視野欠損4/6 文字がほぼ見えず中心付近と内側が欠けてしまっている。
右目視力0.5 視野欠損3/6 中心より上部が左上が殆ど欠けてしまっている。


WEBプログラマーなんぞをやっているものの定年まで仕事ができるのか最近不安でしょうがない。
なんともまぁうまくいかないものかな。

勇者と魔王

ドラクエ3で出てくる道中のキャラは先代、あるいは先々代の勇者が持ちまわりでやってるんじゃないか?とふと考えた。

勇者は魔王に打ち勝った。世界中の人たちから感謝された。
勇者はルイーダの支配人になった。町の多くの冒険者を見送った。
勇者はナジミの塔の番人になった。たんくんの初心者を見守った。
勇者は洞窟の番人になった。それなりの冒険者を導いた。
勇者はカンダタになった。いくらかの猛者たちが自分を越えていった。
勇者はダーマの神官になった。やりこみ派のパーティを転職させた。
勇者は黒胡椒愛好家になった。たまに来る黒胡椒と引き換えに船をあげた。
勇者はランシールの番人になった。まれに来る挑戦者に「引き返せ」とつぶやいた。
勇者はラーミアの番人になった。数年に一度ラーミアの乗り方を教えた。
勇者は世界の隙間の番人になった。何十年に一度落ちていく人に心構えを説いた。
勇者はあまぐものつえの管理人になった。待ちくたびれた頃にやってきた誰かにそっとアイテムを手渡した。
勇者は最後のダンジョンに住み着いた。勇者とはなんだったのか忘れかけた時にやってきた勇者たちに最後の希望を託した。

…そうして勇者は最後に魔王になった。

C++ 11がそのまま動くiphone

iphoneアプリを作るにあたってopencvでカメラの画像をキャプチャするものを作ってみた。
opencvはテンプレートなどをバリバリ使うC++のライブラリであるが、xcodeで普通に混在できるようだった。
…ということはC++11のコードとかそのまま使えるのかなーと思ってやってみたら案外普通にいけた。


http://codezine.jp/article/detail/6639C++11のthreadを使った素数を数えるプログラムが乗っていたのでそれを簡単に移植してみた。
数万までの整数について素数であるかどうか調べるというもの。
普通に調べるだけならエラトステネスのふるいを使ったほうが断然早いのだが、そこはまあ何秒かかるのかわかりやすくするためにそうなっているんだと思う。


コードはこれ。

//ViewController.mm
//
// ViewControllerにボタンを一つ追加し、クリックした時のデリゲートを適当に設置しておく。

// include じゃなくて import
 #import "vector"
#import "thread"

//それぞれのスレッドにどこからどこまでを計算させるかを示すためのテンプレートクラス
template<typename T=int>
class div_range{
private:
    T lo_;
    T hi_;
    T stride_;
    T div_;
public:
    div_range( int lo, int hi, int div)
    : lo_(lo), hi_(hi), div_(div) { stride_ = (hi-lo)/div; }
    T lo(int n) const { return lo_ + stride_ * n; }
    T hi(int n) const { return ( ++n < div_ ) ? lo_ + stride_ * n : hi_; }
};

typedef std::tuple<int,int,int> thread_io;

//その整数が素数であるかどうかを調べる。
bool is_prime(int n)
{
    for( int i = 2; i < n; i++)
    {
        if( n % i == 0)
        {
            return false;
        }
    }
    return true;
}

int count_prime( const unsigned int lo, const unsigned int hi)
{
    int count = 0;
    for( int i = lo; i < hi; i++)
    {
        if( is_prime(i) ){
            count++;
        }
    }
    return count;
}

//シングルスレッドの場合 (参考まで)
void single(int M)
{
    std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
    int number_of_prime = count_prime( 2, M);
    std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
    
    NSString *title = @"result";
    NSString *msg = [NSString stringWithFormat:@"%d %f [sec]", number_of_prime, sec.count()];
    
    UIAlertView *alert =
	[[UIAlertView alloc]
     initWithTitle:title
     message:msg
     delegate:Nil
     cancelButtonTitle:@"OK"
     otherButtonTitles:nil];
    [alert show];
}

//マルチスレッド
void multi(int M, int number_of_thread)
{
    std::vector<std::thread> thread( number_of_thread);
    std::vector<int> count( number_of_thread);
    div_range<> range( 2, M, number_of_thread);
    
    auto start = std::chrono::system_clock::now();
    for( int i = 0; i < number_of_thread; i++){
        thread[i] = std::thread( [&,i]( int lo, int hi){ count[i] = count_prime(lo,hi);}, range.lo(i), range.hi(i) );
    }
    int result = 0;
    for( int i = 0; i < number_of_thread; i++){
        thread[i].join();
        result += count[i];
    }
    std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
    NSString *title = @"result";
    NSString *msg = [NSString stringWithFormat:@"%d %f [sec]", number_of_thread, sec.count()];
    
    //結果を表示するためにとりあえずメッセージボックスを使う。(重なって表示されるがまあいいや)
    UIAlertView *alert =
	[[UIAlertView alloc]
     initWithTitle:title
     message:msg
     delegate:Nil
     cancelButtonTitle:@"OK"
     otherButtonTitles:nil];
    [alert show];

}


//ボタンが押されたら呼び出されるデリゲート
- (IBAction)showMap:(id)sender {
    const int M = 50000;
    for( int i = 1; i < 6; i++){ multi(M, i); }
}


結果は以下のとおりとなった。

手持ちのiMac 2011で普通にC++としてコンパイルして実行。(10万まで。最適化なし)

かかった秒数 スレッド数
1.89211[sec] 1
1.39071[sec] 2
1.07219[sec] 3
0.858417[sec] 4
0.743213[sec] 5
0.713778[sec] 6
0.67413[sec] 7
0.666978[sec] 8
0.642282[sec] 9


手持ちのiphone4Sで実行。(5万まで。最適化なし)
5.148979[sec] 1
3.889552[sec] 2
3.213674[sec] 3
2.985299[sec] 4
2.854148[sec] 5

と、コア数が増えれば増えるほど早くなっているのがよく分かる。
iphoneは4スレッドで、iMacは8スレッドで頭打ちになるはずだが、いずれも微妙に早くなっていたりする。

iphoneopencvをカメラでキャプチャする

ライブラリのビルドはなぜか毎回失敗する(ファイルが何か足りなかった)ので、大人しくiphoneようパッケージを落としてきて2.4.3だったか何かを設定する。
ボタンを押した時にカメラを起動するためのデリゲート takePictureを適当に書いて、画像を撮り終わったらそれをopencvの画像形式に変換する。
そして、適当に処理をしたらまたiOSの画像形式に変換して表示させる。
…がとりあえず拾ってきたソースをつなげただけなのでイマイチフォーマットやらなんやらがわからない。


カメラを起動して撮影するときはUIImagePickerControllerDelegateを使うらしい。
ボタンを押す → デリゲート(takePicture)
→UIImagePickerController(撮影モード) → 撮影完了 → UIImagePickerController
→UIImageをopencvの形式であるcv::matに変換する。 → opencvで好きなだけいじる → UIImageに変換してviewかなんかに表示させる。

//ViewController.mm

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    worldView.delegate = self;
    [worldView setShowsUserLocation:YES];
}

/*
 参考: http://www.patokeefe.com/archives/721
 */
- (UIImage *)UIImageFromMat:(cv::Mat)image {
    NSData *data = [NSData dataWithBytes:image.data length:image.elemSize()*image.total()];
	
    CGColorSpaceRef colorSpace;
	
    if (image.elemSize() == 1) {
        colorSpace = CGColorSpaceCreateDeviceGray();
    } else {
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }
	
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
	
    // Creating CGImage from cv::Mat
    CGImageRef imageRef = CGImageCreate(image.cols, image.rows,
                                        8, 8 * image.elemSize(),
                                        image.step.p[0], colorSpace,
										kCGImageAlphaNone|kCGBitmapByteOrderDefault,
                                        provider, NULL, false,
                                        kCGRenderingIntentDefault);
	
    // Getting UIImage from CGImage
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);
	
    return finalImage;
}

/*
 * UIImageからCvMatに変換する。
 */
- (cv::Mat)CvMatFromUIImage:(UIImage *)image {
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
    CGFloat cols = image.size.width;
    CGFloat rows = image.size.height;
    
    cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
    
    CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,                 // Pointer to backing data
                                                    cols,                      // Width of bitmap
                                                    rows,                     // Height of bitmap
                                                    8,                          // Bits per component
                                                    cvMat.step[0],              // Bytes per row
                                                    colorSpace,                 // Colorspace
                                                    kCGImageAlphaNoneSkipLast |
                                                    kCGBitmapByteOrderDefault); // Bitmap info flags
    
    CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
    CGContextRelease(contextRef);
    
    return cvMat;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


//ボタンが押されたら呼ぶ。 ここでカメラを起動して画像を取ってくる。
- (void)takePicture:(id)sender{
    
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    //カメラをサポートしているかどうか
    if([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront] ){
        [imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
    }else{
        [imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
    }
    
    [imagePicker setDelegate:self];
    
    //画像ピッカーを表示する。
    [self presentModalViewController:imagePicker animated:YES];
    
}

//写真を撮り終わったら呼び出される関数
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *) info{
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // おまじない
    UIGraphicsBeginImageContext(image.size);
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    // cv::Matを生成
	cv::Mat srcImg = [self CvMatFromUIImage:image];
    cv::resize(srcImg, srcImg, cv::Size(400,640));
    
	// ここで画像を直接いじれる。ただし写真のフォーマットがどうなっているのかまだ調べていない。
	for( int y = 0; y < srcImg.rows; y++ ) {
		cv::Vec3b* ptr = srcImg.ptr<cv::Vec3b>( y );
		for( int x = 0; x < srcImg.cols; x++ ) {
			cv::Vec3b bgr = ptr[x];
			//ptr[x] = cv::Vec3b( 0, 128, 255);
                       ptr[x] = cv::Vec3b(1.0 * x / srcImg.cols * 255, 0, 0);
		}
	}
	
	// UIImageViewに表示する
	UIImage *newImage = [self UIImageFromMat:srcImg];
    [photoImage setImage:newImage];
	
    NSLog(@"tes");
    [self dismissViewControllerAnimated:YES completion:Nil];
}

//カメラがキャンセルされた時に呼び出される関数
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    NSLog(@"camera cancel");
    [btnGps setTitle:@"GPS??" forState:UIControlStateHighlighted];
    
    [self dismissViewControllerAnimated:YES completion:Nil];
}
@end

画面遷移の仕方がいまいちよくわからない。