August 21, 2012

このblogは移動しました。

ARGV Webサーバの引っ越しに伴い、このblogは、http://www.k.nakao.name/noisefactoryに移動しました。

新しいアドレスへリダイレクトしているので、この記事が読めるのは、RSS/Atomで購読されている方だと思います。引き続き購読するには、AtomフィードURLを、http://www.k.nakao.name/noisefactory/?feed=atomに、変更をお願いします。

July 6, 2012

Debianサーバ無限ポチポチのお作法

 大統一で発表したネタの準備に、kvmで色々実験した。その際パラメータや手順を変えて実験するのだが、毎回真っ新なインストール状態に戻す必要がある。この作業は面倒でさらに試行の度に行うので大変である。さらに今回はアーキティクチャーを変えなければならないので、debootstrapでベースシステムをダウンロードしてイメージとしてとっておき、必要になったら展開してchrootというやり方は使えない。そこで、以前第0回福岡Debian勉強会のときに、山田さんが発表されていた、Debianサーバ量産工場 - 無限ポチポチ on Debianという発表を思い出して、それに紹介されていた手法の一つを試してみた。

 基本的なアイデアは、Read OnlyなベースシステムとRead Writeな変更部分を分離しておき、これらをaufsでまとめて、kvmのvirtfsを使うというものだ。

 まず、debootstrapで適当なディレクトリに、ベースシステムを展開して、

# debootstrap --arch i386 sid ./sys http://ftp.jp.debian.org/debian

ベースシステムにカーネルをインストールし、initrdに必要なモジュールを追加する。もしも最初から入れておく必要があるパッケージがあれば、chrootしているうちにインストールしておこう。あとrootパスワードの設定はお忘れなく。

# 必要な設定をするために、ベースシステムにchrootする
# mount -t proc proc sys/proc
# chroot ./sys

# カーネルをインストール
# apt-get update
# apt-get install linux-image-i686

# initrdに、virtioと9pのモジュールを追加
# echo virtio_pci >> /etc/initramfs-tools/modules
# echo 9p >> /etc/initramfs-tools/modules
# echo 9pnet_virtio >> /etc/initramfs-tools/modules
# update-initramfs -u

# root passwordの変更
# passwd

# chrootを抜ける
# exit
# umount sys/proc

 次にroot ファイルシステムを作ろう。変更部分のディレクトリを作り、さきほどのベースシステムのディレクトリとaufsで束ねる。

# mkdir -p rootfs/rw
# ln -s ../sys rootfs/
# mount -t aufs -o br:rootfs/rw:rootfs/sys=ro none rootfs

 最後に、kvmを起動する。

# kvm -virtfs local,path=./rootfs,mount_tag=FOO,security_model=none\
 -kernel ./rootfs/vmlinuz -initrd rootfs/boot/initrd-.... \
 -append "rootfstype=9p rootflags=trans=virtio root=FOO" ....

mount_tagと、-appendオプション中のrootパラメータを一致させることがポイント。 また、これは実験を目的としているので、セキュリティのことは考慮されていない。

 あとはRead Writeなディレクトリを自動で作って、rootfsを自動でマウントして、kvmを立ち上げてくれるスクリプトを書けば幸せになれます。

Have Fun!

June 28, 2012

Debian MultiArch Supportに関する諸々

2012年6月23日に京都大学で行われた「大統一 Debian勉強会」で「Debian MultiArch Support」という発表をした(スライド)。MultiArchのことは日本語でほとんど情報がないので、この発表のために調べたことをせっかくなので記事にしておこう。まずは概要とユーザ向けの話から。

MultiArchとは何か

 DebianのNext Release DescriptionのMultiArchのところに、以下の記述がある。

The goal comprises all the changes required to support installation and execution of binary from multiple architectures on singlemachine.This includes not only the usual amd64/i386 bi-arch systems but also anyother combination, including cross-compiling environments for embedded systems.
Release Goals - MultiArch http://wiki.debian.org/ReleaseGoals/MultiArch

これによると、

  • ひとつのマシンに複数のアーキティクチャーのバイナリをインストールし実行できるようにすること
  • これは一般的なamd64/i386のbi-archシステムのみにとどまらず、組み込みシステムへのクロスコンパイル環境を含む他の組み合わせも含む。

ということがわかる。また、Release GoalsにMultiArchが含まれていることから、MultiArchをサポートしないとWheezyはリリースできない。

つかいかた

 まずインストールしたいセカンドアーキティクチャを指定する。ここでは、amd64システムが動いており、i386をセカンドアーキティクチャとしてインストールするとしよう。

# dpkg ­--­add-­archtecture i386

セカンドアーキティクチャの表示や削除は、dpkgにそれぞれ、--list-foreign-archtectures および --remove-architrecture を指定する。

# dpkg ­­--list-­foreign­-architectures
  i386 
# dpkg --­­remove­-architecture i386 

セカンドアーキティクチャをを追加または削除したら、パッケージデータベースの更新を忘れないように注意する。

# apt­get update

アーキティクチャー毎で、異なるパッケージ リポジトリを使いたいときは、apt lineを以下 のように記述する。

# in /etc/apt/sources.list etc. 
deb [armel, armhf] http://ftp.debian.. 

foreign-archのパッケージをインストールするときは、パッケージ名の後に:をつけて アーキティクチャを指定する remove, purgeするときも同様

# # Example.
# apt­get install libc6:i386

Have Fun!

May 1, 2012

DNSサーバのIPアドレスが変わった時の networksolutions の手続きに関する諸々

networksolutionsのDNSサーバのIPアドレスの変更について書いたのだが、間違っていたので訂正。

Managing Domain Name Serversによると、新しいネームサーバを追加したり、アップデートするためには、

  1. www.networksolutions.com にいく
  2. 右上にある、Manage Account タブをクリック
  3. User ID と password を入力
  4. My Products & Services タブをクリック
  5. My Domain Names をクリック
  6. More Domain Optionsまでスクロールして、Manage Name Serversをクリック
  7. 変更したいまたは追加したいサーバ名を入力して、GO (Continue)をクリック
  8. IPアドレスの入力欄が出てくるので、ネームサーバのアドレスを入力して、GOをクリックする。
  9. 変更していいか確認が出るので、良ければ Save Changesをクリック
  10. 更新した旨のメッセージが出る。

注意:世界中のサーバにドメインネーム情報が行き渡るのに、およそ72時間かかります。この手順を完了するとドメイン名を利用できるようになります。

April 13, 2012

MathJaxを使ってみた

まずは、オイーラーの公式から

\[ e^{i\theta} = \cos\theta + i \sin\theta \\ e^{i\pi}=-1 \]

おおぅ。ではガウスの法則はどうだっ!

\[ \oint_S \boldsymbol{D} \cdot d\boldsymbol{S} = \int_V \rho dV = Q \]

すばらしい。

April 12, 2012

素数日を調べるプログラムを書いてみた

長文こへだというブログの素数と素材とアホ夫婦の話という記事に、素数日だと思って2011年4月17日に婚姻届を出したのだが、20110417は、19の倍数(1058443 x 19)で素数ではなかったという話が載っていた。この夫婦の悲劇を繰り返してはならないという使命に燃え、素数日を調べるプログラムを書いてみた。ここでは素数日を、ある日付の西暦を4桁、月を2桁、日を2桁で表し、それをYYYYMMDDと並べた数値が素数である日付と定義する。

 それではまず、素数のリストを求めよう。素数は無数にあることが分かっている(数学ガール参照のこと)ので、求める範囲を2020年12月31日までとしよう。これは、私が結婚をすることを諦めるであろう期間の最大値であると根拠なく推定したからだ。ともあれ、C++で書くとこんな感じ。

#include<iostream>
#include<cstdio>

using namespace std;
const int MAX = 20201231;

int main(void)
{
	FILE *f;
	int n;

	if(NULL == (f = fopen("prime.dat", "wr")))
		return -1;

	fwrite("0", 1, 1, f); 
	for(int i=0; i<MAX; i++){
		fseek(f, i, SEEK_SET);
		fwrite("1", 1, 1, f); 
	}

	for(int i=2; i<=MAX/2; i++)
	{
		for(int j=2; MAX>(n=j*i); j++){
			fseek(f, n-1, SEEK_SET);
			fwrite("0", 1, 1, f);	
		} 
	}

	fseek(f, 0, SEEK_SET);
	for(int n=1; 0==feof(f);n++){
		if((int)'1' == fgetc(f))
			printf("%d\n", n);
	}

	return 0;
}

 C++とで書いたと言ってたくせにCじゃないかとか、最大値がマクロで指定されていてカッコ悪とか都合の悪いことは知らんぷりなのであしからず。素数の計算というと、べらぼうに時間がかかるイメージがあったのだが、実際に計算させてみるとCore2の2.4GHz、RAM2GByteで15分くらいだった。ちょっと拍子抜け。これならRubyで書いても問題なかったなぁと思った。 この出力をリダイレクトして、prime.lstというファイルに保存しておこう。

 このコードはシンプルなアイデアで、20201231個の「1」を書いたファイルを用意して、2の倍数、3の倍数、4の倍数...個目の1を0に変えていく。これをある大きさまで繰り返すと、素数個目の数が1で、それ以外が0になっている。つまり、1が何番目にあるか調べれば素数のリストを作ることができる。全く最適化していないので、無駄な計算をしている部分があるのだが、40行程度で書け、実行時間が実用上支障のない時間だったので、よしとする。

 次に、求めた素数が存在する日付であるか判定するプログラムが必要だ。PCが素数を探している間に、そのプログラムを書くことにしよう。こういうことはC/C++よりも、RubyやPerlがきっと得意なのでRubyで書くと、

#!/usr/bin/ruby

def calcEndofMonth(year, mon)
  t1 = Time.mktime(year, mon, 1);
  if(mon == 12)
    t2 = Time.mktime(year+1, 1, 1);
  else
    t2 = Time.mktime(year, mon+1, 1);
  end 

  return year*10000 + mon*100 + (t2-t1)/(3600*24);
end

def isCal(val)
  for year in 2012..2020
    for month in 1..12
      if((val > year*10000 + month*100) && (val <= calcEndofMonth(year, month)))
        return true;
      end
    end
  end
  return false;
end


f = File.open("prime.lst", "r");
f.each{|n|
  if(isCal(n.to_i))
    p n.to_i;
  end
}

これも簡単で、ある月に何日あるかを調べ、それをYYYYMMDDに並べて数を作る(たとえば、2012年4月であれば、4月には30日あるので20120430)。 次にその月の1日の数を作る(20120401)。そしてさきほど求めた素数がその範囲に入っているか調べる。入って入れば表示し、入っていなければ次の月で同じことを行う。これを求めたいすべての月で行うと、素数日を求めることができる。

 計算の結果、2012年1月1日から2020年12月31日までの間に182日あるようだ。計算した2020年までの素数日のリストもリンクしておく。

April 8, 2012

後悔と失意の週末

今日は映画、サッチャーを見た。 マーガレットサッチャーは、私が物心付いたときの英国の首相だ。 メリルストリープの演技が非常にすばらしく、マーガレットが類い稀な信念を持ち、 国民の反発を招きつつも、家族、特に夫ロバートに支えられていたことがよく描かれていた。

終わった後、私は深い後悔の念を感じた。 この作品を見たことに対する後悔ではない。 やるべきことをやらなかったこと、できることをしなかったことに。
そしてその時は過ぎ去り、取り返しがつかないのに...

スコッチが飲みたい。

March 26, 2012

変数を宣言せずに1から100までの和を求める方法

twitterで、

@nullmineral
「1から100までの整数の和を表示するプログラムを作れ」という問題を鼻で笑う諸君、「但し変数は新たに宣言しないこと」 という条件を付けても鼻で笑っていられるかな?

というtweetがあったので、あぁ再帰を使えば簡単。Rubyで書くとこんな感じかな。

def sum(n, r)
    if(n > 100)
        return r;
    else
        sum(n+1, n+r);
    end
end

p sum(1, 0)

だが、もっと強者がいた。

p (1 + 100) * 100 / 2

等差数列の和の公式....ボロ負けでした...orz


追記:
twitterでいろいろツッコミをいただいたので、追記。

@littlestarling:
(1..100).inject(0){|i, sum| sum += i} だと宣言してることになるのかな。まあ公式ちゃんと使う方が正しいっすね。

ほう。こんなものもあるのか。ということで調べてみると、Rubyの1.9系には、Enumerateにreduceというメソッドがあり、injectの別名のようだ。これを使うとわずか1行で書ける。

(1..100).reduce(:+)

すばらしい。LISPでこのような問題を解く場合、「Lisp脳」の謎に迫る - Schemeプログラマの発想に記されているように、「データからデータへの変換」を考える。すなわち、1から100までのリストを作って、それをいじって結果を出すという考え方だ。例えばSchemeで書くとしたらこんな感じになる。

(use srfi-1)
(fold  + 0 (iota 100 1))

injectやreduceを使ったやり方は、まさにこの考え方だ。ちなみにreduceに渡している":+"というのは、+演算子のSymbolで、これはSchemeでいうと'+'という関数をFOLDに渡すことに相当する。

最後に、もう一つ。

@hiromiso:
sum(1:100)

GNU Rか... またもや敗北...orz

March 2, 2012

Rubyのlambdaでクロージャを書いてみた

いつの間にかRubyにlambdaができていたようなので、条件反射でいつものクロージャーを書いてみる。

def makefunction
  x = 0;
  return lambda {
    return x+=1
  };
end

f = makefunction;
x = -100;

p f.call;
p f.call;
p f.call;

p x; 

これを実行すると

1
2
3
-100

すばらしい。 だが、この程度であれば1.8以前でもProcを使えばできたことは秘密だ。

def makeproc
  x = 0;
  return Proc.new {
    return x+=1
  };
end

f = makefunction;
x = -100;

p f.call;
p f.call;
p f.call;

p x; 

$ ruby1.8 clojur.rb
1
2
3
-100

だが、Understanding Ruby Blocks, Procs and Lambdasによると、lambdaとProcには微妙な違いがあるようだ。これは後日。

おまけ。Procの中で、self.callを呼べば無名再帰できるんじゃね?と思ったけれど、Proc.selfはObject型でした。残念。

February 5, 2012

Gnuplotの canvas terminalドキュメントの和訳

gnuplot 4.4 document の canvas terminal の所を和訳してみました。かなり意訳になっているので、間違いや勘違いを含んでいる可能性があります。この原文は英語で、http://www.gnuplot.info/docs_4.4/gnuplot.pdf (p.169 - 170)にあります。この邦訳の著作権も原文に準じるものとし、この邦訳によって生じたいかなる損害の責任は負いません。

83.7 Canvas

Syntax: 
      set terminal canvas {size <xsize>, <ysize>} {fsize <fontsize>}
                          {{no}enhanced} {linewidth <lw>}
                          {standalone {mousing} | name '<funcname>'}
                          {jsdir 'URL/for/javascripts'}
                          {title '<some string>'}

ここで、<xsize> と <ysize> は、プロットエリアのサイズをピクセルを単位で指定します。 デフォルトサイズは、standalone モードで、横600、縦400ピクセルです。 デフォルトフォントサイズは10です。 NB: Only one font is available, the ascii portion of Hershey simplex Roman provided in the file canvastext.js. You can replace this with the file canvasmath.js, which contains also UTF-8 encoded Hershey simplex Greek and math symbols.

デフォルトのstandaloneモードは、HTML5の canvas 要素を使ってプロットする JavaScript のコードを含むHTMLページを生成します。このHTMLページは ''canvastext.js' と 'gnuplot_common.js' の2つの JavaScript ファイルをリンクしなければなりません。デフォルトでは、ローカルにあるファイルをリンクしており、一般的な Unixライクなシステムでは、/usr/local/share/gnuplot/<version>/js ディレクトリの中にあります。他のプラットフォームに関しては、installation notesを参照してください。これを変更するには、jsdir オプションに、他のローカルのディレクトリまたはURLを指定します。このURLの指定は、ネットワークに接続されているクライアントマシンにプロットしたグラフを転送するときに使われます。

canvas ターミナルによって全てのプロットにマウスを使うことができます。キーワード mousing を追加すると、standalone モードのプロットの横にマウストラッキングボックスが追加されます。gnuplot は、canvastext.js'と同じディレクトリ、または URL にあるJavaScript ファイル 'gnuplot_mouse.js' とマウスボックスのためのスタイルシート 'gnuplot_mouse.css' へのリンクを追加します。

name オプションを指定すると、JavaScript だけが含まれたファイルを作成します。javascript ファイルに含まれている関数の名前と、 canvas 要素の id は、name オプションに続く文字列になります。以下のコマンドは、

      set term canvas name 'fishplot'
      set output 'fishplot.js'

fishplotという id を持つ canvas に描画する fishplot() という JavaScript で書かれた関数を含むファイルを生成します。 またこの JavaScript 関数を呼び出す HTML ファイルは、前述の canvastext.js をロードしておかなければなりません。 この fishplot を含む最低限の HTML ファイルは以下のようになるでしょう。

      <html>
      <head>
          <script src="canvastext.js"></script>

          <script src="gnuplot_common.js"></script>
      </head>
      <body onload="fishplot();">
          <script src="fishplot.js"></script>
          <canvas id="fishplot" width=600 height=400>
              <div id="err_msg">No support for HTML 5 canvas element>/div>
          </canvas>
      </body>
      </html>