プログラマメモ2 - programmer no memo2

目次

正規表現 年月日の漢字削除 2007/08/31

簡単な正規表現だけど。

String s = "2007年08月31日";
s = s.replaceAll("(年|月|日)", "");
System.out.println(s);


結果は、
20070831

java.nio.channels.Selector を止める - 忘れないようにメモ  2007/08/29

忘れないようにメモです。時間があるときにまとめたいです。

ネットワークのデータを待ちうけでこんな感じのコードを書いていました。
※適当です。

ServerSocketChannel server;
server = ServerSocketChannel.open();
server.configureBlocking(false);
server.socket().bind(new InetSocketAddress(host, port));
this.selector = Selector.open();
server.register(selector, SelectionKey.OP_ACCEPT);


while (isGo) {
int n = this.selector.select();
if (n == 0) {
continue; // Nothing to do
}
Iterator i = selector.selectedKeys().iterator();
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
i.remove();
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key
.channel();
SocketChannel client = server.accept();
parseData(client.socket().getInputStream());
client.close();
}
}
}


で、これを止める方法ですが、
まず
isGoをfalseにします。これでループがとまります。

つぎに、
selectorを起こします。起こしますと
selector.select()が動きだして、ループがとまっているので、whileの外にでます。
そしてつぎに、server.socket().close()にしておしまいです。

ですので、isGo,selectorとserverは外部でもつ必要がありますね。

コードはこんな感じ

isGo = false;
selector.wakeup();
server.socket().close();



多分うまくいきます。うごかしてうまくいったレベルなので、説明できないです。

あとで、調べたいと思います。

gspとgroovletの連携方法その1 2007/08/29

groovletとgspがとてもいい感じです。
groovletとgspの連携方法です。

シナリオ

groovletを呼び出して、処理を行いその結果を、gspを利用して表示してください。



web.xmlの設定は以下の感じ
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

<display-name>groooovy</display-name>

<servlet>
<servlet-name>Groovy</servlet-name>
<servlet-class>groovy.servlet.GroovyServlet</servlet-class>
</servlet>

<servlet>
<servlet-name>GroovyTemplate</servlet-name>
<servlet-class>groovy.servlet.TemplateServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Groovy</servlet-name>
<url-pattern>*.groovy</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>GroovyTemplate</servlet-name>
<url-pattern>*.gsp</url-pattern>
</servlet-mapping>

</web-app>


まず、f.groovyというgroovletをよびだして、内部で何かしら処理を行います。
そして、その何かしらの処理結果をrequestに入れて、gspにフォワードします。

f.groovyです。
request.p_p=request.getParameter('o_o')

dispatcher = request.getRequestDispatcher('aaa.gsp')
dispatcher.forward(request, response)


何をしているかといいますと、HTTPのgetで、o_oというパラメータを受け取って、それをrequestにp_pという名前でつめています。

このrequest.xxxと直でプロパティを指定、宣言できるのは、やはりすごいなと思います。
あのまどろっこしいgetter,setterから解放されるだけでも、groovyを使いたくなってしまいます(笑)。
※もちろんgetter,setterのよさはありますが、必ずしも用意しなければいけないものではないはずです。getter,setterの起源って何でしたっけ?カプセル化のためだけ?

次にディスパッチャーを取得して、最後にforwardの実行ですね。
このディスパッチャーの処理を一行ですませればいいなと思います。

最後に、フォワードされた先のGSPです。
<html><head>
<title></title>
</head>
<body>
<% println "${request.p_p}" %>
</body>
</html>


あとgroovyを使うなら、もっと軽やかに変数名をつけたいところですかねー。
javaを使う場合は、IDEなしではコーディングしたくない(できない(笑))ですが、groovyだったらちょこっとテキストエディターを開いてパパパパっと書いてしまいたいですねー。

小数点3桁まで表示 2007/08/29

javaです。

小数点3桁まで表示したい場合です。
BigDecimalのsetScaleでいい感じです。

package decimal;

import java.math.BigDecimal;

public class Test {

public static void main(String[] args) {
double d = 3.789512345678;
System.out.println(new BigDecimal(d).setScale(3, BigDecimal.ROUND_HALF_UP));
}

}


結果は
3.790

それで、丸めるパラーメータはいろいろあるので、試してみるといいでしょう。
やはり、javadocは絶対必要ですね。

ROUND_CEILING
正の無限大に近づくように丸めるモードです。
ROUND_DOWN
0 に近づくように丸めるモードです。
ROUND_FLOOR
負の無限大に近づくように丸めるモードです。
ROUND_HALF_DOWN
「もっとも近い数字」 に丸めるモードです。
ROUND_HALF_EVEN
「もっとも近い数字」 に丸めるモードです。
ROUND_HALF_UP
「もっとも近い数字」に丸めるモードです。
ROUND_UNNECESSARY
要求される演算の結果が正確であり、丸めが必要でないことを表す丸めモードです。
ROUND_UP
0 から離れる
javadoc 1.4


javadocをローカルマシンにインストールしていないjavaプログラマがいましたら、その時点で減点です。

あとメガバイトでbyte[]を表示するためのユーティリティメソッドです。
public static double mbyte(byte[] bs) {
return new BigDecimal((bs.length / 1024.0) / 1024.0).setScale(3,
BigDecimal.ROUND_HALF_UP).doubleValue();
}


参考
小数点第2位以下で四捨五入する / Java(SE) API 逆引き辞典

groovlet + springでちょっと試した。 2007/08/28

groovletがすごくいい感じなので、groovletでしばらく何かつくってみようかと考えていて、springと一緒に使えないかなと考えた。

どういったことを希望しているかというと、
xxx.groovletで呼ばれると、DIで必要なオブジェクトのインスタンスをgroovyに渡してくれるイメージです。

HttpServletResponseならresponse
HttpServletRequestならrequest
って感じで、groovletからは何も考えず使えます。

で、この仕組みはもちろん、GroovyServletが提供してくれています。で、このGroovyServletがgroovyスクリプトを初期化して、ServletBindingなるものを作成します。このServletBindingでresponse,requestとかをgroovletに渡してくれるための処理を行ってくれているようです。

そんな感じで、beans.xmlに定義したbeanをgroovletですぐに使えたら(setter injectionされて)いいなぁとか考えているのですが、調査中です。

で、groovletでspringを利用できるだけでもいいかなぁということで試してみました。

実験手順は、
(1)web.xmlに、リスナーを登録します。

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


springを使うときのお決まりのようです。

(2)web.xmlに、context-paramを設定
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/g.xml
</param-value>
</context-param>


この設定で,applicationContext.xml(beans.xml)のファイルパスを設定するってことですね。
g.xmlというの想定しています。下記のような内容にしてみました。groovyをbeanとして扱っています。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
<lang:groovy id="calc" script-source="classpath:calc.groovy"/>
</beans>


(3)groovletで使用します。
ちょっとまどろっこしい感じがします。
import org.springframework.web.context.WebApplicationContext

def ctx = context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
def calc = ctx.getBean("calc");
calc.p()


ctx.getBeanだけすませたいですが...

springのコンテナを利用して、groovletを生成するのがいいのかなぁと考えています。
おいおい考えていきたいです。

Java7にクロージャー搭載に一票 再び 2007/08/28

Code To Joy: It's Raining Closures

今度は、男性が一票している...


関連
プログラマメモ2: Java7にクロージャー搭載に一票

GZIPOutputStreamではfinish 2007/08/28

GZIPOutputStreamで、出力ストリームにデータの書き込みを終わらせる場合は、
迷わずfinishを使うこと。flushではありませんよ。
と自戒をこめて。2,3時間はこれではまった。

出力ストリームへの圧縮データの書き込みを終了します。このときストリームは閉じられません。複数のフィルタを同じ出力ストリームに連続して適用するときにこのメソッドを使用します。javadoc

SWT_AWT.new_Shellを使う時の注意点 2007/08/27

swtを使用する時の注意点

たとえばJFrameをEXIT_DISPOSEで閉じるにして、その上にDislplayをおいたときに、先にJFrameが閉じると、Displayをdisposeするタイミングを失うので、DO_NOTHING_ON_CLOSEにして、Windowイベントをひろって、display.dispose()したのちに、frame.setVisible(false),frame.dispose()するとうまくいった。

groovletでstatic変数使用してみた。 2007/08/27

groovletでの実験です。

下記のようなコードを用意して動かしてみました。

response.setContentType('text/html;charset=utf-8');

int c = 0

print c++


期待している動作は、表示するたびにカウンタがアップすることです。
groovletのファイルを保存しなおすと、カウンタがクリアされることを望んでいます。

が、結果はそうなりません。

それで、次に、
response.setContentType('text/html;charset=utf-8');

class A{
static int c = 0
}
print A.c++

を試してみましたら、カウンタがアップしていきました!!

groovyでカエルの歌 2007/08/25

どう書く?org
Tiny MML どう書く?orgというお題があったので、思わずアカウントを作成して投稿してみた。

NoteChannelのplayNoteRawメソッドを使用しています。

pitch - MIDI pitch values (0 to 127, 60 is middle C)
velocity - velocity of note, where 0 = silence - note off.
NoteChannel


Note names, MIDI numbers and frequencies

pitchに-1入れて音がたまたまならなかったのですが、本当はもうちょっと丁寧処理したほうがいいのかもしれない。

import quicktime.QTSession
import quicktime.std.music.ToneDescription
import quicktime.std.music.NoteChannel
import quicktime.std.music.NoteRequest

// kaeru_song_player
// cがド、dがレ、eがミ、fがファ、gがソ、aがラ、bがシ、rが休符
def tbl = ['c':60, 'd':62, 'e':64, 'f':65, 'g':67, 'a':69, 'b':71, r:-1]
def song = "cdefedcrefgagfercrcrcrcrcdefedcr"

QTSession.open()
NoteChannel noteChannel = new NoteChannel(new NoteRequest(new ToneDescription(1)))

for(c in song){
noteChannel.playNoteRaw(tbl[c] as int, 60)
sleep(300)
}

QTSession.close()

電子楽器『reactable』 - かっこいい!! 2007/08/25



WIRED VISION / Bjorkもお気に入り、透明ブロックを操作する電子楽器『reactable』(1)

かっこよかったので紹介。

うーん、こんな感じのつくってみたいなぁ

POJに挑戦 - そして挫折... 2007/08/25

このブログの傾向として、たいがい何かにチャレンジして挫折していますね。
しかし、千里の道も一歩から。失敗して立ち上がっていきたい今日この頃です。

POJにチャレンジしてみました。


Short Codingという本を購入して紹介されていたのがPOJでした。

参考:

POJは北京大学の、プログラミングの問題を解いて競うシステムですね。

プロブレム1002に挑戦していろいろ勉強になったので、メモしておきます。
使用して言語は、javaです。

問題は、1002 -- 487-3279です。


この1002ですが、なんとなくできたので、POJでサブミットしたのですが、Time Limit Exceedがでて、失敗。で、この、Time Limit Exceedですが、時間超過というのはわかるのですが、なんでこれがでるのかが、わかってなくて、結構な時間を無駄にしてしまいました。

システムがプログラムにあたえるInputの値を標準入力で処理しないといけないのですが、これをずーとプログラムのほうでブロックして、待ちの状態になっているというふうにまちがって考えていました。

これは、制限時間内に処理ができなかったのは、プログラムのロジックが時間がかかるものであったということだったんですね。Orz...

たとえば、最初に自分がサブミットしたコードは、こんな感じでした。
s = s.replaceAll("-", "").replaceAll("(A|B|C)", "2").replaceAll(
"(D|E|F)", "3").replaceAll("(G|H|I)", "4").replaceAll(
"(J|K|L)", "5").replaceAll("(M|N|O)", "6").replaceAll(
"(P|R|S)", "7").replaceAll("(T|U|V)", "8").replaceAll(
"(W|X|Y)", "9");

文字列をreplaceAllの繰り返しで処理。
しかし、この処理する単位が何万(最大100,000)となればたしかに重くはなるか...

根本的に自分が書いたロジックが重たいということに気がつかず、検討違いのところをずーと調べていたりしたのでした。

で、耐えきれず、Short Codingの本を開きますと1002が紹介されていたので、コードを拝見。
C言語でしたが、ほう、ここまで、やるかという感じだった。かなり自分の試みが恥ずかしくなってしまいました。

参考にしつつ、短いコードを目指しているわけではないので、CのコードをJavaにそのままうつすすのもかっこわるいしなぁと思いながら、だらだらと、サブミットしていて、やはりだめ....

自分で考えるのを放棄して、java風のコードを探しみました。

プロブレム1002のディスカッションのページでjavaのコードをアップしている人がいました。
Detail of message

えーと、なるほどなぁ、うーん、これっなんと言う整列の仕方なんだろう?
自分の、右、左にふっていくんだよね。

いろいろを参考にして作成したのが下記のコード。
一応、Acceptされました。
package p1002;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

public static void main(String[] args) throws IOException {

char[] table =
// A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,
{ '2', '2', '2', '3', '3', '3', '4', '4', '4', '5', '5', '5', '6', '6',
'6',
// P, ,R,S,T,U,V,W,X,Y
'7', '7', '7', '7', '8', '8', '8', '9', '9', '9' };

BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
int c = Integer.parseInt(reader.readLine());

PhoneDictionary root = null;

do {
c--;
String s = reader.readLine();
int len = s.length();
StringBuilder b = new StringBuilder();
for (int i = 0; i < len; i++) {
char cc = s.charAt(i);
if (cc == '-')
continue;
if ('0' <= cc && cc <= '9') {
b.append(cc);
continue;
}
if ('A' <= cc && cc <= 'Z') {
int d = cc - 'A';
b.append(table[d]);
continue;
}
}

s = new String(b);

if (7 != s.length())
continue;

if (root == null) {
root = new PhoneDictionary(s);
continue;
}

root.add(new PhoneDictionary(s));

} while (c != 0);

if (root != null)
root.print();

if (PhoneDictionary.isNoduplicate)
System.out.println("No duplicates.");

}

static class PhoneDictionary {
int times = 1;;
String number;
PhoneDictionary r, l;
static boolean isNoduplicate = true;

public PhoneDictionary(String number) {
this.number = number;
}

public void add(PhoneDictionary phone) {
int i = number.compareTo(phone.number);
if (i == 0) {
times++;
} else if (i > 0) {
if (r != null) {
r.add(phone);
} else {
r = phone;
}
} else if (i < 0) {
if (l != null) {
l.add(phone);
} else {
l = phone;
}
}
}

public void print() {
if (r != null) {
r.print();
}
if (1 < times) {
isNoduplicate = false;
System.out.println(this);
}
if (l != null) {
l.print();
}
}

public String toString() {
return number.substring(0, 3) + "-" + number.substring(3) + " "
+ times;
}
}
}

StreamTokenizerでTT_EOLを取得するには - javadocをみればわかりますが。 2007/08/25

java1.5から導入されたjava.util.Scannerが非常に便利なのですが、System.inから改行を受け取りたい場合、どうも使いづらいことがわかったので、別の方法を模索している最中です。

java.util.Scannerの使い方をちょい研究せねば...

いろいろ調べていて、java.io.StreamTokenizerを使用したことがなかったので試してみました。
このトークナイザーを使えば、簡単なパーサーは楽に作れると思いました。

java.io.StreamTokenizerにはTT_EOLがありました。

行の終わりが読み込まれたことを示す定数です。javadoc1.6


ちなみにこのトークンを受け取るためには、実は、パラメータを設定しないといけません。

javadocには下記のようにあります。

行の終わりをトークンとして処理するかどうかを判別します。flag 引数が true の場合、このトークナイザは行の終わりをトークンとして処理します。行の終わりが読み込まれると、nextToken メソッドは TT_EOL を返し、ttype フィールドにこの値を設定します。

行は、キャリッジリターン文字 ('\r') または改行文字 ('\n') で終わる文字シーケンスです。また、直後に改行文字が続くキャリッジリターン文字は、行末を表す単一のトークンとして扱われます。

flag が false の場合、行末文字は空白として扱われ、その機能はトークンを区切るだけです。
javadoc1.6


これに気がつかず、TT_EOLがとれないことにしばし頭を抱えていました....

以下、参考コードです。

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

public class Test2 {

public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new InputStreamReader(
System.in));
st.eolIsSignificant(true);

while (st.nextToken() != StreamTokenizer.TT_EOF) {
switch (st.ttype) {
case StreamTokenizer.TT_WORD:
System.out.println("Text : " + st.sval);
break;
case StreamTokenizer.TT_NUMBER:
System.out.println("Number: " + st.nval);
break;
case StreamTokenizer.TT_EOL:
System.out.println("EOL: ");
break;
}
}

}

}



ちなみに、人によっては、nextTokenメソッドの返り値を格納して場合がありますが、あまり意味ないです。StringTokenizerのインスタンスには、直で参照できる、ttypeがpubliフィールドとして公開されているからですが、ttpyeの使い方ってjavaオンリーのプログラマは違和感を感じるかもしれませんね。

次に、java.io.StreamTokenizerを利用して標準入力の1行単位で処理を行ってみます。文字列、数字を区別しないようにしみます。

コードはTT_EOLがでてくるまで、StringBuilderに文字をつぎつぎとappendしていき、TT_EOLで出力しています。数字をTT_NUMBERとして処理されてしまうのをふせぐために、ordinaryCharメソッドを使用しています。

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

public class Test2 {

public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new InputStreamReader(
System.in));
st.eolIsSignificant(true);
st.ordinaryChar(' ');
st.ordinaryChar('-');
st.ordinaryChars('0', '9');
StringBuilder builder = new StringBuilder();
while (st.nextToken() != StreamTokenizer.TT_EOF) {

switch (st.ttype) {
case StreamTokenizer.TT_WORD:
builder.append(st.sval);
break;
case StreamTokenizer.TT_EOL:
System.out.println("EOL: " + new String(builder));
builder.setLength(0);
break;
default:
builder.append((char) st.ttype);
break;
}
}

}

}

javaのリリースノート 2007/08/24

javaのリリースノート
いつも探し物迷子になるので、リンクリストを用意しておきます。

groovyでmidi演奏の最初の一歩 - quicktimeを使って 2007/08/23

groovyを使用してmidiで簡単な音を発音してみます。
実は、フィボナッチミュージックというのをみかけて、真似したかったのですが...



上記のサイトでは、javax.sound.midi.*を使用してRubyから音をだしていました。
それで、groovyでコードをまねてみたのですが、音がでない...
調べると、どうもosx上のjavaから標準のパッケージ(javax.sound.midi.*)を使用して音をだすのがしんどうそう(※)だったので、いろいろ調べて回って、appleのquicktimeを使ってみることにしました。
※調べかたがまだまだなのかも。

quicktimeのjavadoc


開発環境はosxなので、quicktime関連は、デフォルトのjavaからすぐにアクセスできましたが、widows環境だと開発環境をつくるところからはじめることになりますね。

簡単なサンプルです。

import quicktime.QTSession
import quicktime.std.music.ToneDescription
import quicktime.std.music.NoteChannel
import quicktime.std.music.NoteRequest

QTSession.open()

def noterequest = new NoteRequest(new ToneDescription(1));
def r = 0..150

for(int i in r){
NoteChannel noteChannel = new NoteChannel(noterequest);
noteChannel.playNote(i, 127);
sleep(30);
noteChannel.playNote(i, 0);
println i
}

r = 150..0
for(int i in r){
NoteChannel noteChannel = new NoteChannel(noterequest);
noteChannel.playNote(i, 127);
sleep(30);
noteChannel.playNote(i, 0);
println i
}

QTSession.close()


参考

groovy メソッドポインタ - printlnとうつのが面倒なときに 2007/08/22

この一ヶ月間、groovyづいています。

groovyにはメソッドポインタという機能があります。名前の通りに、メソッドをポインタ化(!?)して使うってことですね。

def p = System.out.&println
p "test"


printlnとうつの面倒な場合に使えます。

groovy何でもできるなぁ
というか、世のLLといわれている言語群は、こんなに簡単にいろいろな表現ができるんだよね。

groovy 基本ループとか 2007/08/22
2007/08/23

やはりループを押さえておこうということで、




groovyのような言語な柔らかい(!?)言語を使っていくのなら、
ループの書き方を知ったうえで、自分なりのコーディングルールを作っていったほうがよいのかも。

// for 1~100
for (i in 1..100) { println i }
//while 1~99
i = 1
while (i <= 100) { println i; i++ }
//each 1~100
(1..100).each { println it }
//times 0~99
100.times { println it }
// upto 1~100
1.upto(100) { println it }
// step 1~100
1.step(101, 1) { println it }


for (i in 1..100)が好きかもしれない。(1..100).each {}の書き方も好き。
ただ、書いているときはいいのだが、().eash{}はちょっとわかりづらいかもしれない。
なので、やはりjavaでなれたfor( in )を使うようにしようと思う。

100.times
は数字もオブジェクトという感じがしていいかもしれない。でも、timesが回数というのを押さえた上で0からはじまって100回を押さえておく。

upto,stepは自分的には使わないだろうなぁ。

と思って調べていくと、おもしろい使い方発見!!
result = (1..10).step(2).join(',')
println result


まさに、2刻み(step)で動くわけだ。

Rangesは".."で記述する。このRangesはたしかに直感的だよね。
※Rangesは単にRange(s)です。

Rangesの定義を別にループの宣言部分でしなくてもいいわけで。
out = new StringBuffer()
r = 0..10
for(i in r){
out << i
}
println out


このRanges、負からはじめてもオッケーなんだよね。
def r = -7..7
for(i in r){
println i
}


reverse使えば、逆にすることもできますと。
(1..10).reverse().each{
print it;
}


Rangesの使い方こんなのもあるよってことで。
r = "あ".."ん"
for(i in r){
print i
}



参考

groovyからデコンパイラツールのjadをぐるぐるまわしてみる - できはよくない。 2007/08/22
2007/08/23

デコンパイラツールのjadを使うスクリプトをgroovyで書いてみた。
もちろん、groovyである必要はまったくないけど。

にあるサンプルを利用して書くとjadを使っていると途中で固まる現象に出会った。
理由は、なぜかよくわからないけど、どうも標準出力と標準エラーの両方の出力があるとそうなるっぽい。でも、ほんとのところは追求していません。

ちょっとだめった感じのコードは下記のような感じ。
def command = "ジャド"
def proc = command.execute()
proc.waitFor()


って何故このコードでだめなのかよくわからない。

追記:20070823 これはgroovyだからというわけではないです。groovyからは、Runtime.getRuntime().exec(self)とjava.lang.Runtimeを使用しているだけだから。

で、試行錯誤した結果、java5から導入されたProcessBuilderを使用してみてうまく動いた。


ただし、単に使うだけではなく、redirectErrorStreamをtrueにしたのが肝要ぽいです。
java5のjavadocには以下のように書いてありました。

このプロパティが true の場合、このオブジェクトの start() メソッドでそれ以降起動されたサブプロセスにより生成されるエラー出力は、標準出力とマージされます。これにより、Process.getInputStream() メソッドを使って、エラー出力と標準出力の両方を読み取ることができます。マージにより、エラーメッセージと対応する出力との相関を示すのが容易になります。初期値は false です。
javadoc api


あとファイル操作で参考

ディレクトリのファイルを再帰的にとれるのが、eachFileRecurse。
これすごく便利。

いまいちgroovyのStringの操作がよくわかってないので、おいおい練習していこうと思います。

かっこわるいけど、以下groovyコード。
import java.io.*;


if(this.args.length < 0){
println "Usage: decompile_by_jad.groovy [targetdirname]"
System.exit(0);
}

def dir = args[0]


def jad_path = "jad"; // maybe exist current dir....

new File(dir).eachFileRecurse{ f ->

if((f as String).endsWith(".class") && !( (f as String).contains('$') )){
println "=====================================";
println f;

def command = "${ jad_path } -r -o -s java ${f as String}"

try {
println "execute ${ command }";
ProcessBuilder builder = new ProcessBuilder( (command as String).split(' ') );
builder.redirectErrorStream( true );
Process process = builder.start();
InputStream stream = process.getInputStream();
while (true) {
int c = stream.read();
if (c == -1) {
stream.close();
break;
}
}
} catch (e) {
println e;
}
}
}

Java7にクロージャー搭載に一票 2007/08/21

Java7にクロージャー(closure)搭載に一票。

IT-Walker on hatena - Closures Are Hot! 経由です。


いろいろな女性がvote +1って感じですかね。

groovyのSqlでjava.sql.StatementのsetMaxRowsしたい場合 2007/08/21

java.sql.Statementには、setMaxRowsというメソッドが用意されています。

この Statement オブジェクトで作成された任意の ResultSet オブジェクトが含むことのできる最大行数の制限値を、指定された数に設定します。制限値を超えた行は通知なしに除外されます。
java6 doc api


つまり、ResultSetで指定したサイズ以上のデータをもらいませんよ、ということですね。

ところで、groovyのSQLはすんごい便利そうですね。
groovyでSQLしたい場合は、groovyのほうで用意してくれている、Sqlクラスを使用しますが、Sql.newInstanceで生成したこのsqlオブジェクトからどうやってjava.sql.StatementのsetMaxRowsみたいなことするのというはなしですが、えーと、ここでやはり登場するのがクロージャーというわけです。

groovy.sql.SqlにはwithStatementというメソッドが用意されているんですね。教えてもらってなるほどと思った次第なのですが、このメソッドは引数に、Closureオブジェクトをもらいます。

apidocには下記のように記されています。
Allows a closure to be passed in to configure the JDBC statements before they are executed to do things like set the query size etc.
javadoc groovy api

ほーほーなるほどなるほど。

で、JDBC statementが実行される前によばれるよとあります。ってどういうふうに使うのよ、と、この手の言語になれていないと思うわけです。

それで、groovy.sql.Sqlをみてみますと、
0990 /**
0991 * Allows a closure to be passed in to configure the JDBC statements before they are executed
0992 * to do things like set the query size etc.
0993 *
0994 * @param configureStatement
0995 */
0996 public void withStatement(Closure configureStatement) {
0997 this.configureStatement = configureStatement;
0998 }


とあります。

そして、このconfigureStatementがどこで実行されるのかといいますと、protectedメソッドのconfigureで実行されるわけです。もちろんこのconfigureメソッドは、Sqlオブジェクトを操作する人からは直接操作できません。

1252 /**
1253 * Provides a hook to be able to configure JDBC statements, such as to configure
1254 *
1255 * @param statement
1256 */
1257 protected void configure(Statement statement) {
1258 if (configureStatement != null) {
1259 configureStatement.call(statement);
1260 }
1261 }


すんごく感心してしまったんです。
Statementをクロージャに渡してくれるんですね。で、そのStatementを操作するわけです。


肝心の、StatementへのsetMaxRows設定は、
sql.withStatement({statement -> statement.setMaxRows(1000)})

という感じにするんですよね。

さらにgroovyおもしろいなぁと思ったんだですが、何がそんなにおもしろいと思ったのか伝わりましたでしょうか。いやそれとも、こんなの常識!?

参考
Sql Groovy 1.0.jsr06 API Documentation and Javadoc
IBM 実用的なGroovy: GroovyによるJDBCプログラミング - Japan

ビットで表示しましょう。 - いまさらながらですが。 2007/08/21

いまさらながら感がさらに漂いますが、javaでビット表示です。
Integer.toBinaryString
であればこれで変換します。
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE));
とすれば、
1111111111111111111111111111111
と表示されます。

次に0埋め、桁あわせですが、String.formatterが使えるかなぁと思ったんですけど、ちょっとうまくできなくて...

しかたがないので、

public static void p(String s) {
StringBuilder builder = new StringBuilder();
for (int i = s.length(); i < 32; i++) {
builder.append('0');
}
builder.append(s);
System.out.println(builder);
}

とかなんとかします。
ついでに、
public static String toBin(int i) {
return Integer.toBinaryString(i);
}

を用意しておきます。

これで、準備はできたので、
使ってみます。


p(toBin(Integer.MAX_VALUE));
p(toBin(Integer.MIN_VALUE));
p(toBin(-1));
p(toBin(max >> 16));
p(toBin(max >> 8));
p(toBin(max >> 4));



結果は、
01111111111111111111111111111111
10000000000000000000000000000000
11111111111111111111111111111111
00000000000000000111111111111111
00000000011111111111111111111111
00000111111111111111111111111111
となります。

javaのintは32bitで符号付なので、一番左側は符号をあらわしていますね。

全てのビットをたてたい場合は-1ということになるのかな。

ビットをみることができるようになると、ビットの動きがみえるようになると演算子の理解がすすむかと思いましたよ。

javaでは色を表現するのにRGBの値をint(32ビット)で一般的に使用しています。
ではRGBの各成分を取得することを考えてみます。
とりあえず0xffffffffにした値からRGBの成分をとってみます。
下記のようなコードにしてみました。

int i = 0xffffffff;
p(toBin((i & 0xff0000)) );// R成分
p(toBin((i & 0xff00)) );// G成分
p(toBin((i & 0xff)) );// B成分


結果
00000000111111110000000000000000
00000000000000001111111100000000
00000000000000000000000011111111

ちなみに一番左側8バイトはアルファチャンネル(透明度)をあらわしているようです。

p(toBin(0xff000000));
p(toBin(0xff0000));
p(toBin(0xff00));
p(toBin(0xff));


としますと結果は、
11111111000000000000000000000000
00000000111111110000000000000000
00000000000000001111111100000000
00000000000000000000000011111111
です。

うーん、やって思ったのはどうも、0xXXXXXXXXの使い方が自分の直感とそぐわないんですよね。なんでかなぁ。

それで、下記のようにしてみると自分の直感とマッチ
p(toBin(0xff000000));
p(toBin(0x00ff0000));
p(toBin(0x0000ff00));
p(toBin(0x000000ff));


結果は、
11111111000000000000000000000000
00000000111111110000000000000000
00000000000000001111111100000000
00000000000000000000000011111111

ようするに桁があってる感じがすると自分の脳とダイレクトな感じがするからですかね。

論理積 論理和 - いまさらながら 2007/08/21

論理積(&) 論理和(|)を逆におぼえていたことは内緒です。
以下、自分を納得させるための説明です。

論理積(AND(&))は
1に1をかけると1
0に1かけても0
でおぼえています。

論理和(OR(|))は
0に1をたしても1
だから片一方に0がでてきても、その片一方に1があれば、1でおぼえています。

で、
これで、java(javaに限らず)でint値からRGBの値をとるときのおきまりの書き方がわかるわけで、

rgb & 0xff0000

でRの情報がとれるのは、とりたい箇所をffとしてビットを1にして、えーととそれと、欲しいRをかけて存在すればとれるという感じなんですかね。

つぎに、
取得した各RGBの値を一個にするときに、論理和を使うのもなんとなく納得できるかなと。そのときに足すまえに、ビットの位置をうごかすのに、シフトを使って移動させて、足すわけですね。


参考
論理演算
@IT:Javaプログラミング・ワンポイントレクチャー:演算子

グレースケール 2007/08/20


グレースケールです。上記のサイトを参考にさせていただきました。

groovyを使ってピクセル操作しています。
といっても、特にjavaと変わらないコードになってしまっていますが。。。
ちょっとおちついてコードをみなおしていますと、ループの処理に統一がないですね。


1.単純にRGB の平均値を用いる方法

変換後の値 = (R + G + B)/3
で計算します。

下記、groovyコードです。

package fun.g.filter.grayscale;

import fun.g.filter.IFilter;
import com.jhlabs.image.GrayscaleFilter;

public class grayscale implements IFilter{

public int[] filterPixels(int width, int height, int[] pix){

def d = pix;
def dout = new int[width * height];
int p = 0;
(0..<height).each{ y ->
int x = 0;
while(x< width) {
int gray = 0;
int rgb = d[p];
int a = rgb & 0xff000000;
int r = (rgb & 0xff0000) >> 16;
int g = (rgb & 0xff00) >> 8 ;
int b = rgb & 0xff;

rgb = (r + g + b) / 3;
gray = (0xff000000 | rgb << 16 | rgb << 8 | rgb);
dout[p] = gray;
x++;
p++;
}
}

println "ok gray"
return dout;
}

}


2.中間値法 ( middle value )

R、G、B の3つの値は 0 ~ 255 の任意の整数を取るものとし、また値が最大のものを max、最小のものを min とすると、グレースケール変換後の値 Y (値の範囲は 0 ~ 255 の整数とする)は、以下の式で求められます。
Y = ( max + min ) / 2
osakana.factory - グレースケールのひみつ


package fun.g.filter.grayscale;

import fun.g.filter.IFilter;
import com.jhlabs.image.GrayscaleFilter;

public class grayscale implements IFilter{

public int[] filterPixels(int width, int height, int[] pix){

def d = pix;
def dout = new int[width * height];
int p = 0;
(0..<height).each{ y ->
int x = 0;
while(x< width) {
int gray = 0;
int rgb = d[p];
int a = rgb & 0xff000000;
int r = (rgb & 0xff0000) >> 16;
int g = (rgb & 0xff00) >> 8 ;
int b = rgb & 0xff;
int max = (r < g) ? g:r;
max = (max < b) ? b:max;
int min = (r < g) ? r:g;
min = (min < b) ? min:b;
rgb = ( max + min ) / 2;
gray = (0xff000000 | rgb << 16 | rgb << 8 | rgb);
dout[p] = gray;
x++;
p++;
}
}

println "ok gray middle value "
return dout;
}

}


3.NTSC 係数による加重平均法

Y = ( 0.298912 * R + 0.586611 * G + 0.114478 * B )


下記、groovyコード

package fun.g.filter.grayscale;

import fun.g.filter.IFilter;
import com.jhlabs.image.GrayscaleFilter;

public class grayscale implements IFilter{

public int[] filterPixels(int width, int height, int[] pix){

def d = pix;
def dout = new int[width * height];
int p = 0;
(0..<height).each{ y ->
int x = 0;
while(x< width) {
int gray = 0;
int rgb = d[p];
int a = rgb & 0xff000000;
int r = (rgb & 0xff0000) >> 16;
int g = (rgb & 0xff00) >> 8 ;
int b = rgb & 0xff;
rgb = ((r * 0.299) + (g * 0.587) + (b * 0.114 ));
gray = (0xff000000 | rgb << 16 | rgb << 8 | rgb);
dout[p] = gray;
x++;
p++;
}
}

println "ok NTSC Coef. method"
return dout;
}

}



4.HDTV 係数による加重平均と補正

X = 2.2

R = ( R ^ X ) * 0.222015
G = ( G ^ X ) * 0.706655
B = ( B ^ X ) * 0.071330

Y = ( R + G + B ) ^ ( 1 / X )


以下、groovyコード。


package fun.g.filter.grayscale;

import fun.g.filter.IFilter;
import com.jhlabs.image.GrayscaleFilter;

public class grayscale implements IFilter{

public int[] filterPixels(int width, int height, int[] pix){

def d = pix;
def dout = new int[width * height];
int p = 0;
(0..<height).each{ y ->
int x = 0;
while(x< width) {
int gray = 0;
int rgb = d[p];
int a = rgb & 0xff000000;
int r = (rgb & 0xff0000) >> 16;
int g = (rgb & 0xff00) >> 8 ;
int b = rgb & 0xff;

double X = 2.2;
// groovy's pow is **
// r ^ X, g ^ X, b ^ X
r = (r ** X) * 0.222015
g = (g ** X) * 0.706655
b = (b ** X) * 0.071330
rgb = (r + g + b) ** ( 1 / X );

gray = (0xff000000 | rgb << 16 | rgb << 8 | rgb);
dout[p] = gray;
x++;
p++;
}
}

println "ok ITU Coef. method"
return dout;
}

}

アトキンソンのディザリング - 再挑戦 でもだめ 2007/08/19




一番上がjava版で作成したもの。
その次が、Tinrocket, LLC | HyperDitherで作成したもの。

なんとなく近いかなぁと思ったんだけど。
HyperDitherの設定はcontrastをonにしている。

1. Start with a standard stochastic dithering algorithm.
2. Propagate only 3/4 of the total error term.
3. Propagate the error to the neighbors as follows:
Tinrocket, LLC | Programming:Computer Graphics


の説明がすべてのような気もするのだけど、画像処理についてよくわかっていないので、どうも理解できていないです。

コードは、javaでベースのGUIを組んで、毎回、コンパイルするのがいやなので、画像フィルターの部分をgroovyにしたら、めちゃくちゃ遅くなってしまった。もちろん、groovyだけのせいではないです。

コードを掲載したいのだけども、自分でも理解してないので、
一部だけ、

if (x < width - 1)
d[p + 1] += (err * 1) / 8;
if (x < width - 2)
d[p + 2] += (err * 1) / 8;
if (x > 0 && y < height - 1)
d[(p - 1) + width] += (err * 1) / 8;
if (y < height - 1)
d[p + width] += (err * 1) / 8;
if (x < width - 1 && y < height - 1)
d[p + width + 1] += (err * 1) / 8;
if (y < height - 2)
d[p + width + width] += (err * 1) / 8;


画像処理知ってる人なら、ぱっぱっぱっとやってしまえるんだろうけど。

参考

関連

バグと呼ばれている何か。 2007/08/18



命題の「あらかじめ用意しておいた正解」が存在し得ないように、プログラムの「あらかじめ用意しておいた正解」などない。あるとすれば、それは単純すぎる解で、バグ撲滅には全く役に立たない。そんなつじつま合わせから、ズルリと抜けるのがバグと呼ばれている何かである。
Inemuri nezumi diary(2007-07-25)


上記の文章にぐっときたので、メモ。

特定のクラスを格納している JAR ファイルを発見するgroovyスクリプト 2007/08/18


特定のクラスを格納している JAR ファイルを発見するRubyスクリプトを公開している人がいたので、勉強をかねて、groovyにしてみました。

オリジナルのほうはjarコマンドを使用してjarの中のエントリーから見つけ出したいクラスをひっぱてきていましたが、どうせgroovyにするならばというわけで、JarFileクラスを使用してみました。

ちょっと調べきれていないのが、groovyでtoStringしなくてもすむならtoStringしないで文字列で取り扱う方法ですかね。

import java.util.jar.JarFile;

if(this.args.length < 2){
println "Usage: findjar.groovy [classname] [dirname]"
System.exit(0);
}

def classname = args[0]
def dirname = args[1]

classname = classname.replaceAll("¥¥.", "/")

new File(dirname).eachFileMatch(~".*.jar" ){
jarfile ->
new JarFile(jarfile).entries().each({ line ->
if(line.toString().contains(classname)){
println "${jarfile}:${line.toString().replaceAll('/', '¥¥.').replaceFirst('¥¥.class$', '') }";
}
});
}



以下Rubyについてのメモです。
------
rubyのgsubは
gsub(pattern, replace)
らしい。

Dir.glob(pattern)
は、パターンにマッチしたファイルを取得するものらしい。ない場合は空の配列を返す。
パターンにマッチするファイルがない場合は空の配列を返します。

rubyのString#chompは、
文字列の末端の改行を削除します。
逆引きRuby - 文字列
if 文字列.include? other
end
という感じなる。
文字列にそれ含んでる?という問いかけになる感じ。

rubyのinclude?(other) は、
other が範囲内に含まれている時に真を返すらしい。


--
groovyもjava同様、配列の長さをlenghtで、Listの長さはsizeでとれるのですが、
両方でlength,size使えたらうれしいかもしれない。

関連

css 見落としがちなので、メモ 2007/08/18


見落としがちなので、メモ
デフォルトではフォームの下端に余白ができるのでCSSで消す。
全ての要素の余白は“ * {margin:0; padding:0;} 初期化
フォームのサイズはCSSでピクセル単位がいいのかも。

ちなみに、* {margin:0; padding:0;} はちょっとはやっていないらしい。

Paul Grahamのサイト 2007/08/17



現時点でのグーグルページランクが7でした。

DSL - domain specific language 2007/08/17



現時点でのwikipediaの説明はあんまりおもしろくないなぁという感想をもったことは別にして、DSLはえーとキーワードとして頭にいれておこう。



こっちのほうが俄然おもしろなぁ。

JavaやC#よりもSmalltalkやRubyのほうがなぜ楽しいかなんて、口では絶対表せないよなーといつも思います。よく言われるのは、静的型言語と動的型言語の違いですけども、これはあるポイントを見逃しています。「言語内DSLに合うか合わないか」ほうが、本質的な違いだと思います。Martin Fowler's Bliki in Japanese - ドメイン特化言語


DSLとはあまり関係ないところでの感想ですが、使って楽しいという言語はすごいよなぁ。

話かわって、


Rubyの
Time.now.tomorrow.midnight

が紹介されていましたが、たしかにかっこいいと思わずおもってしまいましたよ。

DSLは、ちょっとしたキーワードだということで。

JavaScriptと二重否定 2007/08/17



prototype.jsでの二重否定が紹介されていたので、おもしろいと思ったので、実行できるようにしてみました。
注目したいのは!!という二重否定です。
スクリプトを入力欄:


実行をクリックすると上記の入力したスクリプトが実行されます。
実行

 

RFC 4180対応版 CSVレコードの分解 - 精進しないと。 2007/08/14
2007/08/17

RFC 4180対応版 CSVレコードの分解 どう書く?org

あとで書く。

うーん、しばらく暇つぶしにことかかないなぁ

いろいろな人の回答みたのですが、みなさんコンパクトですね。
自分のJava版だとサイズが大きいなぁ

参考
Comma-Separated Values - Wikipedia
RFC 4180 Common Format and MIME Type for Comma-Separated Values (CSV) Files

2007-08-16 その2



アプローチはきわめてオーソドックスだと思います。
コンパイラの本とかのはじめのページあたりででてくる、字句解析の感じを目指しています。

トークンクラスです。
package csv;

public class Token {
TT type;
private StringBuffer val = new StringBuffer();

public Token build(TT type) {
this.type = type;
return this;
}

public void append(int ch) {
this.val.append((char) ch);
}

public void append(String s) {
this.val.append(s);
}

public String toString() {
return "type:[" + type + "] val:[" + val + "]";
}
}


トークンタイプのクラスです。enum使ってます。
package csv;

public enum TT {
EOF("EOF"), FIELD("FIELD"), COMMA("COMMA"), CRLF("CRLF");

String s;

TT(String s) {
this.s = s;
}

public String toString() {
return s;
}
}


CSVトークナイザーという名前にしました。
whileの部分のstateは状態遷移図に起こしやすことを目指してます。が、厳密ではないので、あとで直します。

package csv;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackReader;
import java.io.StringReader;

public class CSVTokenizer {

PushbackReader reader;

static final int DQUOTE = '"';
static final int COMMA = ',';
static final int EOF = -1;
static final int CR = '\r';
static final int LF = '\n';

public CSVTokenizer(String s) {
this.reader = new PushbackReader(new BufferedReader(new StringReader(s)));
}

public CSVTokenizer(InputStream inputStream) {
this.reader = new PushbackReader(new BufferedReader(new InputStreamReader(inputStream)));
}

public Token token() throws IOException {

int state = 0;

Token token = new Token();
loop: while (true) {
int ch = read();

switch (state) {
case 0:
/*
* -- START --
*/
if (ch == EOF) {
return token.build(TT.EOF);
}

if (ch == DQUOTE) {
state = 2;
token.type = TT.FIELD;
break;
}

if (ch == COMMA) {
// empty field
token.append(ch);
return token.build(TT.COMMA);
}

if (ch == CR) {
state = 4;
break;
}

state = 1;
token.type = TT.FIELD;
// break しない
case 1:
/*
* -- non-escaped --
*/
if (ch == EOF || ch == CR || ch == LF) {
unread(ch);
return token;
}

if (!isTextdata(ch)) {
unread(ch);
return token;
}

token.append(ch);
break;
case 2:
/*
* -- escaped(double quote) --
*/

if (ch == EOF) {
return token.build(TT.FIELD);
}

if (ch == DQUOTE) {
ch = read();
if (ch == DQUOTE) {
token.append("\"");
state = 2;
break;
}
unread(ch);
return token;
}

token.append(ch);
break;

case 3:
/*
* -- escaped(single quote) --
*/

break loop;

case 4:
if (ch == LF) {
return token.build(TT.CRLF);
}
if (ch == EOF) {
return token.build(TT.EOF);
}
default:
break loop;
}
}

return token;
}

boolean isTextdata(int ch) {
if (notEq(ch, '\r') && notEq(ch, '\n') && notEq(ch, '"')
&& notEq(ch, ',')) {
return true;
}
return false;
}

int read() throws IOException {
if (reader != null)
return reader.read();
return -1;
}

boolean notEq(int l, int r) {
return (l != r);
}

void unread(int ch) throws IOException {
if (reader != null && ch != -1) {
reader.unread(ch);
}
}

public void close() {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}

}
}
}


テスト書かないときちんと動いているかわからないですね。

2007-08-16 その1


最初の試み。その2をあとで書こう。全然厳密ではない。
まず、トークンに分けて、トークンを処理するという流れで。
package csv;

import java.io.IOException;
import java.io.PushbackReader;
import java.io.StringReader;

public class A {

public static void main(String[] args) throws IOException {
a();
}

public static void a() throws IOException {
String s;
CSVTokenizer tokenizer = new CSVTokenizer("aaa");
print(tokenizer);
System.out.println("-------------");
tokenizer = new CSVTokenizer("aaa,bbb,ccc");
System.out.println("-------------");
print(tokenizer);
tokenizer = new CSVTokenizer("aaa,bbb,ccc\r\n");
System.out.println("-------------");
print(tokenizer);
tokenizer = new CSVTokenizer(" aaa , bbb , ccc \r\n");
System.out.println("-------------");
print(tokenizer);
tokenizer = new CSVTokenizer("日本語, bbb , ccc \r\n日本語2, bbb2 , ccc2");
System.out.println("-------------");
print(tokenizer);
System.out.println("------------- check double quote.");
tokenizer = new CSVTokenizer("\"日本語\",\" bbb \",\" ccc \r\n日本語2\", bbb2 , ccc2");
print(tokenizer);
System.out.println("------------- ");
s = "\"日本語\",\" bbb \",\" ccc \r\n日本語2\", bbb2 , ccc2\r\n二行目aaa,二行目 bbb, \"二行目ccc \"\"OK OK \"";
System.out.println(s);
tokenizer = new CSVTokenizer(s);
print(tokenizer);
}

static void print(CSVTokenizer tokenizer) throws IOException {
Token token = null;
do {
token = tokenizer.token();
System.out.println(token);
} while (token != null && token.type != TT_EOF);

}

static final int TT_EOF = -1;
static final int TT_FIELD = 0;
static final int TT_COMMA = 1;
static final int TT_CRLF = 2;

// --
static final int DQUOTE = '"';
static final int COMMA = ',';
static final int EOF = -1;
static final int CR = '\r';
static final int LF = '\n';

static class Token {
int type;
private StringBuffer val = new StringBuffer();

public Token build(int type) {
this.type = type;
return this;
}

public void append(int ch) {
this.val.append((char) ch);
}

public void append(String s) {
this.val.append(s);
}

public String toString() {
return "type:[" + type + "] val:[" + val + "]";
}
}

static class CSVTokenizer {
PushbackReader reader;

public CSVTokenizer(String s) {
this.reader = new PushbackReader(new StringReader(s));
}

public Token token() throws IOException {

int state = 0;

Token token = new Token();
loop: while (true) {
int ch = read();
// if(ch == -1) System.exit(0);

switch (state) {
case 0:
/*
* -- START --
*/

if (ch == EOF) {
return token.build(TT_EOF);
}

if (ch == DQUOTE) {
state = 2;
token.type = TT_FIELD;
break;
}

if (ch == COMMA) {
// empty field
token.append(ch);
return token.build(TT_COMMA);
}

if (ch == CR) {
state = 4;
break;
}

state = 1;
token.type = TT_FIELD;
// break しない
case 1:
/*
* -- non-escaped --
*/
if (ch == EOF || ch == CR || ch == LF) {
unread(ch);
return token;
}

if (!isTextdata(ch)) {
unread(ch);
return token;
}

token.append(ch);
break;
case 2:
/*
* -- escaped(double quote) --
*/
if (ch == DQUOTE) {
ch = (char) reader.read();
if (ch == DQUOTE) {
token.append("\"");
state = 2;
break;
}

unread(ch);
return token;
}

if (ch == EOF) {
unread(ch);
return token.build(TT_FIELD);
}

token.append(ch);
break;

case 3:
/*
* -- escaped(single quote) --
*/

break loop;

case 4:
if (ch == LF) {
return token.build(TT_CRLF);
}
if (ch == EOF) {
return token.build(TT_EOF);
}
default:
break loop;
}
}

return token;
}

boolean isTextdata(int ch) {
if (not(ch, '\r') && not(ch, '\n') && not(ch, '"') && not(ch, ',')) {
return true;
}
return false;
}

int read() throws IOException{
if(reader != null) return reader.read();
return -1;
}
boolean not(int l, int r) {
return (l != r);
}

void unread(int ch) throws IOException{
if(reader != null && ch != -1){
reader.unread(ch);
}
}
}
}

油売り算 モデル検査ツールというもので解いているらしい - あとでやってみよう。 2007/08/14

ヒビルテ(2007-07-10)

サンタクロース問題 - あとでやってみよう。 2007/08/14

サンタクロース問題 - * お題

行列の回転 - zip関数!! groovyでやってみた。 2007/08/14
2007/08/18

ありました。


/*
* function name is renamed!!
* original name is transpose.
* this function original implementation
* http://archive.groovy.codehaus.org/user/46B2E788.8040208%40asert.com.au
*/
def zip(Object[] listOfLists) {
def returnValue = []
if ((listOfLists == null) || (listOfLists.size() == 0))
{return returnValue}
def length = listOfLists.collect {item -&gt; item.size()}.min()
for (i in 0..&lt;length) {
def item = []
for (list in listOfLists) {item &lt;< list[i]}
returnValue &lt;< item
}
returnValue
}

def rotateR90(m){
zip(m[2], m[1], m[0])
}

def m = [ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]

println rotateR90(m);


一応できてるっぽい。

実は、全然オリジナルのコードではないです。
Orz...

以下、説明。


他の人の解答をみていて、zipという関数(メソッド?)への言及をみて、はじめわからず調べていきますと、rubyにはzipというのがありました。

self と引数に渡した配列の各要素からなる配列の配列を生成して返します。生成される配列の要素数は self の要素数です。
Rubyリファレンスマニュアル - Enumerable


collectメソッド、mapメソッドは配列の各要素に対してブロックを実行し、結果を配列で返却します。それぞれ、破壊的メソッドcollect!、map!が用意されています。
逆引きRuby - 配列


で、さらに、groovyを調べていきますと、メーリングリストで、
pythonにzip関数があるがgroovyにそれ相当のものがあるかというものでした。
適当にスレッドをおいかけていきますと、
transposeという関数を実装した人がいましてそれを利用してみました。

というわけで、探す労力だけで、全然、脳力を使っていないOrz...

ちなみに、haskellにもありますね。



いい勉強になりました。

Prologのインストール - ようやくうまくいった。 2007/08/13
2007/08/16

環境ができたのでようやくスタート地点



swiplの使い方は本家で...
SWI-Prolog's Home

ようやく油売り算をうごかせた。


2007-08-15


mac portsが期待通りに動いてくれないので、/optをリネームして退避させて、再度インストール。
そして、port selfupdateでエラーが...

いつも環境構築で迷子になるなぁ。

別にselfupdateにこだわる必要はないのだけども、多少、気持ち悪いのでグーグルさんにお尋ねすると、
mac portが1.5なら別にselfupdateしなくてもいいんじゃないとかいうのを読んで、いい加減あきらめました。

Nabble - MacPorts - Users - Can't use rsync port

で、再度、
sudo port install swi-prolog

でインストール。

2007-08-14


油売り算を解いている人のコードをいろいろみてまわっていまして、
油売り算(Prolog) by Inquisitor
のPrologのコードを実行してみたかったので、osxにmac portを使ってswi-prologをインストールにチャレンジ。

参考
rubyneko - Prologはじめてみた(1) インストールからHello, Worldまで

sudo port isntall swi-prolog

で行おうとして失敗...何故だろう。

Prolog は論理型言語という種類の言語だそうです。

ちなみにeclipseのプラグイン
Prolog Plugin - IDE Eclipse for Prolog
余力があればインストールして使用してみたいと思います。

参考
prolog
Reversi in GNU prolog -- MAYAH.JP
M.Hiroi's Home Page / Prolog Programming

mac osx ports
FrontPage - MacPortsWiki-JP
HowTo/UseMacPorts - MacPortsWiki-JP

油売り - その1 2007/08/12

とりあえず油売りに挑戦

Karetta|キミならどう書く 2.0 - 2007 - その 1

あとで、その2を書こう。

package abura;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class C {

public static void main(String[] args) {

new C().aburauri(10, 7, 3);

}

/**
* <p>
* 油を等分にして、売ります。
* </p>
*
* @param a
* 升の上限値を指定します。この升に最初に油が入ります。
* @param b
* 升の上限値を指定します。
* @param c
* 升の上限値を指定します。
*/
public void aburauri(int a, int b, int c) {
this.a = new Masu("a", a, a);
this.b = new Masu("b", b, 0);
this.c = new Masu("c", c, 0);

if (!pre_cond_check(this.a, this.b, this.c)) {
throw new RuntimeException("oh no");
}

move(this.a, this.b, this.c);
}

static void move(final Masu a, final Masu b, final Masu c) {
class Row {
int col1;
int col2;
int col3;

Row(int c1, int c2, int c3) {
this.col1 = c1;
this.col2 = c2;
this.col3 = c3;
}

boolean isOk(int c1, int c2, int c3) {
if (col1 == c1 && col2 == c2 && col3 == c3)
return false;
return true;
}

public String toString(){
return "[" + col1 + ", "+ col2 + ", " + col3 + "] ";
}
}
class CheckTable {
List<Row> list = new ArrayList<Row>();

boolean checkMemo() {
Iterator<Row> iterator = list.iterator();
while (iterator.hasNext()) {
if (!iterator.next().isOk(a.size, b.size, c.size)) {
System.out.println("this condition already appered!!");
return false;
}
}
return true;
}

void memo() {
list.add(new Row(a.size, b.size, c.size));
}

boolean trial(Masu f, Masu t) {
System.out.println(f.name + " -> " + t.name);
// fromのサイズがないので移動できない
if (f.size == 0)
return false;

// 移動許容サイズ
int m_s = t.limit_size - t.size;
System.out.println(f.size + "<= " + m_s);

// 移動先の許容サイズがない
if (m_s == 0)
return false;

//
if (f.size - m_s < 0){
int tmp = f.size;
t.size += f.size;
f.size = 0;
if (!checkMemo()) {
// もとにもどす。s
f.size = tmp;
t.size -= tmp;
return false;
}
return true;
}

if (f.size < m_s) {
f.size -= f.limit_size;
t.size += f.limit_size;

if (!checkMemo()) {
// もとにもどす。s
f.size += f.limit_size;
t.size -= f.limit_size;

return false;
}

return true;
}

f.size -= m_s;
t.size += m_s;

if (!checkMemo()) {
// もとにもどす。s
f.size += m_s;
t.size -= m_s;
return false;
}

return true;
}
void remove(){
list.remove(list.size() - 1);
}
}
CheckTable guard = new CheckTable();
int now_exec = 0;
int skip = 0;
while (true) {
guard.memo();
System.out.println(a + " " + b + " " + c);
if (check_goal(a, b, c))
break;

if (!(skip == 1) && guard.trial(a, b)) {
now_exec = 1;
skip = 1;
continue;
}

if (!(skip == 2) && guard.trial(a, c)) {
now_exec = 2;
skip = 2;
continue;
}

if (!(skip == 3) && guard.trial(b, a)) {
now_exec = 3;
skip = 3;
continue;
}

if (!(skip == 4) && guard.trial(b, c)) {
now_exec = 4;
skip = 4;
continue;
}

if (!(skip == 5) && guard.trial(c, a)) {
now_exec = 5;
skip = 5;
continue;
}

if (!(skip == 6) && guard.trial(c, b)) {
now_exec = 6;
skip = 6;
continue;
}

System.out.println("oh !! end of line...pre exec:["+now_exec+"]");
guard.remove();
skip = now_exec;
}

System.out.println(guard.list);
}

Masu a, b, c;

class Masu {
String name;
int limit_size;
int size;

public Masu(String name, int limit_size, int size) {
this.name = name;
this.limit_size = limit_size;
this.size = size;
}

public String toString() {
return String.format("(%s:%s/%s)", this.name, this.size,
this.limit_size);
}
}

static boolean pre_cond_check(Masu a, Masu b, Masu c) {
int divide = a.size / 2;
if (divide <= b.limit_size || divide <= c.size)
return true;
return false;
}

static boolean check_goal(Masu a, Masu b, Masu c) {
int divide = a.limit_size / 2;
if ((a.size == divide && b.size == divide)
|| (b.size == divide && c.size == divide)
|| (a.size == divide && c.size == divide)) {
return true;
}
return false;
}

protected static boolean eq(Object object, Object object2) {
return object == null ? object2 == null : object.equals(object2);
}

}

groovy ソートの平均要素移動距離 - というものらしい。 2007/08/11

きまぐれ日記: ソートの平均要素移動距離

上記の記事を読みまして、手習いがてらに、groovyで表現してみました。


シナリオ

配列をランダムにシャッフルし,ソートするした場合の要素の平均移動距離を求めてみてください。


import java.util.*;

def m_size = 1000;
def max_trial = 1000;

def ary = [];
(0..<m_size).each { i -> ary[i] = i; }

def sum = 0;
def trial = 0;

(0..<max_trial).each {
Collections.shuffle(ary);
(0..<ary.size()).each { i ->
sum += Math.abs(ary[i] - i);
++trial;
}
}
def result = sum / trial / m_size;
print "計算結果:${result}"


def result = sum / trial / m_size;


の部分は、移動した距離の総和を試行回数で割って、それを配列のサイズで割るということですね。

えーと、ソートするとソートされる要素が配列の中で、全体の距離の、3分の1を大体が移動するという理解でいいのかな。

ちなみに、上記の元ネタの記事では、数学的な証明を行っていましたよ。
僕自身、はなはだ数学がだめなので、それはパスしました。

モンテカルロ法はよく確率を近似的に求める手法として使われる。n回シミュレーションを行い、ある事象がm回起これば、その事象の起こる確率は当然ながらm/nで近似される。試行回数が少なければ近似は荒く、試行回数が多ければよい近似となる。モンテカルロ法 - Wikipedia


なるほど。

行列の積 - いまさらながらですが。 2007/08/11

行列の積をプログラミングで行ってみます。

シナリオ

2次元配列を引数にとって行列の積を行うメソッドを作成してください。


で、javaで行います。



参考:
行列 - Wikipedia


上記の結果を目標にしてみます。

工夫した点は、計算式のループのネストがいやなので、匿名クラスを使用した。その副作用としてメソッドの引数にfinalがつきます。

java自体のもつassertを使用した箇所が一箇所あります。
実は、このassertのふるまいがいまいち自分の直感に沿っていなくて、使用するのがためらわれます。

java VMの引数に-eaが必要となりますね。

コード下記のようにしました。
package matrix;

public class Product {

public static void main(String[] args) {
int[][] a = { { 5, 6 },
{ 7, 8 } };
int[][] b = { { 1, 2 },
{ 3, 4 } };
int[][] result;
result = calc_2By2(a, b);
printMatrix(result);
System.out.println();
result = product(a, b);
printMatrix(result);

a = new int[][]{ { 2, 4, 3 },
{ 4, 1, 2 },
{ 2, 3, 5 }};
b = new int[][]{ { 3, 4 },
{ 2, 1 },
{1, 5 }};
//b = new int[][]{{1, 1}};

System.out.println();
result = product(a, b);
printMatrix(result);

}

public static void printMatrix(int[][] m) {
for (int[] is : m) {
for (int i : is) {
System.out.print(i);
System.out.print(" ");
}
System.out.println();
}
}

public static int[][] calc_2By2(int[][] a, int[][] b) {

return new int[][] {
{ (a[0][0] * b[0][0]) + (a[0][1] * b[1][0]),
(a[0][0] * b[0][1]) + a[0][1] * b[1][1] },
{ (a[1][0] * b[0][0]) + a[1][1] * b[1][0],
(a[1][0] * b[0][1]) + a[1][1] * b[1][1] },

};
}

public static int[][] product(final int[][] a, final int[][] b) {

final int m = a[0].length;
final int n = b[0].length;

assert a[0].length == b.length || a.length == b[0].length;

int[][] result = new int[m][n];

class Support {
int calc(int i, int j) {
int result = 0;
for (int k = 0; k < m; k++) {
result += a[i][k] * b[k][j];
}
return result;
}

}

Support support = new Support();
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[i].length; j++) {
result[i][j] = support.calc(i, j);
}
}

return result;
}
}


結果は
//(1)
23 34
31 46

//(2)
23 34
31 46

//(3)
17 27
16 27
17 36



できていると思うのだが。

自信がないので、アドバイスがあればよろしくです。

参考

脳内メーカー - 興味深いです。 2007/08/10



たまにはプログラムのことを忘れて、脳内メーカーなるものをためしてみました。
興味深いです。

脳内メーカー

愛ばかり....Orz.そして忘れる。

シェル ディレクトリにファイルがあるかどうかのチェックのためのひとつの方法 2007/08/10

任意のディレクトリにファイルがあるかどうかのチェックをしたい。


#!/bin/sh
TARGET=~/nakawaka/z2
if [ -d ${TARGET} ] && [ 0 -lt `ls ${TARGET} | wc -l` ]; then
echo "file exist Ok "
fi
echo "end"


-dは、ディレクトリかのチェックを行います。
-ltは、数値の比較
wcコマンドの-lは、
ライン行数だけ表示。

H氏にアドバイスをいただきました。

java 2の31乗とInteger.MAX_VALUE 2007/08/10

シナリオ:

javaで2の31乗とInteger.MAX_VALUEを知りたい。


コードです。
import java.math.BigInteger;

public class A20070809_2 {

public static void main(String[] args) {

BigInteger integer = BigInteger.valueOf(2);

// for (int i = 0; i < 32; i++) {
// System.out.println(integer.pow(i));
// }

System.out.println(integer.pow(31));
System.out.println(Integer.MAX_VALUE);

}

}


結果は、
2147483648
2147483647

(2の31乗)-1がInteger.MAX_VALUEとなります。

java ファイルのコピーのメモ 2007/08/09

FileChannel
駆け足メモ

FileChannel srcChannel = srcRaf.getChannel();
FileChannel dstChannel = dstRaf.getChannel();
srcChannel.transferTo(0, srcChannel.size(), dstChannel);
dstChannel.force(true);



FileChannel srcChannel = srcRaf.getChannel();
FileChannel dstChannel = dstRaf.getChannel();
long totalLength = srcChannel.size();
dstChannel.write(srcChannel.map(FileChannel.MapMode.READ_ONLY, 0,
totalLength));


FileChannel dstChannel = dstRaf.getChannel();
for (ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); srcChannel
.read(buffer) != -1; buffer.clear()) {
buffer.flip();
while (buffer.hasRemaining())
dstChannel.write(buffer);
}


参考:
New IO Copier : FileChannel : File : Java Tutorial

java ラバーバンドを表現するためのした調べ 2007/08/09

rubber band を表現するための試作

参考:
JListのアイテムを範囲指定で選択 - Java Swing Tips

工夫したのは、点線が動いているようにみせるために、Timerを使って書きはじめの位置をずらして交互に表示させていること。

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.SystemColor;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Line2D;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

class TestRubberband extends JPanel {

private static final long serialVersionUID = 1L;
private final Color rcolor;
private final Polygon polygon = new Polygon();
private final Line2D line = new Line2D.Double();
Point srcPoint = null;

public TestRubberband() {
rcolor = SystemColor.activeCaption;

setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
if (srcPoint == null)
srcPoint = e.getPoint();

Point destPoint = e.getPoint();

polygon.reset();
polygon.addPoint(srcPoint.x, srcPoint.y);
polygon.addPoint(destPoint.x, srcPoint.y);
polygon.addPoint(destPoint.x, destPoint.y);
polygon.addPoint(srcPoint.x, destPoint.y);
if (srcPoint.getX() == destPoint.getX()
|| srcPoint.getY() == destPoint.getY()) {
line.setLine(srcPoint.getX(), srcPoint.getY(), destPoint
.getX(), destPoint.getY());

}
repaint();
}
});
addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
repaint();
}

public void mousePressed(MouseEvent e) {

}
});

Timer timer = new Timer();
TimerTask task = new TimerTask() {

@Override
public void run() {
repaint();
}
};

timer.schedule(task, 0, 300);
}

/*
* ラバーバンドが動いて見えるようにするために使用しています。
*/
boolean b = true;

public void paintComponent(Graphics g) {
super.paintComponent(g);
if (srcPoint == null)
return;
Graphics2D g2d = (Graphics2D) g;

float[] pattern = { 5, 5, 5, 5 };

b = b ? false : true;
BasicStroke bs = new BasicStroke(2f, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_ROUND, 1f, pattern, b ? 0f : 3f);

g2d.setStroke(bs);
g2d.setPaint(rcolor);
g2d.drawPolygon(polygon);

}

protected Color makeColor(Color c) {
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
if (r > g)
return (r > b) ? new Color(r, 0, 0) : new Color(0, 0, b);
else
return (g > b) ? new Color(0, g, 0) : new Color(0, 0, b);
}

public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new TestRubberband());
frame.setVisible(true);
}

}

数値文字参照、文字実体参照について。 2007/08/09

数値文字参照、文字実体参照について。

カンマは、数値文字参照で表現すると&#x2cです。

American Standard Code for Information Interchange - Wikipedia
文字参照 - Wikipedia

groovy 手習い groovlet getでもらった値をテーブルで表示 2007/08/08

シナリオ

groovletを使ってGETの値を表示してください。


ソースはUTF-8で書いて、あとURLエンコードは、sjisからの変換を想定しています。

import java.net.URLDecoder;
import groovy.xml.*

response.setContentType('text/html;charset=utf-8');

def s = request.getQueryString().split('&');
def decoder = URLDecoder;

def writer = new StringWriter();
def builder = new MarkupBuilder(writer);

builder.table(border:1){
caption('パラメーター表示します。')
tr{ th('キー'); th(colspan:3, '値')
s.each{ s2 ->
tr{
s2.split('=').each{
s3 -> td(decoder.decode(s3, 'sjis'))
}
}
}
}
}

println """
<html>
<head>
<title>日本語utf-8</title>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=utf-8">
</head>
<body>
${ writer }
</body>
</html>
"""


groovyおもしろいなぁ。

POIを使って読み込めなかったエクセルファイルがあったので、それについてのメモです 2007/08/08
2007/08/10

POIを使って読み込めなかったエクセルファイルがあったので、それについてのメモです。
解決策をみつけたわけではないです。

java.io.IOException: Unable to read entire block; 472 bytes read; expected 512 bytes
at org.apache.poi.poifs.storage.RawDataBlock.(RawDataBlock.java:67)
at org.apache.poi.poifs.storage.RawDataBlockList.(RawDataBlockList.java:52)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.(POIFSFileSystem.java:87)


上記のようなエラーがでました。

そのエクセルのファイルは、エクセルで読めます。
openofficeでも読めました。

そのエクセルファイルを512で、割れるようにバイナリエディターでお尻に文字列を入れたら、
構造がおかしいとエラーになりました。それはそうだ。。。

エクセルで別名で保存すればいいのですが、それだとプログラムで全部行うという解決策にはならない
Orz...

希望する解決策は、
POIを使用する際に、パラメータで解決できれば、うれしい。
マイクロソフトエクセルや、オープンオフィスをそのために起動したくない。。。

そもそもどうやったら読み込めないエクセルファイルができるのかが知りたい。

他のライブラリ(JExcelApi)で読んでもだめだった。
openofficeすごいな。

参考:
sc: Spreadsheet Project
JExcelApi

Lisperとそれ以外の人とが見ているものの違い - なるほど 2007/08/07


Lisperとそれ以外の人とが見ているものの違い
なるほど。

java 「日本語」をURLエンコード 2007/08/07
2007/08/08

「日本語」をURLエンコード

import java.io.IOException;
import java.net.URLEncoder;

public class Check_url_encoder_coder {

public static void main(String[] args) throws IOException {

String targert = "日本語";
String[] encs = { "sjis", "utf-8", "euc-jp" };

for (String enc : encs) {
p(URLEncoder.encode(targert, enc));
}

}

static void p(String s) {
System.out.println(s);
}

}


結果:
sjis:%93%FA%96%7B%8C%EA
utf-8:%E6%97%A5%E6%9C%AC%E8%AA%9E
euc-jp:%C6%FC%CB%DC%B8%EC


URLEncoderのエンコード指定はエンコードが何の文字列を変換するのかという指定になります。何かややこしいかな。
java内部での文字列を、encで指定したエンコーディングにしたあと、URLエンコードに出力するという感じですかね。

プログラム内部で、文字列をbyte[]のようにあつかっていれば、byte[]がどのエンコーディングにされているか気にする必要があります。えーと、つまり、内部データのエンコーディングを知りつつ、それを対象のエンコーディングに変換する必要がありますが、javaのStringで扱っていて、読めているのであれば、気にする必要がないということですよね。

参考:
データ変換ツール(BASE64, URLエンコード(URLデコード), HEX(16進ダンプ), MD5, SHA-1変換フォーム)

groovy groovlet エンコードutf-8でソースを書きたい場合 2007/08/07

groovletをutf-8で書きたい場合は、
アプリケーションサーバを起動するときにファイルエンコーディングを指定する。

jettyなら、起動するときに、
java -Dfile.encoding=UTF-8 -jar start.jar
とします。


参考:
ちくわプログラマの作業履歴@はてな

アトキンソンのディザリング - 挫折 2007/08/05


この画像は、Tinrocket, LLC | HyperDitherというアプリケーションを使用して変換したものです。
HyperDitherは、Atkinson Ditheringというアルゴリズム?を実装したものだそうです。

シナリオ

Atkinson Ditheringっぽいのを実装してみてください。


Atkinson Ditheringを下記のサイトで存在をしって自分で実装もしくは、汎用のライブラリでツール作れないかなぁと思っていろいろやってみたのですが、画像処理についてよくわかってなくて挫折しました。時間が大量にあるときにいろいろやってみようと思います。




ちなみにディザリングでは、
が有名なようです。

DiffusionFilter
をためしているのですが、どうもしっくりこないです。

ちなみに、
いろいろ調べていて、
MemoNyanDum | [C# Graphics] 誤差拡散によるディザ - Floyd_Steinberg
のC#のコードがコンパクトかなぁと思いました。

参考:

これからはAPP(Atom Publishing Protocol)に注目!? 2007/08/04

これからWebAPIを考えているなら、APP(Atom Publishing Protocol)を視野に入れて設計したほうがよい?

この先、Web API を設計する人は、まず APP が利用できないか検討しましょう。 APP を採用すれば自然と REST スタイルを採用することになります。これまで悩みがちだった Web API の設計が、かなり楽になると思います。 Web API を設計する人は、オレオレXMLを設計する前に、Atom/APP をベースにしたらどうなるか、を考えて見ましょう。きっと Atom/APP は良い選択肢になってくれるはずです。
yohei-y:weblog: APP の標準化作業がほぼ終了



参考:

blogger bマークのボタンと被ブックマーク数を表示するための準備 2007/08/04

シナリオ:

bloggerではてなブックマーク(はてブ)のbマークボタンと、被ブックマーク数を表示したい。



コードは下記のものを上記のリンクを参考にテンプレートに入れてみました。

bマークボタン
<!-- HATEBU -->
<a expr:href='"http://b.hatena.ne.jp/add?mode=confirm&amp;url=" + data:post.url + "&amp;title=" + data:post.title'>
<img alt='このエントリーを含むはてなブックマーク' height='12' src='http://deiji.jp/images/entry.gif' style='padding:0 0 0 0; margin: 0 0 0 0; border: none;vertical-align: bottom;' width='16'/>
<!-- HATEBU END -->


はてブの被ブックマーク数
<!-- HATEBU -->
<a expr:href='"http://b.hatena.ne.jp/entry/" + data:post.url' target='_blank' title='このエントリーを含むはてなブックマークを表示'>
<span class='hatena-counter' expr:style='"background-repeat: no-repeat; background-attachment: scroll; background-position: left center; margin:0pt 0pt 0pt 0pt; padding: 15px; background-image: url(http://b.hatena.ne.jp/entry/image/" + data:post.url + ")"'/> </a>
<!-- HATEBU END -->

eclipseでant taskのftp使用する - 別jarが必要 2007/08/04

eclipseでant taskのftp使用する際に、
commonsのnetが必要になったのでメモ。


それでeclipseのpreferencesのantでライブラリへのパスを設定。
Classpath - Ant Home Entries
にAdd External Jarsで設定しました。

他にいい方法があるかもしれません。

ちなみにftp taskは下記のような感じで記述。
<ftp server="myserver address" port="21" remotedir="/home/user/" userid="myuserid" password="mypassword" binary="yes">
<fileset dir="${build.dir}/">
<include name="*.jar" />
</fileset>
<fileset dir="${basedir}/jnlp/">
<include name="*.jnlp" />
</fileset>
</ftp>


というかこのtipsは以前に似たようなものを書いた...



似たようなことを繰り返しているなぁOrz...

java イルージョン webstartで作成してみました。- ちょっと怖い。 2007/08/02



Christopher Walken Illusion - Mighty Optical Illusions
上記のサイトでおもしろいアニメーションGIFがありました。
このアニメーションGIFは4枚のGIFで構成されていまして、おもしろい効果をだしています。
そこで、プログラムで表現できないかなと考えました、



ベースになる、宇宙の写真はここから。

HubbleSite - NewsCenter - Hubble Photographs Grand Design Spiral Galaxy M81 (05/28/2007) - Release Images


どうやって表現しますかといいますと、
まず、上記の宇宙の写真をグレースケールに変換します。表示します(a-1)。そして動いた感じをだすために、少しずらして表示します(a-2)。そしてその白黒写真を反転(invert)します(b-1)。そしてこの反転した画像をずらして表示します(b-2)。
この四枚を繰り返して表示して効果を真似てみました。


作成したアプリケーションは下記のような感じです。java webstartにしてみました。


起動は下記のボタンから。


起動時に画像処理を行っているのでちょっと起動にもたつきがありますが...
画像処理は、

Jerry's Java Image Processing Pages

を使用しています。いろいろフィルターが用意されいるので使いやすいです。

コードは下記の感じです。


BufferedImage image = ImageIO.read(ImagePanel.class.getResource("g.jpg"));
GrayscaleFilter filter = new GrayscaleFilter();
dst = filter.filter(image, null);
invert = new InvertFilter().filter(dst, null);
BufferedImage image2 = ImageIO.read(ImagePanel.class.getResource("man.png"));
man = filter.filter(image2, null);
man_invert = new InvertFilter().filter(man, null);