2012年2月26日日曜日

javascriptの配列sliceコピー

使い捨てコード用メモ。
javascriptで以下の方法で、配列を別インスタンスにして(いくつか注意点があるけど)sliceメソッドを使ってコピーできる。

単なる代入との違いは、以下で確認できる。
sliceコピーした配列には要素の削除が反映されていない。
別インスタンスとしてコピーされている。

ただし、あくまで配列が別インスタンスになっているだけであって
deep copyではないので、object型の要素は同じインスタンスを指している。
以下の3つ目のobject型の要素はvar bでも"hoge"から"fuga"へと変更されてしまっている。
他のプリミティブ型はimmutableなのでたまたま変更が跳ねていないだけ。

sliceメソッドを本来の目的でない使い方をしているのと制約があるのとで
使い捨てコードを書くとき以外は使わない方が良さそうだけど、便利そうなので備忘録としてメモっておく。

■参考:
http://www.gucch.net/programming/javascript/jqueryやprototype-jsでオブジェクトをディープコピーする/

2012年2月17日金曜日

node.jsをgithub経由でローカルにインストール


consoleでjavascriptを手軽に扱えるようにしようとnode.jsをインストール。
せっかくなので、githubからforkしてローカルにcloneしてみた。
環境:Mac OS X Lion, Xcodeインストール済み

上記のnodeのページで右上の「fork」ボタンをクリック。
画像は既にfork済み状態でキャプチャしたので、「Your Fork」ボタンになってしまっている。

ちょいと待ったら、自分のGithub上にリポジトリが出来るので
あとはそれをローカルにcloneしてインストール。コマンドは以下。


インストールは、結構時間かかった。
最後にsudoでmake installしないと、自分の場合はPermission Deniedになった。

nodeコマンドが使えるようになった!

2012年2月15日水曜日

Googleの入社問題(数字当てクイズ)


昨日、会社のリスクマネジメント研修とやらを受けさせられたのだが
その中で講師の人が講義の時間の間を埋めるのに以下の問題をGoogleの入社試験だと出題したのだった。
1
11
21
1211
111221
?
【?に入る数字をこたえよ】

自分は結局答えが分からなかったのだけど。
回答が分かれば、コードで出力する問題としては暇つぶしに手頃なサイズだったので以下のアプリで書いてみた。
Javascript-1

以下、ねたばれ注意



HTMLの中に埋め込む形式で書いたのだけど、HTMLの部分は本質ではないので省いている。
HTML付きでブラウザで表示するだけで回答が見れるコードは以下。
https://gist.github.com/1828081

iPhoneのソフトウェアキーボードでコード打ち込みながらdocument.write()するデバッグは辛かった・・・。
最初、自分でnumber型をresにpushしていながら
6行目で癖で===で比較していたため値は一致しても型不一致で期待通りに動いていなかったという\(^o^)/

以下、回答。一応、文字を白にしとくんで、見たい人は文字選択してください。
1
1 1
2 1
1 2 1 1
1 1 1 2 2 1
3 1 2 2 1 1
1 3 1 1 2 2 2 1
1 1 1 3 2 1 3 2 1 1
3 1 1 3 1 2 1 1 1 3 1 2 2 1
1 3 2 1 1 3 1 1 1 2 3 1 1 3 1 1 2 2 1 1

以下が回答を紹介しているページ。
http://ntakei.cocolog-nifty.com/pam/2006/04/post_231f.html

一言で言うと、文字と文字数を並べていくだけなんだけど、これってどこかで見たことある・・・と思って検索したら、正体は「ランレングス圧縮」だったのであった。
# 大学の情報理論の授業で習ったはず
# 久しぶりにハフマン符号化とか調べてしまった

連長圧縮(ランレングス圧縮、RLE:Run Length Encoding)
連長圧縮では、ある連続したデータを、そのデータ一つ分と連続した長さで表現することで圧縮している。
例えば、「A A A A A B B B B B B B B B A A A」は「A 5 B 9 A 3」と表せる。これは、Aが5回続き、そのあとにBが9回、そしてAが3回続いていることを表している(連続回数を、元のデータを表す符号の前に記録することもある。その場合、符号化した後は「5 A 9 B 3 A」と表される)。

講師の人は、Googleはこういう柔軟な発想が出来る人がごろごろいるのでしょうかねーと言っていた。
そういう発想の柔軟さもそうなのかもしれないけれど裏に隠れているコンピュータサイエンスの基礎理論を見抜いて解ける人もまたターゲットにしているのかも。

まあ、最近のシリコンバレーのジョブインタビューは(一時期流行った)こういうクイズめいた問題は実際の業務では役に立たん!とあまり出題されないらしいけど。

# 2012/2/19 Array.join()を使用するよう変更

2012年2月6日月曜日

GithubをXcodeのリモートリポジトリにする方法(コマンド使わずに)

Xcode4から標準インストールされているGit。
Githubをコマンドを使わずにリモートリポジトリとして指定する手順を説明している
良いページが見つからなかったので書いてみる。

前提

Xcodeプロジェクトが既にローカルGitリポジトリで管理されていること。
Githubにコマンドラインから接続可能なこと。
Version:4.2.1

主に以下の手順となる。
  • 1.Github上でリポジトリ作成
  • 2.Xcode上でリモートリポジトリ指定
  • 3.Xcode上でpush

1.Github上でリポジトリ作成

通常の手順でGithub上でリポジトリを作成する。

2.Xcode上でリポジトリ指定

ここからローカル作業。
Xcode上で下記の要領で"Repositories Organizer"を開く。

そして、自分のプロジェクトの"Remotes"を選択して、"Add Remote"を押下。
下記の要領で入力する。
  • Remote Name:Organizer上の表示名程度だと思ってる。詳しい方、教えてください。
  • Location: GithubのURI。git@github.com:ユーザ名/リポジトリ名.git
Locationは"https://..."でも行けるとどこかのサイトに書いてあったけど、試していない。


"Create"ボタンを押すと、以下の画面になる。何もせずに静かにOrganizerを閉じる。
最初、画面の下のパスワード等の入力フォームを入力しないといけないと思ってしまい
いろいろと入力してみるも何の反応も無く、Locationをいじったりして勝手にはまった。
しかし、パスワード等を入れなくても、以下の手順でpushまで出来た。

3.Xcode上でpush

下記のように"push..."を押す。

すると、下記のダイアログ登場。
そして、意外とこの画面で待つ。自分の場合、10秒くらい待った。
ここで待たされたせいで、設定が間違っていると勘違いして手戻った。

待ってると、下記の画面登場。さくっと"push"して完了。

全体的に、独りで勘違いして時間かかった。
Repositories Organizerはまだ安定しなくて、結構しょっちゅうCrashする。
今後の改善に期待。

NSNumberクラスとプリミティブ型との変換


元々はこの記事を書こうと思ってたんだった。
脱線してObjective-Cの整数と32bit64bitの記事が一個forkした。
まあ、この記事も元々はCoredataのNSManagedObjectのプロパティの型ではまったことによるforkです。

Objective-Cのコレクションクラス(NSArrayやNSDictionary)ではid型(オブジェクト型)しか扱えないため
NSIneger等のプリミティブ型を扱う際にはNSNumber型に変換する必要がある。
そこで、下記の相互変換についてメモとしてまとめておくことにした。
  • NSInteger
  • int
  • NSNumber

以下、基本的にMac-OS-X 64bit向け。
iOS環境では、NSIntegerの取る型が異なるため、NSLogのString Format Specifiersが異なる。
値が代入されていないと、%@でNSIntegerはエラーにならないが
値が代入されていると、"EXC_BAD_ACCESS"となって実行時エラーとなる。


初期値について


初期化していない状態での初期値は、NSNumberはオブジェクト型なので「nil」、intは「0」となる。
NSIntegerはオブジェクト型として評価すると「nil」、整数として評価すると「0」となる。


int <-> NSInteger


NSInteger -> int はキャストすれば良い。
キャストしないと警告が出るのは"Objective-Cの整数と32bit64bit"で書いた通り。

一方で、int -> NSIntegerはキャストは不要。
理由はざっくりな説明だと、NSIntegerがintをくるんでいるため
下位概念のものを上位概念のものに入れることになるから、かと。


NSInteger <-> NSNumber


NSInteger -> NSNumberについては、NSNumberクラスのメソッドを使用する。
クラスメソッドを使用するパターンとalloc initするパターンがある。

NSNumber -> NSIntegerについてもintegerValueメソッドでOK。


int <-> NSNumber


このパターンについては、NSInteger <-> NSNumberとメソッドが微妙に変わるだけ。



整数以外のfloatやdoubleも基本的には同じなので割愛。

サンプルプロジェクトを以下のGithubで公開。
https://github.com/k-ori/objc-nsnumber-primitive-convert-samples

xcodeからのGithub連携でいいサイトが無かったので、それも後で書く。

■参照ページ
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/Reference/Reference.html

http://peterszwach.blogspot.com/2011/03/github-xcode-4.html

Objective-Cの整数と32bit64bit


NSIneger等のスカラ型とNSNumber型の変換についてまとめようとしたんだけど
調べてるうちにObjective-Cのint型とNSInteger型、32bitと64bitの関係について
気づいたら調べていたのでまずはそこからまとめておく。

以下、特に注意書きしていない限りは、Mac-OS-X 64bit向けにビルドした結果。

まずは、NSInteger型をint型にキャストせずに代入すると以下の警告が出る。
Implicit conversion loses integer precision: 'NSInteger'(aka 'long') to 'int'

警告の理由は、NSIntegerの持ちうる値が32bitか64bitかは処理系依存だから。
int型変数に値を代入する時はプログラマが明示的にint(32bit)と宣言する必要がある。
そして、NSIntegerはlong型 "または" int型をtypedefしたもの。
(この"または"が処理系に依存する部分)

Foundation Data Types Reference

NSInteger

Used to describe an integer.

Discussion

When building 32-bit applications, NSInteger is a 32-bit integer. A 64-bit application treats NSInteger as a 64-bit integer.

Availability

Available in Mac OS X v10.5 and later.

Declared In

QTKitDefines.h

long型、int型といったプリミティブな型をNSIntegerにラップしてくれている。
NSInteger型を使用することで、32bit環境のコードを64bit環境に移植する時にコードを変更する必要がなくなる。

ちなみに、現時点のiOSデバイスのARM processorは(現時点で)32bit onlyだそうなのでNSIntegerでは64bit整数は扱えないそうです(@see iOS: 32bit or 64 bit? - DesignersTalk)。
OSX Lionだと64bit整数を扱える。

OSX 64bit用にビルドして下記のコードを動かすと、int型以外は正しく表示される。

NSLogに渡す際のformatter文字列を%ldにしないと正しく表示されないので注意。
int型は現在4バイト32ビットで、-2147483648〜2147483647 (約マイナス20億からプラス20億) の整数値を表すことができる。

2147483647を超えると、-2147483648に戻る。
よって、以下の通り2147483647を超えて1周半くらいして1410065408になる。
1410065408=10000000000-(2147483648*4)

ちなみに、上記と同じコードをiOS向けにビルドすると、結果が変わる。

32bit整数しか扱えないので、OSXでは正しく扱えていた値がオーバーフローしてしまっている。
ただ、コンパイラの優しいところは、ちゃんと明示的に大きな値を入れているときは警告を出してくれる。
warning: implicit conversion from 'long long' to 'NSInteger' (aka 'int') changes value from 10000000000 to 1410065408 [-Wconstant-conversion,3]
まあバグが発生する時は、だいたい巨大な値が外部リソースから実行時に入ってくる時なんだけど。



コンパイラ様の言う通りに「long long」型にしたら、iOSシミュレータ用でもちゃんと動いた。
NSLogのformatter文字列を%lldにしないとやっぱり正しく表示されないけど。
long修飾子をつけるとより多くのメモリ領域を確保する模様。

しかし、結局のところint型の取りうる範囲もコンパイラ依存な訳で
Apple様以外の環境なりコンパイラなりでいろいろと結果が変わるのだろうなあ。

■主な参照ページ
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_DataTypes/Reference/reference.html
http://stackoverflow.com/questions/8813799/warning-implicit-conversion-loses-integer-precision
http://www16.ocn.ne.jp/~maccocoa/objective_c/keyword/keyword1.html
http://www.designerstalk.com/forums/mobile/59128-ios-32bit-64-bit.html