「String」を含む日記 RSS

はてなキーワード: Stringとは

2012-02-14

そっとうに。

/**
 * そっとうに。
 *
 * そっとうにを置く。
 *
 * @param string $str
 * @return string
 * @see <a href="http://vipsister23.com/archives/5204131.html">とある小学生が書いた詩が哲学的過ぎる件</a>
 */
function sottoUni($str) {
  return 'そっと'    .PHP_EOL
         . $str.'に' .PHP_EOL
         .'うに'     .PHP_EOL;
}

$arr = array('せなか','わたげ','たにま');
foreach($arr as $d) {
  echo sottoUni($d);
}

2011-07-16

[] Symbolについて

RubyのSymbolと文字列の違いを研究室輪講用に書いたのですが,折角なので公開したいと思います

元々学部生に対する輪講用に書いた物なので,若干上から目線ですがご了承ください.

Symbolの意義は何か

文字列とSymbolはよく似ていますプログラマから見ればどちらも文字列です.違いを一言で説明すると『プログラムが扱う』文字列か,『プログラマが見る』文字列かの違いです.例えば変数名は『文字列ですが,rubyオブジェクトである文字列』ではないですよね?

例えば,今あなたC言語お絵描きライブラリを作っているとしましょう.その中に,色で塗りつぶすfillという関数があり,色を青・赤・緑の3色から選べ,fillの引数でそれを指定できるとしましょう.

fillの引数の設定方法として一番単純なのが,0を青,1を赤,2を緑として,0〜2で選択させる方法でしょう.しかし,それでは,どの数値が何色か覚えないといけないし,fill関数を知らない人から見れば,どういう意味引数かすらさっぱり分かりません.

ではどうするかと言えば,普通BLUE = 0, RED = 1, GREEN = 2と適当に定数を設定して,その定数を引数で指定させますよね.

こうして,fill関数引数意味の無い数値から意味のある文字列に変わったことによってプログラムが分かりやすい物となります.さて,ここで注意してほしいのは,ここで言う文字列プログラムが扱うオブジェクトとしての文字列では無いということです.fill関数引数として,"BLUE","RED", "GREEN"などとC言語文字列を渡すということは普通しませんよね.それは,ここで言う文字列は,あくまでプログラマプログラムコードを分かりやすくするために必要な文字列であって,プログラムオブジェクトとして扱う(例えば,長さを求めるとかする)文字列ではないかです

分かってきたでしょうか?

プログラムコード上では(つまりプログラマから見れば)どちらも同じ文字列(文字の列という意味で)ですが,実際に動くプログラムから見れば単なる数値と本物の文字列という大きな違いです.結局,fill関数引数の具体的な値は何でもいいわけですプログラマから見て文字列であればそれだけでよく,プログラムが動くときの実際のその中身は何でもいいわけです.これのために存在するのが,Symbolであり,:fooとひとたびSymbolを作成すれば:fooの実態は適当な数値となります.(この数値がいくらかなんていうことはもちろん気にする必要はありません)

そして,もちろん同じプログラム上では:foo == :fooはちゃんと成り立ちます.もうここまでくれば,Hashのkeyとして文字列でなくSymbolを使う理由が分かりますね.Hashのkeyはあくまで,プログラマが見る(プログラムコードを分かりやすくするための)文字列であってプログラムが扱うオブジェクトとしての文字列では無くて,keyの実際の値は何でもいい,からですね.(特別な場合を除いて)Hashのkeyに対してrubyStringメソッドを使うなんてことは無いですよね.

なぜrubyにはSymbolが存在するのか

しかし,他の軽量言語ではSymbolなどなくHashのkeyとして普通に文字列を使うことが多いです.では,なぜrubyだけSymbolを使うのでしょうか.

その答えは一言でいうと,rubyの(プログラムコード上に直接書かれた,つまりリテラルの)文字列は他の言語と違いimmutable(不変)でない,からです.実際,pythonjavascript文字列(リテラル)は破壊的に変更することはできませんが,ruby文字列破壊的に変更することができます. ('abc'.concat('d')の様に)

これがどういう違いを生むかというと,コード上に直接現れる文字列がimmutable(不変)であるならば,実行時に一つだけそのオブジェクト作成し,後はそれを使いまわすという最適化ができます

そうした時,Hashのkeyの様なプログラマから見た文字列というのは,プログラムコード上のリテラルとして現れるわけですが,これらは実行時に一つだけオブジェクト作成され(特にコード上に現れる同じ文字列は全て一つのオブジェクトにまとめると),それらの比較はそれらに対する参照(そしてこれは大抵メモリアドレスなど単なる数値)の比較で済むので,結局Symbolと同じ様な働きをするわけです

本当はプログラマが見るためだけの文字列だけど,それをオブジェクトとしての文字列としても,Symbolと同じ様な働き,パフォーマンスが得られるならば,別にオブジェクトとしての文字列であってもいいわけです

繰り返しになりますが,プログラマが見るためだけの文字列は,その中身・実態は何でもいいわけですが,その実態がオブジェクトとしての文字列でも十分なパフォーマンスが得られるならば,別にオブジェクトとしての文字列でもいいわけです

さて,rubyに話を戻しますと,rubyコード上に現れる文字列であっても,実行時にそのコードを通る度に毎回新たな文字列オブジェクト作成します.

(以下のプログラムを動かすことで確認できる.)

def foo
  'foo'.object_id
end
p foo, foo

まりrubyでは文字列が可変であるため,先に述べたような最適化ができない(または難しい)ので毎回新たな文字列オブジェクト作成されるのです

こうなると,先ほどの話とはうってかわって,プログラマが見る文字列はその実態は何でもいいのに,それを文字列リテラルrubyオブジェクトとしての文字列)にしてしまうと,毎回毎回文字列オブジェクト作成されてしまうという非常にばかばかしい状況になってしまます.我々はそれらの文字列オブジェクト文字列としての操作は一切施さないのにも関わらず,です

こういうわけで,rubyではプログラマが見るためだけの文字列にSymbolというruby特有のものを使うのです

もちろん,プログラマが見るためだけの文字列を全て定数として(そしてもちろん中身は適当な値で)定義しても構わないわけですが,Hashのkeyとかで数多くのプログラマが見るためだけの文字列が現れることを考えると,とてもじゃないですけどそんなことは面倒でやってられないですよね.ですので,実行時に自動適当な値にしてくれるSymbolというもの存在するのです

以上で,Symbolについての説明を終えます.以下は蛇足です

おまけ

最初の方で出てきたfill関数rubyで実装しようとしたとき,青・赤・緑の各色はその実際の値はなんでもいいのでrubyのSymbolを使って:blue, :red, :greenとしてもいいのですが,ライブラリとかでは大抵ちゃんと定数として定義されていることが多いです

これは恐らく,定数として明示的に定義することで値の存在を明示でき,ドキュメント化の際にも役立つことによっているのでしょう.

Symbolだと,良くも悪くも定義がいりませんから

しかし,あくまでこれは外部に公開するようなライブラリでの話であって,自分が使うちょっとしたプログラムならこういう場面でも精力的にSymbolを使っていってもいいと思います.ちなみに,僕ならSymbolを使います

Symbolだと定義もいりませんし,定数は大文字ですからつのが面倒ですし,あまりソース大文字が入ると見た目がすっきりしません(主観).

Symbolは非常に便利なものですので,その意義・用途を十分に理解して,Hashのkeyにとどまらず様々な所で使えるようになりましょう.

2011-05-30

http://anond.hatelabo.jp/20110530004826

Javaだけど。

class HelloWorld {
  public static void main(String args[])
  {
    System.out.println("Hellp World");
  }
}

typoバグの一種:p

2011-05-19

「これからの「パスワード」の話をしよう」のバグについて突っ込む

Web屋のネタ帳( http://neta.ywcafe.net/ )様の

これからの「パスワード」の話をしよう( http://neta.ywcafe.net/001184.html )で

紹介されているパスワードハッシュ化のバグについて突っ込んでみる

バグといっても大きなものではな

 「1回ハッシュ化を解読できただけ、プレーンパスワードを入手することが可能である

というものである

問題の部分はここ

    /**
     * 平文のパスワードハッシュ&stretchするメソッドです。
     * loop回数は1000としていますが、999でも1001でもお好みでどうぞ。
     * ただしループ回数は処理時間に直結しますのでほどほどの数値で。
     */
    private static final String hashAndStretch(String plainPasswd, String salt) {
        int loop = 1000;
        String hashedPasswd = "";
        for (int i = 0; i < loop; i++) {
            hashedPasswd = DigestUtils.sha256Hex(hashedPasswd + plainPasswd + salt);
        }
        return hashedPasswd;
    }

ここのロジックトレースしてみると

凡例

プレーンパスワードPASSWORD

ソルト:SSSSSSSS

トレース

最終的なハッシュパスワードが「XXXXXXXX」とする

XXXXXXXX ←  DigestUtils.sha256Hex("YYYYYYYY" + "PASSWORD" + "SSSSSSSS")

クラッカーがXXXXXXXXXのハッシュ値を解析し、元の文字列が「YYYYYYYYPASSWORDSSSSSSSS"」と判明したとする。

この時点で元文字列の中にプレーンパスワードが含まれていることになる。

また、ハッシュ化された文字列には「0123456789abcdef」の文字しか含まれておらず、

 「それ以外の文字が含まれていた場合容易にプレーンパスワードはないか

と推測可能である

一般的なパスワードには少なからず「0123456789abcdef」以外の文字が含まれているだろうし、

意味のある言葉パスワードに使っていた場合一目瞭然だ。


上記のことをふまえてプログラムを修正すると。。

    /**
     * 平文のパスワードハッシュ&stretchするメソッドです。
     * loop回数は1000としていますが、999でも1001でもお好みでどうぞ。
     * ただしループ回数は処理時間に直結しますのでほどほどの数値で。
     */
    private static final String hashAndStretch(String plainPasswd, String salt) {
        int loop = 1000;
        String hashedPasswd = DigestUtils.sha256Hex(plainPasswd + salt);;
        for (int i = 0; i < loop; i++) {
            hashedPasswd = DigestUtils.sha256Hex(hashedPasswd + DigestUtils.sha256Hex(salt + i));
        }
        return hashedPasswd;
    }

プレーンパスワードループの外でハッシュ化し、

またソルトを毎回違う値にハッシュ変換することにより

元の文字列の推測を行いにくく修正した

2011-05-18

遺書の代わりのプレイリスト もしくは無人島に持っていくプレイリス

茉莉(昆蟲白)、Happy New-Yearが言いたくて(南野陽子)、一直到底(Nipples)、赤い戦車ヤプーズ)、南方蝶道(甜梅號)、

一個人的水道(甜梅號)、Air on the G stringBach)、春夏秋(チャットモンチー)、激光中(羅文)、Merry Christmas Mr. Lawrence坂本龍一)、

恋愛スピリッツチャットモンチー)、安眠藥(歐陽靖 陳奐仁)、甜蜜蜜(薛凱琪)、MAY斉藤由貴)、ダンシングヒーロー荻野目洋子)、

雙失情人節(Twins)、青山黛瑪(何韻詩)、汽水樽裡的咖啡(何韻詩)、情歌(側田)、when i listen to the field mice(my little airport)、

習慣失戀(容祖兒)、糖不甩(薛凱琪)、VALON-1(Salyu)、戀人未滿(S.H.E)、美空雲雀(何韻詩)

東風Yellow Magic Orchestra)、Lucky(スーパーカー)、我有一段情(吳鶯音)、曙(ゲルニカ)、2EM12_KK_A09(ヱヴァ破)、

光榮之家(何韻詩)、北歐是我們的死亡終站(my little airport)、隆重登場(容祖兒)、電力組曲 C:電化の暮らしゲルニカ)、妮歌(何韻詩)、

Komm, Susser Tod/甘き死よ、来たれ(Arianne )、ホープ(testpattern)、給十年後的我(薛凱琪)、安靜了(S.H.E)、女朋友(歐陽靖 陳奐仁)、

体操YMO)、You Only Live Twice(Nancy Sinatra)、小茉莉楊丞琳)、Oh!(少女時代)、圓謊(容祖兒)、

管他什麼音樂(范曉萱&100%)、Blue Paradise(Martin Denny)、泡泡(魏如萱)、Sunny Road To Salina(Christophe)、Be True(容祖兒)、

しいたそがれ(南野陽子)、最後的歌(楊千嬅)、Le premier chagrin d'amour(France Gall)、眼球綺譚(戸川純ユニット)、愛しのキッズ小島麻由美)、

月世界旅行アポジー&ペリジー)、韻律泳(何韻詩)、飛べない翼(Lily Chou Chou)、手のなるほうへ(チャットモンチー)、ヒステリヤ(ヤプーズ)、

Green Grass Of Tunnel(Mum)、夢伴(梅艷芳)、舊約(何韻詩)、再見...露絲瑪莉(何韻詩)、AXIA~かなしいことり~(斉藤由貴)、

就算世界童話(衛蘭)、점핑(Kara)、夢のスキマ(鷺巣詩郎)、空しき流れ(鷺巣詩郎)、閉塞の拡大(鷺巣詩郎

那年夏天寧靜的海(王心凌)、痛愛(容祖兒)、落寞莉(昆蟲白)、憤怒の河(戸川純)、惚たる蛍(チャットモンチー)、

愛一個上一課(容祖兒)、最後一課(容祖兒)、時不與我(容祖兒)、Dear. Mom少女時代)、男孩像你(薛凱琪)、

沙堡壘(容祖兒)、A Wishful Way(Hopscotch)、ONE斉藤由貴)、拳銃チャットモンチー)、脆弱(謝安琪)、

立つ鳥跡を濁さず(トップをねらえ2!!)、時の河を越えて(トップをねらえ!)、親知らずチャットモンチー)、媽媽我考試考100分(selfkill)、搜神記(容祖兒)、

想想(何欣穗)、リフトの下で逢いましょう(南野陽子)、ギルガメッシュヤプーズ)、Roller Coaster Rock(selfkill)、a love songEGO-WRAPPIN')、

愛將(梅艷芳)、手のなるほうへ(チャットモンチー)、petsounds(the beach boys)、香格里拉(魏如萱)。

2011-03-30

http://anond.hatelabo.jp/20110330125201

というわけでサンプルコード書きなおしてみた。

サンプルコード意味はないので注意な。

JAVA

public class Main {

    public static void main(String[] args) {
        int count= args.length==0?100000:Integer.parseInt(args[0]);

        long start=System.currentTimeMillis();
        Main m=new Main();

        double result=0;
        for(int i=0;i<count;i++){
            result+=m.test((double)(0.1f*i));
        }
        System.out.println(result);
        System.out.println(String.format("COMPLETE! %d msec",System.currentTimeMillis()-start));
    }

    private double product=0;
    public double test(double rad){

        return this.product+=Math.tan(rad);
    }
}

PHP

<?php
class Test{
    private $product;
    public function test($rad)
    {
        return $this->product+=tan($rad);
        
    }
}

$count =is_null($argv[1])?100000:(int)$argv[1];
$start=microtime(true);

$t=new Test();
$result=0;
for($i=0;$i<$count;$i++){
    $result+=$t->test(0.1*$i);
}
echo "{$result}\n";
printf("COMPLETE! %f msec",  (microtime(true)-$start)*1000);

結果

JAVA

$java -jar test.jar 100000
-7.524990063072938E9
COMPLETE! 31 msec

PHP

$ php -f test.php 100000
-11900078829.3
COMPLETE! 209.314108 msec

うむ。有意な差はあるっぽいな。(結果が違い過ぎてるのはなんか問題があるかもしれん)

多分、変数の型が出鱈目で計算されるようなもんだとPHPは遅くなるのだと思われ。javaは強い型制約があるから、同じ型同士の計算だと速いとか?

http://anond.hatelabo.jp/20110330114912

サンプルコード

JAVA

package test;

public class Main {

    public static void main(String[] args) {
        int count= args[0]==null?10000:Integer.parseInt(args[0]);

        long start=System.currentTimeMillis();
        Main m=new Main();
        for(int i=0;i<count;i++){
            System.out.println(m.test());
        }
        
        System.out.println(String.format("COMPLETE! %d msec",System.currentTimeMillis()-start));
    }


    public String test(){


        return "ぽぽぽぽーん";
    }
}

PHP

<?php
class Test{
    public function test(){

        return "ぽぽぽぽーん";
    }
}

$count =is_null($argv[1])?10000:(int)$argv[1];
$start=microtime(true);

$t=new Test();
for($i=0;$i<$count;$i++){
    echo $t->test()."\n";
}

printf("COMPLETE! %f msec",  (microtime(true)-$start)*1000);

結果

$ java -jar test.jar 10000

ぽぽぽ...

COMPLETE! 1008 msec

$ php -f test.php 10000

ぽぽぽ...

COMPLETE! 988.869190 msec

実行したのは全く同じ環境jdkは1.6でPHPは5.2。

どういうことなのか説明してもらおうか?

2011-03-03

ブログの問題を解いてみた

http://okajima.air-nifty.com/b/2011/01/2011-ffac.html

ぷよぷよを解く問題をやってみた

かかった時間はおおよそ1時間

途中でわからないところがあったのでくぐってしまった

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder[] blocks = {
                new StringBuilder("**GYRR"),
                new StringBuilder("RYYGYG"),
                new StringBuilder("GYGYRR"),
                new StringBuilder("RYGYRG"),
                new StringBuilder("YGYRYG"),
                new StringBuilder("GYRYRG"),
                new StringBuilder("YGYRYR"),
                new StringBuilder("YGYRYR"),
                new StringBuilder("YRRGRG"),
                new StringBuilder("RYGYGG"),
                new StringBuilder("GRYGYR"),
                new StringBuilder("GRYGYR"),
                new StringBuilder("GRYGYR")
            };

            bool updated = true;
            while (updated)
            {
            breaked:
                DumpBlock(blocks);
                for (int i = 0; i < blocks.Length; i++)
                {
                    for (int j = 0; j < blocks[i].Length; j++)
                    {
                        char c = blocks[i][j];
                        if (c == '*')
                            continue;
                        updated = false;
                        if (KillBlocks(blocks, i, j))
                        {
                            updated = true;
                            goto breaked;
                        }
                    }
                }
            }
            DumpBlock(blocks);
            Console.Read();
        }
        struct Point
        {
            public int x, y;
            public Point(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }
        static bool KillBlocks(StringBuilder[] blocks, int x, int y)
        {
            bool[,] visted = new bool[blocks.Length,blocks[0].Length];

            MarkBlock(visted, blocks, x, y);

            Queue<Point> queque = new Queue<Point>();
            for (int i = x; i < blocks.Length; i++)
                for (int j = y; j < blocks[i].Length; j++)
                    if(visted[i,j] == true)
                        queque.Enqueue(new Point(j,i));

            if (queque.Count < 4)
                return false;

            while (queque.Count > 0)
            {
                Point p = queque.Dequeue();
                RemoveBlock(blocks, p.x, p.y);
            }
            return true;
        }
        static void MarkBlock(bool[,] visted, StringBuilder[] blocks, int x, int y)
        {
            if (x < 0 || y < 0 || x >= blocks.Length || y >= blocks[0].Length || visted[x, y] == true)
                return;
            char c = blocks[x][y];
            visted[x, y] = true;
            if (x + 1 < blocks.Length && blocks[x + 1][y] == c) MarkBlock(visted, blocks, x + 1, y);
            if (y + 1 < blocks[0].Length && blocks[x][y + 1] == c) MarkBlock(visted, blocks, x, y + 1);
            if (x > 0 && blocks[x - 1][y] == c) MarkBlock(visted, blocks, x - 1, y);
            if (y > 0 && blocks[x][y - 1] == c) MarkBlock(visted, blocks, x, y - 1);
        }
        static void DumpBlock(StringBuilder[] blocks)
        {
            foreach (StringBuilder s in blocks)
                Console.WriteLine(s);
            Console.WriteLine();
        }
        static void RemoveBlock(StringBuilder[] blocks,int x,int y)
        {
            int i;
            if (y == 0)
            {
                blocks[y][x] = '*';
                return;
            }
            for (i = y; i > 0; i--)
            {
                blocks[i][x] = blocks[i - 1][x];
            }
            blocks[i][x] = '*';
        }
    }
}

2011-02-25

if(string.Compare(hoge,hige)){}

if(hoge.CompareTo(hige)){}

こういうのってどっち使うべきなんでしょうか

そういうのをどういう基準で選ぶべきなんでしょうか

2011-02-17

http://anond.hatelabo.jp/20110216205420

Object.ToString();

Objectがnullだと例外発生

結果はそのクラスが持つToString()メソッドに応じる

Object as string;

キャスト出来ない場合はnullが返る

Objectキャスト出来る場合のみ実行したときに、nullかどうかで条件分岐させたり

(string)Object;

キャスト出来ない場合は例外発生

Objectが確実にキャスト出来るなら、asよりちょびっと速いか

2011-02-16

教えてC#

Object.ToString();

Object as string;

(string)Object;


型を変換する方法がいくつも用意されてるけど

どうやって使い分けたらいいの?

2011-02-09

JavaScript の内部関数が便利すぎる件

ちょっとした関数を作る時、一部処理が冗長だなと思っても、

わざわざ外に出して関数化するほどのことでもないよな、とか

この関数からしか呼ばないのに、並列に関数を置きたくないな、とか思うことがあるでしょう。



JavaScript ならこんな思いに見事に答えてくれます

たとえば個人情報が云々なので文字列マスク処理を作ろうとしましょう。

String.prototype.mask = function() {

  var maskedText = "";
  for(var ix = 0; ix < this.length; ix++){
    maskedText += mask1(this.substring(ix, 1));
  }

  return maskedText;

  function mask1(character) {
    var maskedCharacter = "";
    swith(chr) {
     case 数字:
      処理A, 個別処理
     case 英字:
      処理B, 個別処理
     case数字:
      処理A, 個別処理
     case 全英字:
      処理B, 個別処理
     case ひらがな:
      処理C, 個別処理
     case カタカナ:
      処理C, 個別処理
     case 漢字:
      処理D, 個別処理
     default:
      未処理
    }

    return maskedCharacter;
  }
};

こういうメソッドを作った時、処理A、処理B、処理Cは冗長な処理になっているわけです

個別処理があるのでbreakしなければいいや、というわけでもありません。

しかしこの処理A,B,Cはこの関数外に置くような処理でもないわけです

この関数内でしか使いませんし、むしろ使って欲しくないわけです

  function mask1(character) {
    var maskedCharacter = "";
    swith(chr) {
     case 数字:
      shoriA(), 個別処理
     case 英字:
      shoriB(), 個別処理
     case数字:
      shoriA(), 個別処理
     case 全英字:
      shoriB(), 個別処理
     case ひらがな:
      shoriC(), 個別処理
     case カタカナ:
      shoriC(), 個別処理
     case 漢字:
      処理D, 個別処理
     default:
      未処理
    }

    return maskedCharacter;

    function shoriA() { 処理A }
    function shoriB() { 処理B }
    function shoriC() { 処理C }
  }

こう書けるのです

JavaScript で一番好きなのはこの内部関数です

2011-01-15

12時間ほどでTwitter連携webサービスを作った記録

2010年年末から年始にかけて10連休ほどあったので、新しいサイトを作ろうと思い立った。


自分スペック

何を作るか

小遣いを稼げるサイトしたい、とまず思った。

月に1万円だと、毎日コーヒーを飲んでるだけでなくなってしまうので、コーヒー代くらい稼げたらうれしいなあ。じゃあどうする。何を作る?

ということで、まずTwitterを使ったものを作ることにした


テーマ

ひとつジャンルにしぼってツイートをかき集めれば、面白い流れになるんじゃないか。人が来るんじゃないか。そう思った。togetterたいな。で、ジャンルは、個人的に興味がある子育て。ていうか毎日帰宅してから朝まで子どもの寝かしつけや夜泣き対応サイト更新する暇も、俺が寝る暇もあんまりない。ので、手がかからないことが大前提。なんだったら自動更新でもいい。

自動更新かー。と思って「ブログ 自動更新」でググったら、wordpressRSSから更新するプラグインがあるらしいことを知った。はい決定。その瞬間、「TwitterAPIからRSSを引っ張ってwordpress投稿するサイト」に決まった。


やってみた

12時間は実装を初めてから時間になります


1時間

さくらインターネットスタンダードを申し込んだ。14日お試しがあるらしいけど、仮申し込みの時点で住所も入れてコンビニ請求にしたら、数日後に請求書が送られてきてビビった。(同時にドメインも申請しちゃった)

まあ、webで申し込んで、すぐにサーバコントロールパネルという画面に入れるようになった。「クイックインストール」というリンクがあったので見てみたらMovableTypeWordPress自動インストールしてくれるらしかったので、ボタンを押したインストールできましたというので発行されたURLクリックしたけど404だった。1時間くらい404で、その日はもう寝た。


2時間

次の日の夜。これはもう、10連休を利用して毎晩1時間ずつ捻出するしかない、さくらのお試し14日あるから約14時間で作りきるしかねえ、と思った。

サイトアクセスしたwordpressが入ったページが出てきた。おお、サイトができてる!

まずTwitterを調べるか、と思って、「Twitter API」で検索したけどOauth?とかいう面倒なことをしないといけないらしかったのでやめた。じゃあ普通に検索は?と思って「Twitter 検索」で検索したら、search.twitter.comの結果はjsonatomで取得できるし、APIコール制限もないらしいのでこれに決定。検索だけで1時間たった。


3時間

夜も更けて、続けて作業した。「wordpress xml 投稿」で検索していくつか探したらFeedWordpressというプラグインがあったので入れた。あ、事前知識としてMovableTypeでのブログはやったことがあったので、プラグインを入れるみたいな話はスムーズに進められた。

で、twitter検索結果をatomで返した結果を入れてみた。ら、本当に投稿されてた。よっしゃできた、と思った。1ツイートが1エントリになってたし、投稿者もツイートした人になってた。よかった。でも、満足できなかった。


4時間

次の日。同じことを自力でやる方法を探した。「wordpress xml 投稿」で検索して、XMLパースできるようになればいいんじゃないかと思い、simplepieというPHPライブラリにたどり着いた。が、PHPなんてまったく知らないし、憶える気もなかった。actionscriptで書かせてよ、とずっと思ってた。


5時間め・6時間

次の日。「wordpress xml 投稿」でまた検索。どうやらwordpress投稿って、xmlrpcというやり方を使ってるらしかった。ので、「wordpress xmlrpc 自動投稿」で検索したら、なんかサンプルコードが載ってたのでそのまんまコピペ(結局PHPだった)。したらちゃんと投稿されていた。ふむ。ここで何を思いついたのか、「wordpress xml パース」と昨日みたいなことを検索した。simpleXML?というライブラリがあるらしかったので、それを試してみることにした。(たぶんPHPが動いたので気をよくしてたんだと思う)

こういう流れでいけると思った。考え方はactionscriptエディタに書いて、ノリであてにいった。変数に宣言するのはできた。$var1とかで宣言したことになるらしいURLRequestに相当するコードを探したら「file_get_contents」らしいことが分かった。(「PHP 外部ファイル」で検索

で、ゲットしたのはXMLなんだけど、上記検索したかにたまたま書いてあった「simplexml_load_string」というのを使うとXMLパースできそうな気がしたので、ノリで書いたactionscriptでは

var req:String = "http://search.twitter.com/?q.atom=mogemoge";

var r:URLRequest = new URLRequest(req);

var kekka:XML = r.send() as XML; ←いまここ

なので、XMLキャストしたんだろうなみたいな感じだった。E4Xを使えればいいのにPHPって馬鹿ねと思いながら寝た。


7時間

年があけて、3が日が終わりそうだった。年末にやってたこと(上記までのこと)を思い出しながら、XMLの必要な部分だけ抜き出す方法を模索したatomっていってもentryがたくさん入ってたか配列にするんだろうけど、ってんで「php foreach」を検索。なんとなくサンプルコードをまねしながら、記事タイトル、記事本文だけ取得した。あとはxmlrpcのサンプルにあわせて投稿するようにした。できた。寝た。


8時間

次の日の朝、ブログを見た。昨日更新したのしかあがってない。自動じゃねーじゃん。

で、「自動 投稿」で検索したら、クローン(cron)という仕組みを使わないといけないのだった。クローンサーバの仕組みらしく、そういえば俺はPHPをはじめDBサーバという単語を極力さけて仕事してきたので、もう気持ちが悪くなってきた。「さくらインターネット cron php」で検索して、なんとかやり方を見つけて、cronを登録した。(1時間に1回にした。設定は * * * 0)


9時間

仕事から帰ってきて、サイトを見ると、投稿が大量にたまっていた。やった!で、調子に乗ってツイッターアカウントを作った。なんだったらツイッター自動したかったので「twitter bot」で検索した。Easybotterというサンプルボットがあったので使わせてもらった。自動で一行ずつつぶやくようにした


時間外)

サイトテーマを考えてた。通勤電車で悶々とする時間

ツイートを集めることは成功したけど(毎時間100件のツイートを1エントリとして投稿してる)、それを眺めて面白いんだろうか? ボットを動かしてるけど人がくるんだろうか?

そんなとき「trivist」がはてブに載ってた。なんかにたものを感じた。やっぱツイートを引っ張ってきて投稿するサイトはアリなのか?アリなはずだ!


10時間

サイトの体裁を整えた


11時間

trivistをまねて、記事を評価(はてなスターかいいねボタンかにいもの)する仕組みが欲しくなった。「wordpress 評価 プラグイン」で「wp-postratings」というプラグイン発見して、入れてみた。どうやら1エントリーに1評価しかできないらしい。俺のサイトは1エントリーに100ツイートあるから、どのツイートを評価するのかが分からない。

いったん、wordpressの全投稿を削除した。で、cron に登録されてるPHPを、1記事に1エントリーした


12時間

エントリー投稿するついでに、Yahoo日本語解析APIをつかってツイートを分析して、名詞動詞だけを取り出そうと思った。それをタグにすれば、タグクラウドが作れると思った。はてブはずっとずっと昔からやってるからYahoo日本語解析っていうのが2006年くらいに流行ったことをなぜか憶えてたので、やってみた。できた。

なんか俺、PHP書くのが早くなってね?


そして微調整をしながら今に至る

アクセス解析を入れてみた。サイトに来てる人は、俺だけだった。

どうにかして人を増やしたい。サイト広告募集はする気がないしベタベタバナーを貼りたくなかった。みんなが気軽に見に来て、軽い気持ちで評価してくれて、更新を楽しみにしてくれるサイトしたかった。コミュニティサイトじゃないけど、やっぱりサイトコミュニケーション設計をしないと意味がないんじゃないか、見てくれるユーザはどうやったら楽しいんだろう、ということを考え続けて10日ほど経った。Twitter経由で来てくれた人が3人ほどいるようだけど、何がダメなのか分からないので増田にお願い。


ここまで書いて教えてくんじゃねーか、と思われるかもしれないが、ググレカス的な検索は上記で書いたみたいにいろいろやってきた。でも、サイトを作ってみてはじめて、ユーザに向けたサイトってどう作ればいいのかが分からないということに気づいた。

小遣い稼ぎもしたいんだけど、面白いサイトを作るヒントがほしいと思った。

kanzen21やtrivistみたいに、俺も過程を全部さらしたから辛辣意見を求む。そしてはてブされるのを待ってます

http://kosodate-now.com/

2011-01-11

人材獲得作戦・4 試験問題ほか

http://okajima.air-nifty.com/b/2010/01/post-abc6.html

迷路の最短経路を求める問題が出たので解いてみた

幅優先探索を使えばいいのがわかっていたのですんなりかけたのだが無限ループになる個所があったので動くようになるまで時間がかかった


using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace MazeFind
{
    class Point
    {
        public int x;
        public int y;
        public Point before;
        public Point(int x, int y,Point before)
        {
            this.x = x;
            this.y = y;
            this.before = before;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            const char BreakChar = 'B';
            const char GoalChar = 'G';
            const char WallChar = '*';
            const char BeforeChar = '.';

            StringBuilder[] maze = new StringBuilder[]{
                new StringBuilder("**************************"),
                new StringBuilder("*S* *                    *"),
                new StringBuilder("* * *  *  *************  *"),
                new StringBuilder("* *   *    ************  *"),
                new StringBuilder("*    *                   *"),
                new StringBuilder("************** ***********"),
                new StringBuilder("*                        *"),
                new StringBuilder("** ***********************"),
                new StringBuilder("*      *              G  *"),
                new StringBuilder("*  *      *********** *  *"),
                new StringBuilder("*    *        ******* *  *"),
                new StringBuilder("*       *                *"),
                new StringBuilder("**************************"),
            };
            Point start = new Point(1, 1,null);

            //最短経路を探索する
            Queue<Point> queque = new Queue<Point>();
            queque.Enqueue(start);

            while (queque.Count > 0)
            {
                Point now = queque.Dequeue();
                if (maze[now.y][now.x] == BreakChar)
                    Console.WriteLine("break");
                if (maze[now.y][now.x] == WallChar || maze[now.y][now.x] == BeforeChar)
                    continue;
                else if (maze[now.y][now.x] == GoalChar)
                {
                    Point p = now.before;
                    while (p != null)
                    {
                        maze[p.y][p.x] = '@';
                        p = p.before;
                    }
                    break;
                }

                if (maze[now.y - 1][now.x] != '#')
                {
                    queque.Enqueue(new Point(now.x, now.y - 1, now));
                    maze[now.y][now.x] = '.';
                }
                if (maze[now.y][now.x + 1] != '#')
                {
                    queque.Enqueue(new Point(now.x + 1, now.y, now));
                    maze[now.y][now.x] = '.';
                }
                if (maze[now.y + 1][now.x] != '#')
                {
                    queque.Enqueue(new Point(now.x, now.y + 1, now));
                    maze[now.y][now.x] = '.';
                }
                if (maze[now.y][now.x - 1] != '#')
                {
                    queque.Enqueue(new Point(now.x - 1, now.y, now));
                    maze[now.y][now.x] = '.';
                }
            }

            //結果を出力する
            foreach (StringBuilder s in maze)
                Console.WriteLine(s.ToString().Replace(BeforeChar,' '));

            Console.ReadLine();
        }
    }
}
<||

2011-01-09

http://anond.hatelabo.jp/20110109000805

最近は、24インチ 30インチディスプレイなんて安いんだから、横80ではなく横120ぐらいは平気で使える。

classname::enumname という毎回指定でも エディタインテリジェントに保管してくれるから問題ない。

個人的には、毎回、スコープを明示して欲しい

 

基本的に 外部ツールがチェックしてくれるんだから

class{

enum{

{

};

で問題ないと思われ

言い方を変えれば、class内部以外でenum定義することなんて最近はあるのか?グローバルなenumなんて余り無いと思うが・・・

クラス内部では、省略できるし、外部からクラス内部の値を呼ぶときは、どのクラスのこのenumって外部だよって意味で毎回書いたほうが安全だろ?

 

スコープの省略は基本、オススメできない。

using namespace std

ですら、書かないほうが安全 毎回std::って書かないと、うっかり、stringクラス定義する人がいないとは限らんからね・・・

一斉に変更したい? エディタ正規表現で置換すればよろしい・・・

 

原則、外部のツールで解決できる問題は、外部のツールで解決すればいい。

言語仕様拡張されると、初心者に、その理屈を説明するという問題が出てきて、そういうのは初心者には無理。

他方、ツールを使えない初心者でも、毎回コピペや手で置換は出来る。

 

ソーシャルな人を使うという観点から、そういう言語拡張オススメできない。

2010-08-06

なんで・・・どいつもこいつもStringクラスとかを独自で作るんだ?STLにあるものは、STLのを使えよSTLのを・・・

複数のオープンソースとかをまたいでアプリ作るときにStringの載せ替えでメモリコピーが発生とか、泣きたくなる。

とか言うのは有りですか?

2010-07-28

std::copy(v.begin(), v.end(), std::ostream_iterator<string>(std::cout, "\n"));

とか書くやつなんなの

2010-07-24

google発のProtocol Buffersについて

オブジェクトシリアライズツールであるプロトコルバッファについて書きます。

プロトコルバッファって何って方はこちらへ

Protocol Buffers 本家

http://code.google.com/apis/protocolbuffers/

XMLはもう不要!? Googleシリアライズツール「Protocol Buffer」

http://journal.mycom.co.jp/articles/2008/07/18/protocolbuffer/index.html

Protocol Buffers (Protocol Buffers の内部解説記事。とても参考になります)

http://dodgson.org/omo/t/?date=20080712

内容

プロトコルバッファは異種言語間でオブジェクトのやりとりをするための規格です。

独自の言語によりオブジェクトインターフェースを規定することで、多言語対応を行っています。

例えばこんな感じ。

  • address.proto
package tutorial;

message Person {
  required string name = 1;
  required int32 id = 2;        // Unique ID number for this person.
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person person = 1;
}

以上のようなprotoファイルから各言語ソースコード、または何らかのデータ操作ライブラリを使いオブジェクトの処理を行います。

googleによってC++, Java, Python用のライブラリ作成されましたが、他の言語対応したサードパーティー製のライブラリがいくらでもあるので、実質的にほぼすべての言語で使えると言っても過言ではありません。

以下はこのライブラリを使ってみた感想などです。

整数型はVarintという可変長型でバイナリに保存される

数字が多きければ大きいほど、長いバイト長で保存されます。ただし、負数の場合符号ビットが立つ関係で、ほとんど常に変換後のバイト数が最長バイト数(10)になってしまいます。フィールドの型をsint32, sint64で宣言しると、各数値にzig-zags変換が行われるため、負数であってもその値の絶対値で使用バイト数が決まるようになります。

保存されるデータは各メッセージID/型/値のみ

バイナリに保存されるデータは各メッセージID/型/値のみです。なので、同じ定義の二つのメッセージ型は、プロトコルバッファ上では全く同じように扱うことが出来ます。例えば、片方からシリアライズしたデータを、もう片方の型でデシリアライズすることが可能です。

またオブジェクト連続シリアライズ/デシリアライズすることもできます。

継承されたクラスマッピング

すでに存在する継承関係のあるクラスを、Protocol Buffersでシリアライズ/デシリアライズしたい場合は次のようにします。

(Base, Derived はすでに存在するとします)

(ソースコード中になぜか日本語が書けないので、コメントはすべて英語になっています)

message PbBase {
        require int32 id = 1;
        require int32 value = 2;

        require Derived derived = 10; // - Point !!!
}

message PbDerived {
        require string string_value = 1;
}

継承元のメッセージ定義に、継承先のメッセージを持たせます。Base継承するクラスシリアライズ/デシリアライズしたい場合は、PbBaseメッセージを中心に処理を行うことで、比較的簡単に処理を実装することが出来ます。

例えばこんな感じ

Base *Base_DeserializeFrom(PbBase &pbobj)
{
    // Arrange the classes which inherits from Base.
    if (pbobj.has_derived()) {
        return new Derived(pbobj);
    }
    else
    ...
}

class Base {
    ...
    virtual void Base::SerializeTo(PbBase &pbobj) {
        // Set the fields of 'pbobj',
    }
    ...
};

class Derived {
    ...
    virtual void Base::SerializeTo(PbBase &pbobj)
    {
        PbDerived *derived = pbobj.mutable_derived();

        Base::SerializeTo(pbobj);
        // Set the fields of 'derived',
        ...
    }
    ...
};

protoファイルを以下のように書くと、メッセージの扱いが非常に難しくなります。

message PbBase {
        require int32 id = 1;
        require int32 value = 2;
}

message PbDerived {
        required PbBase base = 1; // - Here is the point !!!
        require string string_value = 2;
}

2010-04-20

頭痛

DLRでさ、ホスト側からホストされる側の変数定義できるじゃん。

~.SetVariable(名前, );

みたいなコードでさ。



それでさ、ホストされる側の文字列型がmutableな場合に、ホスト側のStringクラス(immutable)を、ホストされる側の文字列型として扱っていいのか悩むんだよ。

ホストされる側で文字列を変更する操作でエラーになるのは嫌だけどさ(ホストされる側の言語をそれだけで使ってれば絶対に発生しないエラーだから)、読み取りだけでもホストされる側の文字列として使えれば便利かなぁとも思うんだよ。

IronSchemeはどうしてるのかなぁ。

2010-02-13

R基礎文法最速マスター

基礎

外部スクリプトの読み込み

Rコンソールに一行ずつコマンド入力してもいいけど、実際に使うにはテキストファイルコマンドを書いて(ソースコード)一気に実行させる方が楽。

source('hogehoge.R')

hogehoge.Rというのがソースコードを書いたファイルソースファイル)の名前

ライブラリの追加

CRANという、CPANパクリがある。膨大な数のライブラリがあるので、好きなものをインストールするには、

install.packages('hoge',dependencies=TRUE)

とするのが楽。

変数宣言

不要。変数に使える文字も結構多い。日本語でもOK。

> あ<-1
> あ
[1] 1
代入
a<-1
b=2
1->a

どれでもいい。但し推奨されてるのは一番上。Rの人は「束縛」という言葉を使いたがる傾向があるけど、どっちでもいいと思う。

余談だけど、関数引数の中で代入できる、しかもその値をそのあとの引数で使える。これ実は便利。

> sum(a<-1,a)
[1] 2
変数の内容を確認

基本は変数名を入力すれば表示される。

> a
[1] 1
> str(a)
 num 1
> summary(a)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      1       1       1       1       1       1 

最後のsummaryはRっぽい。strっていうのはstringではなくstructの略(だと思ってる)。Rの変数はいくらでも複雑な構造になり得るけど、そのときにぱっと見がわかるように構造を出力してくれる。

ベクトル

Rの基本はベクトル

ベクトルを作る

ベクトルの作り方はいくらでもあるけど、例示するのが早いでしょう。

> x<-1:3
> y<-c(TRUE, FALSE, TRUE)
> z<-c("a","b","c")
> x
[1] 1 2 3
> y
[1]  TRUE FALSE  TRUE
> z
[1] "a" "b" "c"

他にもいっぱいあるし、関数返値ベクトルってこともよくある。

> runif(3)
[1] 0.2200965 0.6391403 0.1089252

一様乱数を三個作った。

ベクトルの要素にアクセス
> x<-letters[1:5]
> x
[1] "a" "b" "c" "d" "e"
> x[2]
[1] "b"
> x[4:5]
[1] "d" "e"
> x[c(1,3,5)]
[1] "a" "c" "e"

こんな感じで、[]の中に添え字でアクセス。1-indexなので注意。2,3番目の例では添え字にもベクトルを使って、複数の要素に一気にアクセスしてる。

ベクトルの要素に代入
> x[3]<-"z"
> x
[1] "a" "b" "z" "d" "e"

でOK。

終わりに

要望があれば続くかも。

2010-01-20

続・id:JavaBlack氏って

http://anond.hatelabo.jp/20100119023114

しょぼい煽りだなあ。

煽りに見えるのかなあ。

優れたIT技術者だからといってなにか役に立つアプリを公開したいという欲があるとは限らない。

そりゃそうですが。

よくできたアプリを公開している人は、定義からして優れたプログラマなわけですが、何も公開しない人は、優れたプログラマかどうかはわからない。

優れたプログラマアプリを公開しているとは限らないですが、公開しない人が優れたプログラマであるとは限らない。

もちろん「優れたプログラマであるとは限らない」だけで、優れたプログラマではないと断定はできないですが、これだけの長期にわたってこれだけ大量のエントリを投下している割に、具体的な技術の話がさっぱりないのはかなり異様に見えます。

昔はコードを少し載せてた。

ちょっと見てみた。

http://d.hatena.ne.jp/JavaBlack/archive/200503

2005年の分をタイトルだけさらってみたけど、コードが載ってるのは上記のStringの結合ネタぐらいのような……もちろんこういう記事はJavaプログラマにとっては(中級異常のプログラマには常識の範疇とはいえ)かなり役に立つ記事だと思うんですよ。でも、その後そういう記事は減少の一方じゃないですか?

このリストJavaやる人なら必須でしょ。このリストを作ってくれてるだけでブログレベルでは十分だと思う。

Javaオブジェクト指向参考書リスト2007年版)http://d.hatena.ne.jp/JavaBlack/20070522/p1

普通ブログ記事として、この記事だけを見たら、悪くないエントリだと思う。

でも、逆に言うとどれも標準的な必読書。内容に関する言及もないので、それこそ本をまったく読まなくても、ネットで評判を調べるだけでこのリストは作れそうだ(JavaBlack氏がこれらの本を読んでないと言っているわけじゃない。邦訳ぐらいは読んでると思う)。

でもさ、普段あれだけ上から目線の偉そうなエントリを連投している割には、ご本人の技術力は、さっぱり具体的には見えてこない。

ブコメだと、(今回の地震の話はさておき)そこそこ好意的なコメントが付くようだけど、そのへんみんなどう思ってるのかな、と思ったわけですよ。

ちょうどシロクマ先生がこんなエントリあげてるけど、

全能感を維持するために「なにもしない」人達

http://d.hatena.ne.jp/p_shirokuma/20100119/p1

JavaBlack氏は、自らの全能感を維持するために、コードを書いたり公開したりしないのかな、という気もちょっとする。

実力を晒さない限りは、馬鹿にされることもないからね。

ええと、ご本人がこれを見ることがあるとしたら、

プログラマならコードで語れ

と言いたいです。JavaBlack氏がまだ求職中なのかどうか知らないけど、もし私がうちの会社の人事権を持っていたとしても、悪いがこの人は採らない。

2010-01-14

http://anond.hatelabo.jp/20100114003544

34分

現役のときに比べて腕が鈍ってるなあ

ソースは汚いよ


同じところを二回訪れないことに注意して、次の状態をキューに入れていけばいいだけ

隣は距離1なのでただのFIFOでいい

重み付きのグラフならpriority queueを使う


dequeなんちゃらの前までが入力で、while の中が重要コード

答えはSとGも塗り潰しちゃったのを出力してる

サンプルの入力で最短距離であることを確認してる


増田できれいにC++を出力するにはどうすればいいんだろう?

#include <map&gt;
#include <string&gt;
#include <iostream&gt;
#include <vector&gt;
#include <iterator&gt;
#include <deque&gt;
#include <set&gt;

using namespace std;
typedef pair<int, int&gt; P;

int dir_x[] = {0,1, -1, 0};
int dir_y[] = {1, 0, 0, -1};

int main() {
  string line;
  vector<string&gt; input;

  while (getline(cin, line)) {
    input.push_back(line);
  }
  const int X = input.size();
  const int Y = input.begin()-&gt;size();

  vector<P&gt; start;
  P goal;
  for (int i = 0; i < X; i++) {
    for (int j = 0; j < Y; j++) {
      if (input[i][j] == 'S') {
        start.push_back(P(i, j));
      }
      else if (input[i][j] == 'G') {
        goal = P(i, j);
      }
    }
  }

  deque<vector<P&gt; &gt; Q;
  set<P&gt; visited;
  Q.push_back(start);

  while (!Q.empty()) {
    vector<P&gt; p = Q.front();
    Q.pop_front();

    if (visited.find(p.back()) != visited.end()) { continue; }
    visited.insert(p.back());

    if (p.back() == goal) {
      for (int i = 0; i < p.size(); i++) {
        input[p[i].first][p[i].second] = '$';
      }
      copy(input.begin(), input.end(), ostream_iterator<string&gt;(cout, "\n"));
      break;
    }

    for (int i = 0; i < 4; i++) {
      P next = P(p.back().first + dir_x[i], p.back().second + dir_y[i]);
      if (input[next.first][next.second] == '*') { continue; }
      vector<P&gt; new_state(p.begin(), p.end());
      new_state.push_back(next);
      Q.push_back(new_state);
    }
  }
  return 0;
}

http://anond.hatelabo.jp/20100113192313

これで40分。

タイムアタックってことでアルゴリズムは全幅探索で書き上げました。

エラーチェック皆無。

A*ならもう5分ほど延びるかな?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Maze
{
    class Program
    {
        // 探索用地図
        static int[,] maze;

        // 始点終点
        static Position Start = new Position(0, 0), Goal = new Position(0, 0);

        static void Main(string[] args)
        {
            //////////////////////////// まずは各行のリストとして読み込み
            string[] inMaze;

            using (var fp = new FileStream(args[0], FileMode.Open, FileAccess.Read))
            using (var iStream = new StreamReader(fp))
                inMaze = iStream.ReadToEnd().Split('\n');

            // 迷路幅
            int height = inMaze.Length;

            // 迷路高さ
            int width = inMaze[0].Length;

            /////////////////////////// 読み込んだ迷路を作業用地図に展開
            maze = new int[width, height];
            for (int y = 0; y < height; ++y)
            {
                string line = inMaze[y];
                for (int x = 0; x < line.Length; ++x)
                {
                    maze[x, y] = line[x] == '*'
                        ? -1
                        : 0;
                    if (line[x] == 'S') Start = new Position(x, y);
                    if (line[x] == 'G') Goal = new Position(x, y);
                }
            }

            // 探索実行
            int dist = Search(maze, Start);

            // 探索結果から最短経路を再現
            Position backTracer = Goal;
            while (dist&gt;1){
                --dist;
                backTracer = backTracer.Nearbys.First(pos =&gt; maze[pos.X,pos.Y] == dist);
                maze[backTracer.X, backTracer.Y] = -2;
            }

            //////////////////// 最短経路こみのアスキー地図に変換
            char[,] outMaze = new char[width, height];

            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    outMaze[x, y] = maze[x, y] == -2
                        ? '$'
                        : maze[x, y] == -1
                            ? '*'
                            : ' ';
                }
            }
            outMaze[Start.X, Start.Y] = 'S';
            outMaze[Goal.X, Goal.Y] = 'G';


            ////////////////////// 結果は標準出力に。
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                    Console.Write(outMaze[x, y]);
                Console.WriteLine();
            }
            Console.ReadLine();
        }

        /// <summary&gt;
        /// 探索する。SG間の道のりを返す(道のり=SGが隣接しているなら1)
        /// </summary&gt;
        private static int Search(int[,] maze, Position Start)
        {
            List<Position&gt; FrontLine = new List<Position&gt;();
            FrontLine.Add(Start);
            int dist = 1;
            for (; ; )
            {
                List<Position&gt; NextFrontLine = new List<Position&gt;();
                foreach (var pos in FrontLine)
                {
                    foreach (var nextPos in pos.Nearbys)
                    {
                        if (nextPos == Goal) return dist;
                        if (maze[nextPos.X, nextPos.Y] == 0)
                        {
                            maze[nextPos.X, nextPos.Y] = dist;
                            NextFrontLine.Add(nextPos);
                        }
                    }
                }
                FrontLine = NextFrontLine;
                ++dist;
            }
        }
    }

    struct Position
    {
        public readonly int X, Y;
        public Position(int x, int y) { X = x; Y = y; }

        public IEnumerable<Position&gt; Nearbys
        {
            get
            {
                return new[]{
                    new Position(X-1,Y),
                    new Position(X,Y-1),
                    new Position(X+1,Y),
                    new Position(X,Y+1),
                };
            }
        }

        public static bool operator==(Position p1, Position p2){
            return p1.X == p2.X &amp;&amp; p1.Y == p2.Y;
        }

        public static bool operator!=(Position p1, Position p2){
            return p1.X != p2.X || p1.Y != p2.Y;
        }
    }
}

2009-10-04

グーグルマップ壁紙にしてみる

10/18 改訂



グーグルマップ航空写真をつなげて一枚にするスクリプト

なお、取得した画像著作権グーグル他各社が保持しています。

ご利用は計画的に私的範囲でどうぞご利用ください。

#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;
use LWP::UserAgent;
use GD;

my $cmdline = join(" ", $0, @ARGV);
my $usage = "usage: $0 -sx=116423 -sy=51603 -ex=116426 -ey=51605 -dx=4 -dy=3 -z=17 -size=300 -get=30 -dir=cache -output=output.jpg -nodebug";
my ($sx, $sy) = (0, 0);
my ($ex, $ey) = (0, 0);
my ($dx, $dy) = (4, 3);
my $z = 17;
my $size = 300;
my $get = 30;
my $dir = "cache";
my $output = "output.jpg";
my $debug = 0;
GetOptions("sx=i" => \$sx, "sy=i" => \$sy,
	   "ex=i" => \$ex, "ey=i" => \$ey,
	   "dx=i" => \$dx, "dy=i" => \$dy,
	   "z=i" => \$z,
	   "size=i" => \$size, "get=i" => $get,
	   "dir=s" => \$dir, "output=s" => \$output,
	   "debug!" => \$debug) or die "$usage\nDied";
if ($ex == 0) {
    $ex = $sx + $dx;
} else {
    $ex++;
    $dx = $ex - $sx;
}
if ($ey == 0) {
    $ey = $sy + $dy;
} else {
    $ey++;
    $dy = $ey - $sy;
}
$sx>0 and $dx>0 and $sy>0 and $dy>0 and $z>0 and $dir and $output
    or die "$usage\nBad arguments";
$dx*$dy > $size and die "Getting too large.";

$debug and print "debug: mkdir $dir\n";
mkdir $dir;
-d $dir or die "can't make dir $dir: $!";

my $base = sprintf("http://khm%d.google.co.jp/kh/v=46&z=%d", int(rand(4)), $z);
my $ua = LWP::UserAgent->new;
printf "now get %d images...\n", $dx*$dy;
for (my $x=$sx; $x < $ex; $x++) {
    for (my $y=$sy; $y < $ey; $y++) {
	my $file = sprintf("%s/%02dz%06dx%06d.jpg", $dir, $z, $x, $y);
	$debug and print "debug: check of $file\n";
	-s $file and next;
	--$get < 0 and last;
	my $req = HTTP::Request->new(GET=>+"$base&x=$x&y=$y");
	$debug and print "debug: fetch from ".$req->uri."\n";
	my $res = $ua->request($req);
	unless ($res->is_success) {
	    print "fail fetch from $file: ", $res->status_line, "\n";
	    next;
	}
	if (open(my $fh, ">", $file)) {
	    $debug and print "debug: write of $file\n";
	    binmode $fh;
	    print $fh $res->content;
	    close $fh;
	} else {
	    print "fail open in $file: $!\n";
	}
    }
}
$get < 0 and print "reach the getting limit, skip after all.\n";

printf "creating %dX%d image...\n", 256*$dx, 256*$dy;
my $image = new GD::Image(256*$dx, 256*$dy);
for (my $x=$sx; $x < $ex; $x++) {
    for (my $y=$sy; $y < $ey; $y++) {
	my $file = sprintf("%s/%02dz%06dx%06d.jpg", $dir, $z, $x, $y);
	$debug and print "debug: check of $file\n";
	-s $file or next;
	$debug and print "debug: read of $file\n";
	my $part = GD::Image->newFromJpeg($file);
	$debug and print "debug: image copy\n";
	$image->copy($part, 256*($x-$sx), 256*($y-$sy), 0, 0, 256, 256);
    }
}
#$image->string(gdSmallFont, 0, 0, $cmdline, $image->colorAllocate(255, 255, 255));
open(my $fh, ">", $output) or die "fail open $output: $!";
$debug and print "debug: write of $output\n";
binmode $fh;
print $fh $image->jpeg();
close $fh;

例えば秋葉原とか

perl gmwall.pl -sx=116423 -sy=51603 -ex=116427 -ey=51606

駅だけとか

perl gmwall.pl -sx=465701 -sy=206420 -ex=465705 -ey=206423 -z=19

使う数値はfirebugなどで拾ってください。

2009-09-29

OOPFizzBuzz

あえてプログラミングゴルフの正反対を目指してみる。

class FizzBuzzProgram{
	public static void main(String args[]){
		for (int i = 0; i++ < 100; ) {
			System.out.println(new Number(i).checkMod3().checkMod5());
		}
	}
}

interface Mod3Mod5Unchecked extends Mod5Unchecked {
	public Mod5Unchecked checkMod3();
}

interface Mod5Unchecked {
	public Object checkMod5();
}

class Number implements Mod3Mod5Unchecked{
	private int no;
	public Number (int no) { this.no = no; }
	public Mod5Unchecked checkMod3() {
		return no % 3 == 0 ? new Fizz(no) : this;
	}
	public Object checkMod5() {
		return no % 5 == 0 ? new Buzz() : this;
	}
	public String toString() { return Integer.toString(no); }
}

class Fizz implements Mod5Unchecked{
	private int no;
	public Fizz (int no) { this.no = no; }
	public Object checkMod5() {
		return no % 5 == 0 ? new FizzBuzz() : this;
	}
	public String toString() { return "Fizz"; }
}

class Buzz {
  	public String toString() { return "Buzz"; }
  }

class FizzBuzz {
	public String toString() { return "FizzBuzz"; }
}
- 転職ならen
- 派遣ならen
4ページ中1ページ目を表示(合計:78件)