メッセージ欄

2010年4月の日記

一覧で表示する

Base64エンコードとデコード
2010/04/25(日) 19:06 C言語はてブ情報 はてブに登録 はてブ数

codetovalueは結局使ってない。
#include	<stdio.h>
#include	<string.h>
#include	<malloc.h>
/* BASE64変換テーブル */
const static char BASE64[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/=";

/* エンコード */
unsigned char* base64Encode(unsigned char *source){

    unsigned char* result = NULL;
    unsigned char buf1,buf2,buf3;
    unsigned char ind1,ind2,ind3,ind4;
    int i,j;
    int size = sizeof(source[0])*strlen(source);
    /* 結果領域 */
    result = calloc(sizeof(char), (size*2)+1);

    /*
    3バイト(24ビット)ごとにデータを、6ビットごと分割
    */
    for( i = 0, j = 0 ; i < size ; i += 3,j += 4){
        /* 文字コード値取得 */
        buf1 = (i < size - 0) ? *(source + i + 0) : '\0';
        buf2 = (i < size - 1) ? *(source + i + 1) : '\0';
        buf3 = (i < size - 2) ? *(source + i + 2) : '\0';
        //printf("文字コード(16進数) %d : %d : %d \n", buf1,buf2,buf3);
        /* 3文字=>4文字へ分解 
           つまり2進表現に直して、6bitずつに分割
        */
        ind1 =                      (buf1 >> 2);// 2bit右シフト
        ind2 = (buf1 & 0x03) << 4 | (buf2 >> 4);// 0x3f は2進数で111111
        ind3 = (buf2 & 0x0f) << 2 | (buf3 >> 6);// 0x0f は2進数で  1111
        ind4 = (buf3 & 0x3f);
        //printf("4分割 %d : %d : %d : %d\n", ind1,ind2,ind3,ind4);
        /* エンコード
           変換テーブルに従いキャラクター文字に変換
        */
        *(result + j + 0) = BASE64[ind1];
        *(result + j + 1) = BASE64[ind2];
        *(result + j + 2) = ( i < size - 1 ) ? BASE64[ind3] : '=';// 端数は=に
        *(result + j + 3) = ( i < size - 2 ) ? BASE64[ind4] : '=';      
    }

    return(result);

}
/* *(source + i + 0) */ 
unsigned char codetovalue(unsigned char c)
{
    printf("%c   @",c);
	if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') ) {
		return (long)(c - (unsigned char)'A');
	}
	else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') ) {
		return ((long)(c - (unsigned char)'a') +26);
	}
	else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') ) {
		return ((long)(c - (unsigned char)'0') +52);
	}
	else if( (unsigned char)'+' == c ) {
		return (long)62;
	}
	else if( (unsigned char)'/' == c ) {
		return (long)63;
	}
	else if( (unsigned char)'=' == c ) {
		return (long)0;
	}
	else {
		return -1;
	}
}
/* デコード */
unsigned char* base64Decode(unsigned char *source){
    unsigned char* result = NULL;
    unsigned char ind1,ind2,ind3,ind4;
    int i,j;
    int size = sizeof(source[0])*strlen(source);
    /* 結果領域 */
    result = calloc(sizeof(char), size + 3);

    for( i = 0, j = 0 ; i < size ; i += 4 , j += 3){
        /* 文字コード値取得 */
        ind1 = *(source + i + 0) == '=' ? 0 : strchr(BASE64, *(source + i + 0)) - BASE64;// codetovalueと同じ
        ind2 = *(source + i + 1) == '=' ? 0 : strchr(BASE64, *(source + i + 1)) - BASE64;
        ind3 = *(source + i + 2) == '=' ? 0 : strchr(BASE64, *(source + i + 2)) - BASE64;
        ind4 = *(source + i + 3) == '=' ? 0 : strchr(BASE64, *(source + i + 3)) - BASE64;
        // printf("4分割 %d : %d : %d : %d\n", ind1,ind2,ind3,ind4);

        /* デコード */
        *(result + j + 0) = (unsigned char)( (ind1 & 0x3f) << 2 | (ind2 & 0x30) >> 4 );
        *(result + j + 1) = (unsigned char)( (ind2 & 0x0f) << 4 | (ind3 & 0x3c) >> 2 );
        *(result + j + 2) = (unsigned char)( (ind3 & 0x03) << 6 | (ind4 & 0x3f) >> 0 );
       
    }

    return(result);
}


main()
{
	char *src = "Hello World";
	char *decoded = base64Encode(src);
    printf("encode :  %s\n", decoded);
    printf("decode : %s\n", base64Decode(decoded));
}

<script>タグから読み込んだjsのディレクトリを取得
2010/04/18(日) 13:21 Javascriptはてブ情報 はてブに登録 はてブ数

<script src="..."> という感じでjsファイルを読み込んで、src部分が
http://example.com/lab/test.js であるとき、
http://example.com/lab/ を自分自身で取り出す方法を模索する。

自分自身のsrcを調べる方法は

とてもシンプルに自分自身が属する script 要素を取得 - IT戦記
http://d.hatena.ne.jp/amachang/20061201/1164986067
で大体いいと思います。 もしくは
var n=document.getElementsByTagName("script");
n[n.length-1].src; // 自分自身のurl
相対パスの場合とか調べてないけど、今回の主題はディレクトリを取り出すとこなので後回し。
Twitterでどういう方法があるのだろうと投げてみたらいろいろな方法が返ってきたので見てみる。

Togetter - まとめ「scriptタグからディレクトリを取得」
に皆さんから言っていただいたものがまとめてあります。
var src = "http://example.com/lab/test.js";
としたとき。
  • lastIndexOfを使う方法
ブラウザ間で差が少なく、比較的早い感じ。
また今回の題材だと、ディレクトリのパスが長いほど有利になるので一番よいかも。
src.slice(0, src.lastIndexOf("/") + 1);
  • split,pop,joinを使う方法
ディレクトリパスだけをとるならpopが少し気になるけど、jsのファイル名もとるならいいのかも。
IEはsplit,joinが苦手だそうで。(そこまで大きな差ではないが)
var a = src.split("/");
var dir = a.pop(); // jsのファイル名
a.join("/") + "/"; // ディレクトリ
  • split,slice,joinを使う方法
なんとなくリズムが好きな書き方。
上と同じくらいの速度。Firefoxは比較的早めになる。
src.split("/").slice(0, -1).join("/") + "/";
  • 正規表現execを使う方法
マッチしたものを取り出す。
Chromeだと正規表現は早いみたい。
/^.+\//.exec(src)[0];
  • 正規表現でreplace
いらない(ファイル名)部分を削ろうって発想
ブラウザ間でばらつく。
src.replace(/[^/]+$/, "");
実際に動かす場合は以下のソース
gist: 369771 - GitHub
http://gist.github.com/369771

実際に使うときはそこまで差が出てくれるわけではないと思うので、好きな方法でいい気がする。

Konnoさんの教科書解
Konno Free Software Blog: #JavaScript: URI.prototype.basename and URI.prototype.dirname properties
http://konno-freesoftware.blogspot.com/2010/04/javascript-uribasename-and-uridirname.html

素数判定
2010/04/11(日) 25:16 Javascriptはてブ情報 はてブに登録 はてブ数

試し割り
  1. 単純に2からその数まで割っていき、割れるのはその数だけとなるのが素数。
全く最適化してない。
function decisionPrime(n){
    for(var i=2,cnt=false;i<n;i++){
        if(n%i==0){
            cnt = true;           
        }
    }
    if(!cnt) console.log(n + " == 素数");
}
for(var j=0;j<30;j++){
   decisionPrime(j) 
}
2で割ったら2の倍数は計算しなくてもいい。

フィボナッチ数列
2010/04/07(水) 26:45 Javascriptはてブ情報 はてブに登録 はてブ数

F(1) = 1
F(2) = 1
F(3) = 2 = 1+1
F(4) = 3 = 1+2
F(5) = 5 = 2+3
という感じで、1と2は例外で>2の時はF(n-1)-F(n-2)の値となる数列

上の式からそのまま導くと以下のような感じ。
function fib(n){
    if(n <= 2){
        return 1;
    }else{
        return fib(n-1) + fib(n-2);
    }
}
for(var i=1;i<10;i++){
    console.log(fib(i));
}
fibを再帰させてる*2なので数字が大きくなるとやばそう。
F(n-1)とF(n-2)は途中で同じ計算をやってるので、毎回やるのはもったいないからキャッシュしてみる。
メモ化というらしい
var fibs = {};
function fib(n){
    if(fibs[n]) return fibs[n];
    if(n <= 2)  return 1;
    return fibs[n] = fib(n-1) + fib(n-2);
}
for(var i=1;i<10;i++){
    console.log(fib(i));
}
404 Blog Not Found:アルゴリズム百選 - フィボナッチ数列にO()を学ぶ
http://blog.livedoor.jp/dankogai/archives/50958771.html

  • Chapter 6. Building Reusability with JavaScript Functions prog*sig azu
    ■6.0  Introduction関数を使う方法には function(){}のようなfunctionキーワードを使った関数宣言 匿名関数(function(){)()} or new Functionを使った関数コンストラクター 関数リテラル or f...

FizzBuzz
2010/04/06(火) 25:03 Javascriptはてブ情報 はてブに登録 はてブ数

fizzbuzzを書いてみる。
  1. 3の倍数はfizz
  2. 5の倍数はbuzz
  3. 3かつ5の倍数はfizzbuzz
  4. それ以外の数字はそのままの数字を出力
1から始めると言うことを忘れがちなので注意。


JavaScriptで書いてみる。
console.log()は勝手に改行するのでjoinでまとめてみる。
function fizzbuzz(n){
    for(var i=1,ary;i<n;i++){
        ary = [];
        if(i%3==0) ary.push("fizz");
        if(i%5==0) ary.push("buzz");
        if(i%5!=0 && i%3!=0) ary.push(i);
        console.log(ary.join(""));
    }
}
fizzbuzz(100);
Javaで
public class fizzbuzz {
    public static void main(String[] args) {
        fizzbuzz(50);
    }
    public static void fizzbuzz(int n){
        for(int i=1;i<n;i++){
            if(i%3==0){
                System.out.print("fizz");
            }
            if(i%5==0){
                System.out.print("buzz");
            }
            if(i%3!=0 && i%5!=0){
                System.out.print(i);
            }
        }
    }
}