2011年11月29日火曜日

パズル:おいらの回答

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
one offやりまくってしまった。orz ideaとしてはheadとtailをとって短くしていく、tailとheadを入れ替える、ということ。再起が分からない人にはかけないやつね。
#include 
#include 
#include 


void reverse (char *str) {
  char head, tail;
  int len;


  len = strlen(str);
  if (len == 0){
    return;
  }
  if (len == 1){
    return;
  }

  tail = *(str+len -1);
  *(str+len -1) = '\0';
  head = *str;
  reverse(str+1);
  *(str+len -1) = head;
  *str = tail;
  return;
}

int main (int argc, char *argv[]) {
  if (argc *lt;= 1) {
    printf("give me a string\n");
    exit(1);
  }
  char *str = argv[1];

  reverse(str);
  printf("%s\n", str);
  return 0;
}
思ったこと:

strlenを使ってよい(というか仕方ないだろう)はどーなのでしょうか。中身loopだからこれ実行したらO(n^2)だよ、多分。

まあ、パズルだから許されるだろうけど、職場で同僚がこういうコードを書いていたらヤバい。なぜなら:

from ゲリラ的雇用面接のすすめ 関数の実行速度は充分速いか? strlen を何回呼ぶ事になるのか考えてみよう。 かつて私はO(n)であるべきstrrevのアルゴリズムがO(n^2)になってしまっている アルゴリズムを目にした事がある。彼らは繰り返しの strlen をループの中で呼ん でしまっていたのだ。 まあ、問題を
void reverse (char *start, char *end) {
    return;
}

とか書き換えればいいのですが(C++のイテレータチックだな)そうすると問題が変わってしまう。

やる気に関する驚きの科学 (TED Talks)に出てくる、この絵の問題のようなものだ。

オリジナルCパズルの問題は前者、書き換えたものはfor dummiesになっているのではないかと思う。

C言語パズル?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
reverseを下請け函数なし、loopなし、memmove/memcopyなしで実装せよ
#include 
#include 
#include 


void reverse (char *str) {

  /* place your code here. */

  return;
}

int main (int argc, char *argv[]) {
  if (argc <= 1) {
    printf("give me a string\n");
    exit(1);
  }
  char *str = argv[1];

  reverse(str);
  printf("%s\n", str);
  return 0;
}

2011年11月23日水曜日

tumblr関連のスクリプティングまとめ・反省

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
唐突にtumblr関係のプログラムをごにょごにょしたので、その簡単なまとめと反省。

コードはgithubに置いてある。

メモを見ると
Goal
非同期書き込み非同期読み込み、重複contentなしのtumblr client
pointされている画像とかも表示できる(twitterのpicsとか)
らしい。


  • 最初の頃はUIを作る気でいた。面倒なのでpythonを使うつもりでいた。
  • getをかけている間固まるのが厭だったので、twistedを選択。(まあまあの決断かな。遠い未来は分からないので悪い決断出なければよしとすべきだろう。)
  • pyqtをインストールできないのでwxを試す。
  • とっつきはwx.html.windowを使ってレンダーしたのだったが、依存する画像データのメモリ渡しが出来ない様だったので捨てる。このままでは表示系がないのでproxyとして実装して、UIは後回し。(これはよい決断だったと思う。)
  • とりあえず動かしたproxyでもfirefoxの読み込みの遅さが改善されて驚く。どういう作りなんだか。IPv6がらみ??(根拠なし)
  • proxy上で特定のhostに関してhookするやり口はよかったのだが、hostにマッチする方法がやりすぎだった。
  • proxyとcacheのプロセスを分けたのは正解だった。pluginも分離すべきかもしれない。repが短くなりデバッグがやりやすい。

  • dashboardの取得でハマる。ブラウザのクッキーを覗き見して使うのではなくてapiを使うべきだった。(反省)

  • twisted.web.client.getPageとかでのヘッダーの扱いで思い込みが多かった。(反省)
    • uaやcookieを渡しても書いてくれるだろう→ダメ。
    • content-typeを付けてくれない! c.f. urllib.openurlは勝手にpostにしてくれるし、コンテントタイプを付けてくれる。
今後
  • tumblr api v2はoauthなのだが対応するのか? メリットデメリットは?
  • package cacheデータの置き場所とか
  • prefetchの機能改善:
    • 現状、/api/dashboardを読み込んだときのxmlのデータでpointされる画像しか拾っていない
    • dashboardのhtmlをlocalで生成する。(/dashboard読み込みの遅さを改善する。)
    • endless scrollに対応する。
    • cacheされていなかったことでmissしたcontentもcacheに書き込む。
  • reblog graphの生成とか重複排除とか・・・たぶんpostのdbが必要になる。
  • UIどうしよう?外部プレーヤの起動もやってみたい。

2011年11月8日火曜日

先日のLVM関係の騒ぎのときに拾ったpdfより

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

まあ、デバッグとかと同じで、想定している値と食い違った値を出している箇所を特定する作業が必要なのですが、
レイヤーごとにどうなっているか、下からチェックしなさい、といっている。


出典:LVM2 – data recoveryという、Milan Brož(mbroz@redhat.com)さんがが書いたプレゼン。

2011年11月2日水曜日

VMware Player 上のguest OSに生LVM Volumeをマウントする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
HostはScientific Linux 6.1です。VMWare Playerは4系列。

まあ、ここにある結論をそのまま使っただけですけどね。


結論:ディスクイメージの元のHDDのジオメトリが分からなければ、総セクタ数としてファイルサイズ÷512(の小数点以下を切り捨てた整数)を総セクタ数として記述しておき、セクタ数、ヘッド数、シリンダ数は“0”としておけばいい。その状態で仮想マシンを立ち上げると、適当なセクタ数、ヘッド数、シリンダ数をVMwareの仮想ディスクドライバが決定してくれる。もし、定義ファイルに“0”のままでは気になるのであれば、hdparmで得たドライバが決定したジオメトリの値を定義ファイルに書き込んでおけば良い。というところだろうか。

今時のコンピュータでは、ディスク上の情報の位置は先頭からのセクタ番号だけアクセスして、昔の様にヘッド番号とかシリンダ番号、トラック内のセクタ番号を使ってアクセスしないので、これでも問題ない、ということかもしれない。(fdiksがHDDの物理ジオメトリは無視して、セクタ数を63、ヘッド数を255にしてパーティションするのも、この考え方であれば納得できる。)


実作業としては:

1. なんか適当にtemplateとなるvmdkファイルを作る。metadataの中身はこんな感じ。容量指定はなんでもいいが、preallocateしたほうがよいだろう。
# Disk DescriptorFile
version=1
encoding="UTF-8"
CID=8d03ddbb
parentCID=ffffffff
isNativeSnapshot="no"
createType="twoGbMaxExtentFlat"

# Extent description
RW 208896 FLAT "Win7Template-f001.vmdk" 0

# The Disk Data Base 
#DDB

ddb.adapterType = "lsilogic"
ddb.geometry.sectors = "32"
ddb.geometry.heads = "64"
ddb.geometry.cylinders = "102"
ddb.uuid = "60 00 C2 9f 1a d0 8e 7c-04 3a 03 fe fe 0f 15 52"
ddb.longContentID = "b0e2674d8fa7d5101c4addeb8d03ddbb"
ddb.virtualHWVersion = "8"

2. 上記のファイルをLVMのLVの位置・容量に合わせて書き直す。
# Disk DescriptorFile
version=1
encoding="UTF-8"
CID=51be770e
parentCID=ffffffff
isNativeSnapshot="no"
createType="twoGbMaxExtentFlat"

# Extent description
RW 629145600 FLAT "/dev/vg_akagi/ntfs" 0

# The Disk Data Base 
#DDB

ddb.virtualHWVersion = "8"
ddb.longContentID = "e46ca8b5dbfce4905651da8a51be770e"
ddb.uuid = "60 00 C2 9f 1a d0 8e 7c-04 3a 03 fe fe 0f 15 52"
ddb.geometry.cylinders = "0"
ddb.geometry.heads = "0"
ddb.geometry.sectors = "0"
ddb.adapterType = "lsilogic"

3. VMware Playerを実行するUserをdisk groupに追加。さすがにrootにするのは萎える。これをやっておかないと、/dev/vg_akagi (実態は/dev/dm-XXX)などにはアクセスできない。


4. guestの設定を編集し、既存のharddisk imageとして追加する。

5. Playerを起動してguestを動かす。
注意: guestがマウントしている間はhost上でマウントしないこと!!!ぶっ壊れるよ!1つのdiskに対してファイルシステムが起動することになるから。なので間違ってもfstabに登録するとかバカなことはしないように。