修正版~Googleの入社試験(非公式)にチャレンジしてみた~

Googleの入社試験(非公式)にチャレンジしてみたで、チャレンジしたGoogleの入社試験(非公式)。
久しぶりに見直してみたら、間違ったソースコードだったので修正しました。

さらに、ソースを見ていると、長ったらしくてイライラしたので書き直すことにしてみました。

とりあえず、以下が問題文。

▼問題文

整数nが与えられたとき、0からnの間の全ての数を書くのに必要とされる「1」の数を返す関数があります。たとえば、『f(13)=6』になります。また、『f(1)=1』に注意。『f(n)=n』となるような、2番目に大きいnを求めなさい。

前回のソースは色々と無駄だらけなので、2番目に大きいnを探すだけに書き直してしまいます。


▼以下、問題にチャレンジ


とりあえず、まとめてソースを書いちゃいます。

class GoogleTest {
    private $anw;        // 1.答えを格納するプライベート変数

    /**
     * 答えを返す
     *
     * @param    $search     int    検索する値を整数値で指定
     * @param    $start      int    検索を開始する値を整数値で指定
     * @param    $cnt        int    検索を開始する値までに必要な$searchの数を整数値で指定
     * return    int    『f(n)=n』となるような、2番目に大きいnを返す
     */
    public function getAnw() {
        // 2.答えがセットされていない場合、nを求める。
        // 3.f(1)=1になる事は分かっているので、2から数える
        if(!$this->anw) $this->setAnw(2, 1);

        return $this->anw;
    }

    /**
     * 引数nの中にある「1」の数を返す
     *
     * @param    $n        int    検索を開始する値を整数値で指定
     * @param    $count    int    0から$nの間の全ての数を書くのに必要とされる「1」の数を整数値で指定
     */
    public function setAnw($n, $count) {
        $count += substr_count($n, 1);

        if($n == $count) {
            // 4.答えを変数に格納する。
            $this->anw = $n;
        } else {
            // 5.再帰でもう一度計算する
            $this->setAnw($n+1, $count);
        }
    }
}

$gT = new GoogleTest();
echo $gT->getAnw();

【ソースコードの説明】


ざっとソースを説明します。

1.まずは答えを格納する変数を用意します。

2.答えが変数に格納されていない場合、答えを求めます。

3.『f(1) = 1』となるのは分かっているので、2からカウントします。
この時、1を書くのに必要な1の数は1なので、第2引数には1を指定します。

(文字にするとややこしいですね。。。)

4.nを書くのに必要な1の数がnと等しくなった場合、答えを変数に格納します。

5.nを書くのに必要な1の数がnと等しくない場合、再帰処理を行います。

これで終了です。
前回より見やすいソースになったと思います(たぶん・・・)

このままじゃ、0からnの間の全ての数を書くのに必要とされる「1」の数がnと等しい2番目に大きいnしか求めれないのでダメダメな感じですけど・・・
とりあえず、ソースも短くなったし、実行時間も早くなったので、よしとしておきます><

JavaScriptでIEのバージョン判定を行う方法

なにかと手間のかかるIE先輩。
IEのバージョンごとに処理を分けたい場合とかもありますよね。

そんな時に大活躍するコードの紹介です。
使い方は簡単で、以下のコードを用意するだけです。

▼用意するJavaScriptコード

var ie = (function(){
var undef, v = 3, div = document.createElement('div');

while (
    div.innerHTML = '',
    div.getElementsByTagName('i')[0]
);
	 
return v> 4 ? v : undef;
}());

これだけで準備はオッケーです。
使い方は以下です。

▼ブラウザがIEか判別

if(ie) {
    // 処理・・・
}

▼ブラウザがIEじゃないか判別

if(ie === undefined) {
    // 処理・・・
}

▼IE6か判別

if(ie === 6) {
    // 処理・・・
}

▼IE6以上か判別

if(ie > 6) {
    // 処理・・・
}

▼IE8以下か判別

if(ie < 9) {
    // 処理・・・
}

CakePHP1.3 バリデーションしつつAuthのログインPASSを登録する方法

CakePHPには、便利で強力なバリデーションと認証のシステムがあります。
システム構築時にはどちらも使うことになると思うのですが、ユーザーを登録する際には少しコツがいります。

というのは、パスワードに4文字以上15文字以内という文字制限を行う場合、cakePHPはハッシュ化されたパスワードフィールドを元にバリデーションを行うので、期待した結果にはならなくなります。
つまり、『SHA-256』でハッシュ化すると64文字になるので、15文字以内の文字制限にひっかかってしまいます。

これを解決するには、以下のような方法を行います。

結論から言うと、ハッシュ化したいパスワードフィールドと違う名前のフィールドにバリデーションを行っちゃいます。
『password』というフィールドをパスワードに使用しているなら、『pass』を用意しちゃう感じですね。

文章力がないので、例を書いちゃいます。

▼モデル

public $validate = array(
    'username' => array(
        array(
            'rule'    => 'alphaNumeric',
            'message' => '半角英数字で入力してください。',
        ),

        array(
            'rule'    => array('between', 4, 20),
            'message' => '半角英数字、4文字以上20文字以内で入力してください。',
        ),

    // 別名で用意したフィールドにバリデーションを行う
    'pass' => array(
        array(
            'rule'    => 'alphaNumeric',
            'message' => '半角英数字で入力してください。',
        ),

        array(
            'rule'    => array('between', 4, 20),
            'message' => '半角英数字、4文字以上20文字以内で入力してください。',
        ),
);

▼ビュー

echo $form->create('User', array('type' => 'post', 'action' => './add'));
echo $form->inputs(
	array(
		'legend' => 'ユーザー登録',
		'username',
		'pass'
	)
);
echo $form->end('登録');

▼コントローラー

public function add() {
    if(!empty($this->data)) {
        // ここでAuthで使用するパスワードフィールドに値を渡しています
        $this->data['User']['password'] = $this->Auth->password($this->data['User']['pass']);
 
        if ($this->User->save($this->data)) $this->redirect(array('controller' => 'users', 'action' => 'index'));
    }

    $this->data['User']['pass'] = null;
}

これで、ハッシュ化される前の状態でバリデーションを行うことができるます。

JavaScriptでIEと他のブラウザを判別する方法

JavaScriptを書いているとき、IEと他のブラウザで処理を分けたい場合ってありますよね。
UserAgentを調べたりする手もありますが、たった1行でお手軽に判別できる方法を紹介したいと思います。

▼1行でIEなのか判別

var isMSIE = /*@cc_on!@*/false;

if(isMSIE) {
    // IE用の処理を書く
}

『/*@cc_on!@*/false;』の結果がtureだとIEということになります。

『CakePHP2.0.1』がリリースされたんですね

いつの間にか『CakePHP2.0.1』がリリースされたんですね。
最近は仕様書ばっかり書いていたし、PHPが恋しくなってきたので少~しだけ触ってみることにしました。


(『CakePHP2.0.1』は、マルチバイト関係の問題があるらしいので2.0.1は使わずに次のリリースを待つか、最新の2.0ブランチを使うほうが良いみたいです。
詳しくは、【CakePHP2.0.1がリリースされましたが、ちょっと待ったほうがいい】cakephperの日記(CakePHP, MongoDB))


触ってみるにしても、何が変わったのかも良く分からないので、とりあえずCakePHP2.0のマニュアルを読んでみることに。
どうやらCakePHP2.Xは、PHP4は完全にサポート外、PHP5も5.2.6以上になったみたいです。
PHP4を使用してサイトを構築している人の為に、CakePHP1.3.Xの開発もしばらくは続くみたいですね。

ってな感じで、マニュアルを読み進めていくと、『2.0移行ガイド』なるものが。

ファイル名の命名規約がアンダースコアからキャメルケースに、ディレクトリ名の命名規約もキャメルケースになったんですね。
コンポーネントのスーパークラスも『Object』クラスから『Component』になったり、『Authコンポーネント』が書き直されてたり、テスト環境が『SimpleTest』から『PHPUnit』に変更になってたりと、結構な量の変更が。

まあ、今日は2.Xを触ってみたいだけので詳しくは後で見ることにして、実際に動かしてみることにします。

まずは、ダウンロード
いつものようにディレクトリを配置していき、いつものようにアクセス。

すると、いつもの見慣れたトップページが表示されました。
『Security.salt』や『Security.cipherSeed』の変更も1.Xと同じですね。
『/app/Config』に新しくできた『email.php』は、多分Eメールを送る新しいライブラリクラスに関わる設定なんだろうと思います。

ためしに、コントローラーとビューを作成。
ファイル名とディレクトリ名の命名規約がキャメルケースになったのを注意するぐらいで、簡単なコントローラーなどは作成できました。
がっつりしたアプリケーションを開発する場合に、1.Xとの差を感じるんでしょうね。

マルチバイト関係の問題もあるみたいですし、実際の案件で使用するのはもうしばらく先だと思うんで、テストで色々と作成してみよ~。