GO FOR ITに挑戦 (1) 人生の時計

こんばんは、chen_jiです。

本日は、株式会社SONYさん主催の「GO FOR IT」に挑戦してみました。

5つの問題から、解きたいものを選択して解答するようですが、とりあえず最初ということで、
(1) 人生の時計
を解いてみました。

問題

1) 人生の時計
あなたの一生を24時間にたとえると今日は何時何分何秒ですか?
ただしあなたはあなたの誕生日(a年b月c日)の0時ちょうどに生まれてn歳まで生きる(n歳のときは生きていてn+1歳にはなれない)とし、bとcは一般的な月日の範囲とします。

i) 1990<=a<=2000,n=80のとき、今日は何時何分何秒ですか?
ii) 1900<=a<=2000,n=200のとき、今日は何時何分何秒ですか?

解答

(ひとまず、Pythonで解答。KonohaScript版は後日載せます。)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
1-1.py
license BSD
author chen_ji <wakamori111 at gmail.com>
"""

import datetime
import random
import sys

class DayLife:
    """Life in a day."""

    def __init__(self, date, life):
        """Set birth datetime and life."""
        self.birthdate = date
        self.life = life
        finalyear = self.birthdate.year + self.life
        finaldate = datetime.datetime(finalyear, self.birthdate.month,
                                      self.birthdate.day)
        self.finaldate = finaldate - datetime.timedelta(days=1)

    def now(self):
        """Calculate current time."""
        curdate = datetime.datetime.now()
        maxdays = (self.finaldate - self.birthdate).days
        curdays = (curdate - self.birthdate).days
        curtime = datetime.timedelta(days=1) / maxdays
        curtime = curtime * curdays
        return datetime.time(
                   (curtime.seconds / 60) / 60,
                   (curtime.seconds / 60) % 60,
                   curtime.seconds % 60)

if __name__ == '__main__':
    # options
    startyear = 1990
    endyear = 2000
    life = 80
    print startyear, "<= a <=", endyear
    print "n =", life
    daycount = (datetime.datetime(endyear, 12, 31) -
                   datetime.datetime(startyear, 1, 1)).days
    birthdate = datetime.datetime(startyear, 1, 1) + \
                    datetime.timedelta(days=random.randint(0, daycount))
    args = sys.argv
    if len(args) == 4:
        year = int(args[1])
        month = int(args[2])
        date = int(args[3])
        birthdate = datetime.datetime(year, month, date)
    print "birthdate:", birthdate.date()
    mylife = DayLife(birthdate, life)
    print "finaldate:", mylife.finaldate.date()
    print "today:", mylife.now()

実行結果

today: xx:xx:xx

というフォーマットで、本日の時刻が出力されます。

i) 解答
$ ./1-1.py
1990 <= a <= 2000
n = 80
birthdate: 1994-06-29
finaldate: 2074-06-28
today: 05:16:59
ii) 解答

誕生日と寿命のオプションを下記のように変更してから実行します。

--- 1-1.py      2012-02-07 01:47:51.000000000 +0900
+++ 1-2.py      2012-02-07 01:45:31.000000000 +0900
@@ -31,9 +31,9 @@

 if __name__ == '__main__':
     # options
-    startyear = 1990
+    startyear = 1900
     endyear = 2000
-    life = 80
+    life = 200
     print startyear, "<= a <=", endyear
     print "n =", life
     daycount = (datetime.datetime(endyear, 12, 31) -
$ ./1-2.py
1900 <= a <= 2000
n = 200
birthdate: 1969-05-14
finaldate: 2169-05-13
today: 05:07:42

誕生日を1968年3月1日に指定すると、こんな感じです。

$ ./1-2.py 1968 3 1
1900 <= a <= 2000
n = 200
birthdate: 1968-03-01
finaldate: 2168-02-29
today: 05:16:21

konoha.qt4パッケージの使い方

皆さんこんにちは、お久しぶりです。あけましておめでとうございます。
本年もよろしくお願いします。

昨年末に開催されたQt Developer Conference Tokyo/2011にて、KonohaScriptの紹介をさせて頂きました。これを区切りとして、konoha.qt4パッケージを含むバイナリパッケージをgooglecodeにアップロードしました。
ダウンロードはこちらから
本日は、このバイナリパッケージのインストール方法と使い方を簡単にご紹介したいと思います。

konoha.qt4パッケージとは

konoha.qt4パッケージは、PythonにおけるPyQtライブラリのようなもので、Qtを利用したGUIアプリケーションをKonohaScriptで開発するためのライブラリ群です。

インストール方法

次の中から、ご自身の環境にあったものをダウンロードして下さい。全て64bit OS用です。

Linux版とMac版にはQt本体が含まれていませんので、別途インストールが必要になります。Linuxの方は、yumやaptなどのパッケージ管理システムからQtの最新版(Qt-4.8.0)をインストールして下さい。Macの方は、Qt Libraryのソースコードをダウンロードし、インストールパスをデフォルトのままにして、make installして下さい。
qt-everywhere-opensource-src-4.8.0.tar.gz
または、MacPortsやHomebrewをお使いの方は、Qt-4.8.0をインストールして、

/usr/local/Trolltech/Qt-4.8.0

のパスからQtのルートディレクトリを辿れるように、シンボリックリンクを作成していただいても大丈夫です。

使い方

konoha.qt4パッケージは、基本的にQtのC++インタフェースにあわせてAPI設計されています。Qtを使用したことのある方は、それほど抵抗なく利用できると思います。APIリファレンスは現在のところ用意しておりませんので、クラス設計等は、Qt本家のドキュメントhttp://doc.trolltech.com/4.8-snapshot/index.htmlをご参照ください。

konoha.qt4パッケージを利用したサンプルプログラムを幾つか用意しました。

テキストエディタ

QTextEditを利用して、簡単なテキストエディタを作成しました。

using konoha.qt4.*;
QApplication app = new QApplication();
QWidget widget = new QWidget();
QTextEdit textedit = new QTextEdit();
QVBoxLayout layout = new QVBoxLayout();
layout.addWidget(textedit);
widget.setLayout(layout);
widget.show();
app.exec();

上記のコードの実行結果は以下のようになります。

このように、konoha.qt4パッケージを使用すれば、クロスプラットフォームのGUIアプリケーションを数行程度で開発することができます。c++のQtライブラリは、細かい属性を変更するたびに、変更箇所をコンパイルして実行しなければなりませんが、スクリプト言語を使用すれば、再コンパイルなしに即実行できますので、開発効率の点で非常に優れているといえます。

シグナル

本家のQtライブラリは、シグナルとスロットを用いてオブジェクト間の通信を行います。一方、konoha.qt4では、統一的なインタフェースで、シグナルに対するコールバック関数を登録することができます。

// c++の場合
// チェックボックスのオン・オフの切り替えに連動してラベルの表示・非表示を切り替える
QLabel *label = new QLabel("Label");
QCheckBox *checkBox = new QCheckBox;
connect(checkBox, SIGNAL(toggled(bool)), label, SLOT(setVisible(bool)));
// KonohaScriptの場合
// チェックボックスのオン・オフの切り替えに連動してラベルの表示・非表示を切り替える
QLabel label = new QLabel();
label.text = "Label";
void show(QCheckBox checkBox) {
	label.visible = label.isVisible() ? false : true;
}
QCheckBox checkBox = new QCheckBox();
// QCheckBoxのtoggledシグナルに対して、コールバック関数showを接続する
// QWidget.signalConnect(String signalName, dynamic callbackFunc);
checkBox.signalConnect("toggled", show);

以下はボタンを押した時/離した時に、それぞれコールバック関数を実行させるサンプルコードです。

using konoha.qt4.*;
void pressed(QPushButton button) {
	print "pressed";
	print b;
}
void released(QPushButton button) {
	print "released";
	print b;
}
QApplication app = new QApplication();
QPushButton button = new QPushButton();
button.signalConnect("pressed", pressed);
button.signalConnect("released", released);
button.show();
app.exec();

ボタンを2回押した時の実行結果は以下のようになります。(コンソール含む)

Webビューワ

最後に、QtWebKitを利用したサンプルとして、シンプルなWebビューワをご紹介します。

using konoha.qt4,*;

class SimpleWebViewer {
	QUrl url;
	QWebView web_view;
	QToolButton next;
	QToolButton prev;
	QLineEdit location_bar;
	QHBoxLayout hbl;
	QVBoxLayout vbl;
	QWidget body;

	SimpleWebViewer(String u) {
		url = new QUrl();
		url.setUrl(u);
		web_view = new ();
		web_view.load(url);
		next = new ();
		next.setArrowType(3);
		prev = new ();
		prev.setArrowType(4);
		location_bar = new ();
		hbl = new ();
		hbl.addWidget(next);
		hbl.addWidget(prev);
		hbl.addWidget(location_bar);
		hbl.addStretch();
		vbl = new ();
		vbl.addLayout(hbl);
		vbl.addWidget(webView);
		body = new ();
		body.setLayout(vbl);
		next.signalConnect("clicked", delegate(web_view, back));
		prev.signalConnect("clicked", delegate(web_view, forward));
		webView.signalConnect("url-changed", delegate(this, updateLocationBar));
		location_bar.signalConnect("return-pressed", delegate(this, updateWebView));
	}

	void show() {
		body.show();
	}

	void updateLocationBar(QWebView w) {
		QUrl u = w.url;
		String host = u.host;
		String path = u.path;
		_location_bar.setText(host + path);
	}

	void updateWebView(QLineEdit le) {
		String path = le.text;
		_url.setUrl("http://" + path);
		_web_view.load(url);
	}
};

QApplication app = new ();
SimpleWebViewer viewer = new ("http://konohascript.org");
viewer.show();
app.exec();

実行結果は次のようになります。

まとめ

konoha.qt4aパッケージを使えば、Qtライブラリを利用したリッチなGUIアプリケーションを、効率よく開発することができます。ぜひ一度お試し下さい。
最後に補足ですが、konoha.qt4パッケージは、横浜国立大学、倉光研究室に所属する修士2年と学部4年の学生二名によって開発されました(私ではありません)。QtのWebドキュメントから、KonohaScriptへのラッパーコードを20万行ほど自動生成して作成されました。

MacOSXでsyslogへの1秒あたりの書きこみ上限数を無効にする

MacOSX 10.6 にて、ループで大量の文字列をsyslogに書き込むスクリプトを記述したところ、こんな感じで怒られてしまいました。

Dec  2 11:49:11 chen-pro konoha[730]: *** process 730 exceeded 500 log message per second limit  -  remaining messages this second discarded ***

どうやら、一秒あたりの書き込み上限数に達した模様。これを解除するために、plistファイルを編集しようと思ったのですが、なぜかバイナリファイルのため編集できませんでした。調べてみたところ、
Snow Leopard の syslogd で、UDPポートでLISTENしてリモートからのログを受け取る設定 - hibomaのはてなダイアリー
こちらに載っていた手順で編集できるようになりました。

$ sudo plutil -convert xml1 /System/Library/LaunchDaemons/com.apple.syslogd.plist

あとは、
macos - Mac: Extend or disable 500 Messages Limit of Console - Super User
こちらの手順に従って、syslogd起動時の引数を追加しました。

apple.syslogd.plist     2011-12-02 17:48:59.000000000 +0900
@@ -18,6 +18,8 @@
        <key>ProgramArguments</key>
        <array>
                <string>/usr/sbin/syslogd</string>
+               <string>-mps_limit</string>
+               <string>0</string>
        </array>
        <key>Sockets</key>
        <dict>
cing>/usr/sbin/syslogd</string>

最後に、plistをロードし直します。

$ sudo launchctl unload /System/Library/LaunchDaemons/com.apple.syslogd.plist
$ sudo launchctl load /System/Library/LaunchDaemons/com.apple.syslogd.plist

KonohaScriptの基本文法

おはようございます。

本日は、KonohaScriptの基本文法について書いてみようと思います。
なお、本文中のプログラムの表記ですが、「>>>」から始まる文は、KonohaScriptのインタラクティブシェルでの動作を想定しています。それ以外のプログラムは、ファイルに保存して、「$ konoha (filename)」のかたちで実行することが(おそらく)できます。

コメント

コメントは、内部に書かれた文字の評価を無視する構文です。CやJava言語と同様の形式で書くことができます。それに加えて、複数行コメントの入れ子(ネスト)もできます。

// 単数行コメント
/* 複数行
コメント */
/*
複数行
/* コメントの */
入れ子
*/

文末のセミコロン

文末を表すセミコロンは、改行する場合は省略可能です。(可読性のためつけることを推奨します。)

// OK
a = 1
// OK
a = 1; b = 2;

ブロック

ブロックは、"{"と"}"で囲まれた領域です。ブロック内で宣言された変数のスコープは、ブロックの内部になります。

>>> { int a = 1; } // ブロック内で変数を宣言
>>> print a; // ブロック外から呼び出すことはできません
 - ((eval):1) (error) undefined variable: a
>>> {
      int a = 1;
      print a; // ブロック内から呼び出すことはできます
    }
((eval):3) a=1

変数の宣言

KonohaScriptは静的型付けなので、基本的には型を指定して変数を宣言します。構文はC、Javaと同様、「型 変数名 = 値」の形です。
型を省略した場合、型推論が行われますが、推論できない場合はdynamic型(動的型付け)となります。

int a = 1; // int型の変数aを宣言し、値1を代入
String s = "a"; // String型の変数sを宣言し、値"a"を代入
b = 2; // bの型はint型に推論されます。
c = null; // cの型は推論できません。

また、型ごとにデフォルト値が決まっており、変数の宣言時の代入を省略した場合、デフォルト値が代入されます。

int a; // a = 0
String s; // s = ""(空文字列)
float f; // f = 0.000000

「,」で区切ることで、複数の変数を同時に宣言できます。「=」でつなぐと、同じ値を代入できたりします。

int a,b,c; // a = 0, b = 0, c = 0
int a = b = c = 2; // a = 2, b = 2, c = 2;

条件分岐

if-else, switch, 三項演算子などがあります。

>>> if (true) print 1; // 実行される
((eval):1) 1
>>> if (false) print 1; // 実行されない
>>> if (false) print 1; else print 2; // else節が実行される
((eval):1) 2
>>> switch (2) { // case にマッチした場合、それ以降の式を実行します。抜けたいときはbreakを書いてください。
    case 1:
      print 1;
    case 2:
      print 2;
    case 3:
      print 3;
    default:
      print 4;
    }
((eval):5) 2
((eval):7) 3
((eval):9) 4
>>> switch("abc") { // 文字列もswitchで分岐できます
    case "abc":
      print "OK";
      break;
    case "def":
      print "NG";
      break;
    }
((eval):3) OK
>>> print true ? 1 : 2 // 三項演算子
((eval):1) 1
>>> print false ? 1 : 2 // falseの場合は、コロン":"以降が評価されます
((eval):1) 2

ループ(繰り返し構文)

while、do-while、for、foreachなどがあります。また、繰り返しを抜けるbreak、次の繰り返しへ継続するcontinueが使用できます。

int i = 0;
while(i < 10) i++;
print i; // i=10
do {
  print "hi";
} while(false); // do{}のブロックを一回だけ実行
for (i = 0; i < 10; i++) {
  print i; // i=0, i=1, ..., i=9まで表示
}
Array<String> a = ["a", "b", "c"]
foreach(String s in a) {
  print s; // s="a", s="b", s="c"
}
i = 0;
while(true) {
  if (i == 3) break;
  i++;
}
print i; // i=3
for (i = 0; i < 5; i++) {
  if (i < 3) continue;
  print i; // i=3, i=4を表示
}

konoha.proc, konoha.signalパッケージの追加

こんばんは、

KonohaScriptは、C/C++でラッパー関数を記述することで、C/C++のライブラリを拡張ライブラリとして利用できます。
(ffiを利用してスクリプトから外部関数を呼び出す方法もありますが、こちらは現在調整中です。)

今回は、このラッパー関数を記述して、KonohaScriptライブラリ(我々はパッケージと呼んでいます)を二つ作成しました。

  • konoha.proc
    • プロセス管理(子プロセス生成、標準入出力のパイプ)
  • konoha.signal
    • シグナルハンドラの設定

それぞれ、使い方を簡単に紹介します。

konoha.proc

例えば、カレントディレクトリにあるファイルの一覧を取得したい場合は、以下のように記述できます。

using konoha.proc.*; // procパッケージを読み込む
p = new Proc(["/bin/ls", "-lg"]); // Procオブジェクトpの作成(コマンドの実行)
foreach (String s in p.getInputStream()) { // pの標準出力を一行ずつ処理する
  OUT << s << EOL; // 文字列の表示
}

1行目の>|using konoha.proc.*;|<は、konoha.procパッケージで定義されているクラスを読み込む構文です。
2行目では、子プロセスをフォークして引数のコマンドを実行しています。引数には、コマンドとコマンド引数を文字列の配列として渡します。
3行目で、子プロセスの標準出力をストリームとして取得し、文字列ストリームをイテレータに変換して、foreach構文で一行ずつ取り出しています。
4行目は、KonohaScriptのプリント構文です。文字列sの末尾にEOL(改行)を加えたものをOUT(標準出力)に送信しています。

実行結果は、shellで「ls -lg」を実行した場合と同じです。

konoha.signal

例えば、アラームシグナルを指定時間後に発行して処理を行いたい場合は、以下のように記述できます。

using konoha.signal.*; // signalパッケージを読み込む

// シグナルハンドラ関数の作成
void handler(int n) {
	throw new Script!!("signum=" + n);
}

// SIGALRMに対して、シグナルハンドラhandlerを設定する
Signal.signal(Signal.SIGALRM, handler);
Signal.alarm(1);

try {
	while (1) {
		print "hi";
	}
} catch (Exception!! e) {
	print e;
}

こちらは、Javaとよく似た構文になっています。KonohaScriptは、C/C++, Javaユーザが抵抗なく書けるように文法設計をしています。

以上、二つのライブラリパッケージの簡単な機能紹介でした。
他にもいくつかのライブラリ*1を用意していますので、ぜひ一度お試しください:)
ではまた。

*1:最近作っているものでは、Qt4(GUI開発)、OAuth(Webアプリ認証)、LLVM(コード生成)などがあります。

Aspen

おはようございます。

9月2日から4日にかけて、「夏のプログラミング・シンポジウム2011(プロシン)」に参加してきました。
初めて佐賀県に行きましたが、イカ料理が美味しかったです。

プロシンでは、AspenというオンラインKonohaScript開発環境について発表を行いました。

まだ開発段階でいろいろと仕様変更の可能性が高いのですが、以下のような特徴をもっています。

  • ブラウザから入力したKonohaScriptのスクリプトをサーバサイドで実行して、結果をテキストエリアに出力
  • twitterのOAuthを利用したユーザ認証
  • スクリプトをサーバに保存・読み込み

今後、以下のような機能を追加していく予定です。

KonohaScriptを試しに触ってみたい、という方はぜひ一度お試しください。

http://konoha.ubicg.ynu.ac.jp/aspen/

分からないことがありましたら、コメント等でご連絡ください。