petakoneko’s diary

2010-02-04

[モータースポーツ] 2010年モータースポーツカレンダー作ったよ

Googleカレンダー用です。

Googleの公開カレンダー検索が使えなくなり、ネット上で公開してる人も見つからなかったので作ってみた。

来年はどうするかわからないので2010年限定で。気が向いたら来年以降もそのまま使えるようにするかも。

間違いや変更があったら教えてもらえるとうれしい。

2010 motoGP

http://www.google.com/calendar/embed?src=ov4cjmur71vpkr5k7hnffe8edg%40group.calendar.google.com&ctz=Asia/Tokyo

2010 WRC

http://www.google.com/calendar/embed?src=1k43d7bc21u4q393v8qa4g0njg%40group.calendar.google.com&ctz=Asia/Tokyo

2010 Formula NIPPON

http://www.google.com/calendar/embed?src=73r833vapnkcg2pldpl0g17ebc%40group.calendar.google.com&ctz=Asia/Tokyo

2010 Super GT

http://www.google.com/calendar/embed?src=ndl4btj2tmouqn47v2fadg394c%40group.calendar.google.com&ctz=Asia/Tokyo


ちなみにF1はここのを使わせてもらってます。

F1Fanatic.co.uk Formula 1 calendar

http://www.google.com/calendar/embed?src=hendnaic1pa2r3oj8b87m08afg%40group.calendar.google.com&ctz=Asia/Tokyo

2010-01-13

[プログラミング]人生を書き換える人もいるらしい問題

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

良かった、解けて。


最短性は保証してるはず。


0:40開始、1:40終了。ちょうど一時間かかった。

会社で問題見て、あとで暇なときにやろうと思っててさっき始めたから、実際には一時間強ってところかなあ。


試験の形式としてはとても良いと思った。

普段使ってる環境とネットが使える状態でコードを書いて提出するというのは、限りなく仕事でプログラミングする環境に近い。


僕の場合、ネット使えなかったら解けてないしw

std::cinって改行とかどうなるん?(結局std::getline()を使用)とか、gdbで実行時に標準入力をリダイレクトするのってどうやるんだっけ?とか検索した(ちなみにrun < hoge.txt)。

回答
**************************
*S* *$$$$                *
*$* *$ *$ *************  *
*$*$$$* $  ************  *
*$$$ *  $$$$$$$          *
**************$***********
* $$$$$$$$$$$$$          *
**$***********************
* $$$  *$$$$$$$$$$$$$$$  *
*  *$$$$$ *********** *  *
*    *        ******* *  *
*       *                *
**************************
#include <iostream>
#include <cassert>

class Meiro
{
public:
  static const size_t WIDTH_MAX = 256;
  static const size_t HEIGHT_MAX = 256;

  Meiro () 
    {
      start.x = -1;
      start.y = -1;
      goal.x = -1;
      goal.y = -1;
      for (size_t y = 0; y < HEIGHT_MAX; ++y) {
        for (size_t x = 0; x < WIDTH_MAX; ++x) {
          data[y][x] = '\0';
          distance[y][x] = INT_MAX;
        }
      }
    }

  void setStart (size_t x, size_t y) 
    {
      assert (x < WIDTH_MAX);
      assert (y < HEIGHT_MAX);
      start.x = x;
      start.y = y;
    }

  void setGoal (size_t x, size_t y) 
    {
      assert (x < WIDTH_MAX);
      assert (y < HEIGHT_MAX);
      goal.x = x;
      goal.y = y;
    }

  void setData (size_t x, size_t y, char d)
    {
      assert (x < WIDTH_MAX);
      assert (y < HEIGHT_MAX);
      assert (d == 'S' || d == 'G' || d == ' ' || d == '*');
      data[y][x] = d;
    }

  size_t getDistance (size_t x, size_t y) 
    {
      assert (x < WIDTH_MAX);
      assert (y < HEIGHT_MAX);
      return distance[y][x];
    }
  
  void setDistance (size_t x, size_t y, size_t d) 
    {
      assert (x < WIDTH_MAX);
      assert (y < HEIGHT_MAX);
      distance[y][x] = d;
    }

  char getData (size_t x, size_t y)
    {
      assert (x < WIDTH_MAX);
      assert (y < HEIGHT_MAX);
      return data[y][x];
    }
  
  void setRoute (size_t x, size_t y)
    {
      assert (x < WIDTH_MAX);
      assert (y < HEIGHT_MAX);
      data[y][x] = '$';
    }
  
  void trace (size_t x, size_t y, size_t distance) 
    {
      char d = getData (x, y);
      if (d == '*') return;
      if (distance >= getDistance (x, y)) return;
      setDistance (x, y, distance);
      
      trace (x - 1, y,     distance + 1);
      trace (x + 1, y,     distance + 1);
      trace (x,     y - 1, distance + 1);
      trace (x,     y + 1, distance + 1);
    }
  
  bool traceRoute (size_t x, size_t y, size_t distance) 
    {
      if (distance == 0) return true;	// start

      char d = getData (x, y);
      if (d != ' ' && d != 'G') return false;
      if (distance != getDistance (x, y)) return false;
      setRoute (x, y);
      
      if (traceRoute (x - 1, y,     distance - 1)) return true;
      if (traceRoute (x + 1, y,     distance - 1)) return true;
      if (traceRoute (x,     y - 1, distance - 1)) return true;
      if (traceRoute (x,     y + 1, distance - 1)) return true;

      return true;
    }

  void execute ()
    {
      assert (start.x >= 0);
      assert (start.y >= 0);
      assert (goal.x >= 0);
      assert (goal.y >= 0);

      trace (start.x, start.y, 0);
      traceRoute (goal.x, goal.y, getDistance (goal.x, goal.y));

      output ();
    }

  void output ()
    {
      for (size_t y = 0; y < HEIGHT_MAX; ++y) {
        bool needReturn = false;
        for (size_t x = 0; x < WIDTH_MAX; ++x) {
          char c = getData (x, y);
          if (c != '\0') {
            std::cout << c;
            needReturn = true;
          }
        }
        if (needReturn != false) {
          std::cout << std::endl;
        }
      }
    }

private:
  char data[HEIGHT_MAX][WIDTH_MAX];
  size_t distance[HEIGHT_MAX][WIDTH_MAX];

  struct Point {
    int x;
    int y;
  };

  Point start;
  Point goal;
};
  
int main (int argc, char* argv[])
{
  Meiro meiro;

  std::string line;
  size_t y = 0;
  while (std::getline (std::cin, line)) {
    for (size_t x = 0; x < line.length (); ++x) {
      meiro.setData (x, y, line[x]);
      if (line[x] == 'S') {
        meiro.setStart (x, y);
      } else if (line[x] == 'G') {
        meiro.setGoal (x, y);
      }
    }
    ++y;
  }

  meiro.execute ();
}

2007-07-17

[] 24ビットフルカラー != フルカラー

「1677万色あれば人間の目で判別できる全ての色を表現できる」って言った人は誰?

ダイナミックレンジがすごく狭い液晶モニタ内でもバリバリにマッハバンド出てるんですけど。全然足りてないよ。

256段階のグレーの諧調でもマッハバンド出るし、中間色では全然諧調出せないし。

そもそも色によっては同じ色相のままでは全く諧調が作れないものがあるじゃないのさ。


しかし一番多くの諧調があるグレーやRGBのグラデーションでもマッハバンドが見えるのだから、色のサンプリングが悪いわけでもなさそうだ。

「24ビットカラー = 1677万色 = フルカラー = 全ての色を表現できる」というのはオカルトであり都市伝説だよね、もう。


65536色とか256色とか4096色中16色とかデジタル8色とかから比べればフルカラーとか総天然色と言いたかった気持ちはわからないではないけど、もうそろそろ色を24ビット整数で扱うのはやめよう、と思った。

2007-06-10

[][]仮想化が効かない

システムとデータのドライブは分けたいのでこれを行ってたのですが、

http://www.kkoba.com/blog/archives/2007/03/d.shtml

これにより、うちではシステムフォルダ(Windows、Program Files)の仮想化がされなくなっていました。

AppData\Local\VirtualStoreに書き込まれません。限りなくバグくさいですが。

2007-05-15

[][][]X360Cドライバが入らない

解決しました。

手順としてはx360cドライバのReadme.txtの書いてあった通りです。マニュアルはちゃんと読みましょう。恥ずかしい。

f:id:petakoneko:20070515201809p:image

ここでフォルダを指定してはダメで、いったん下の「コンピュータ上のデバイス ドライバの一覧から選択します(L)」を選ばないといけません。

そうすれば次の画面で「ディスク使用」で指定できます。

2007-05-02

[][][]X360Cドライバが入らない

代わりのマザーを購入してVistaをインストールし直して、マザーを交換したらアクティベーションが無効になってしまい電話サポートで解決し、アプリの再インストールもだいたい終わったたものの、(ある意味とても重要な)X360Cドライバが入らなくなってしまいました。

ドライバの更新を行っても、「最適なドライバ ソフトウェアが既にインストールされています」と言われて弾かれる。

f:id:petakoneko:20070503054731p:image

ドライバを削除しても勝手に標準ドライバが入ってしまう。んもー、なにこれ。

(標準ドライバはあまりにひどいのでちっとも最適なドライバじゃないし)

今のところ解決方法見つからず。

それにアクティベーションってもっと賢い方法なのかと思ってたよ。

[][][]Mutexプロキシオブジェクト

Mutexのプロキシオブジェクト(コンストラクタでLock(), デストラクタでUnlock())を作ってみたけど、すごく便利だこれ。

プロキシオブジェクトの厄介な点としてコピーの扱いをどうするかというのがあるけど、MutexのLock状態をコピーすることなんてないしね。

2007-05-01

[][]Windows Vista on AMD Radeon9100IGP

Windows Vistaのインストール中何度もハングして、でもなんとか回避方法見つけたのでインストール成功して、

でも不安定なのでビデオカードを買い換えて安定して動くようになって、

わーいVistaだAeroだと喜んでましたが、まだサウンドまわりがちょっとおかしいので新しいドライバは無いのかなと調べてみたら、

http://support.asus.com/faq/faq_right_second_detail.aspx?kb_guid=03818E7E-E17B-3412-61FC-56ED6D1619B2&model_name=P4R800-V%20Deluxe&SLanguage=ja-jp

マザーボードがVista非対応でした。

Aero非対応とかならともかく、まさかSocket478のFSB800MHz Northwood3.2GHzのPCがOS自体動かないとは思いませんでした。

AMD Radeon9100IGPチップセットの制限だそうで。

http://www.google.co.jp/search?hl=ja&client=firefox&rls=org.mozilla%3Aja%3Aofficial&hs=iAY&q=P4R800+Vista&btnG=Google+%E6%A4%9C%E7%B4%A2&lr=lang_ja

そもそもインストールできないみたいです。

2007-04-30

[][][]スレッドの同期とvolatile

スレッドの同期を作っていてふと不安になったので調べていたら、とてもいい過去ログを発見しました。

http://ml.tietew.jp/cppll/cppll/thread_articles/11677#ar11700

http://ml.tietew.jp/cppll/cppll/article/11701

関数呼び出しが有ることによってメモリアクセス最適化を排除している、というのはたしかに実質的にそのとおりだと思いますが、たとえそうでなくても、マトモな環境であれば、Lock()を跨いでメモリアクセス最適化されないということが保証されているはずです(外部関数呼び出しをしたり、あるいは明示的にメモリバリアを入れることによってそれを保証する)。つまり、システムの提供するmutex lock手段によってで保護されたオブジェクトにはvolatile装飾は付ける必要は有りません。

そうじゃないと、スレッド間で共有するあらゆるオブジェクトに(lockで保護したとしても)volatile装飾をつけなければならないはめになりませんか?

http://www.lambdacs.com/cpt/FAQ.html

Q56: Why don't I need to declare shared variables VOLATILE?

ちなみに、大抵のC++環境でのmutex lockは、保護の対象となるオブジェクトだけでなくメモリの全領域に対してメモリアクセス最適化を排除してしまうことになると思います。

mutexなどの同期オブジェクト自体にはvolatileを付ける必要は無いようですね。ちょっと安心。付いてなくてもバリアやキャッシュクリアなどにより大丈夫なように作られている、と。パフォーマンス的には少し嫌な感じですね。

volatile変数についてちょっと実験してみました。Cygwinのg++(gcc)で試しました。MSVCは立ち上げるのがおっくうなのでテストの類はいつもCygwinでしてしまいます。

main.cpp
 #include <pthread.h>
 #include <unistd.h> // sleep
 
 static /*volatile*/ bool    flag = false;
 
 #define WAIT()  usleep(1)
 
 static void* threadFunc(void* p)
 {
     WAIT();
     flag = true;
     WAIT();
     pthread_exit(0);
     return 0;
 }
 
 int main(int argc, char* argv[])
 {
     pthread_t   thread;
     pthread_create(&thread, 0, threadFunc, 0);
 
     for (;;) {
         if (flag) break;
     }
 
     pthread_join(thread, 0);
 }

これを最適化ありでコンパイルすると無限ループになりました。volatileを付ければ当然ですが終了します。

ここでループを変更してvolatile無しのままループ内で関数f()を呼ぶようにします。

 void f() {}

     for (;;) {
         f();
         if (flag) break;
     }

f()を同じソース内に書くと無限ループ、f()を別のソースに書いてexternすると終了しました。もちろんインクルードファイルに書いてもマクロやインライン化されるなら一緒です。翻訳単位の範囲外にあるかどうかです。

flag変数にstaticを付けているのですが、static変数でもコンパイラは外から変更されないとは限らないと判断したようです(変数を操作するstaticでない関数がひとつでもあれば変更されうるわけです。今回のプログラムでは変更されないのは明らかですが)。

試したバージョンのgccの場合、コンパイラがf()がflagを操作しないことがわからないからflagを再評価するのであって、スレッドや同期のありなしで変数をレジスタに割り付けるかどうかを決めているわけではないようですね。(gccのソースは読んでませんが)

f()が翻訳範囲外でも、もしかしたらリンク時の最適化をかけてしまうとダメになるかもしれません。

元記事*1にあるように、たいていのコンパイラはグローバルデータのレジスタ保持は関数をまたがない、ということですね。

単純な同期なら、mutexなどの同期オブジェクトを使わずにvolatile付きの変数だけでも問題はないのかもしれません。

ただ、コンパイラの最適化はvolatileだけでも抑制できますが、ハードウェアの最適化(アウトオブオーダー実行など)にどうなってしまうかは実行してみないとわかりません。

安全のためには同期オブジェクト使っておくべきですね。

ちなみにこんな単純なプログラムでも、WAIT()を入れないと再現しませんでした(片方のループが先に終わってしまい、一見正しい結果を出します)。マルチスレッドプログラムのデバッグは本当に大変です。


メンバ関数のvolatile

また、メンバ関数のvolatile属性は初めて知りました。クラスのvolatileと組み合わせるAndrei Alexandrescuさんのテクニックはすごく便利そうです。

volatileをつかって、スレッドセーフで、高速で、しかも間違った使い方をしたときにはコンパイルエラーになるようなオブジェクトを作ろうというはなしです。

http://ml.tietew.jp/cppll/cppll/article/11695

ちなみにAndrei Alexandrescuさんの元記事のアドレスは変わっちゃってますので注意です。

http://www.ddj.com/dept/cpp/184403766


Double Checked Locking Pattern

MayersさんのDouble Checked Locking Patternがスレッドセーフではないというのも実験してみました。

Double-Checked Locking, Threads, Compiler Optimizations, and More

http://www.nwcpp.org/Downloads/2004/DCLP_notes.pdf

mainDCLP.cpp
 #include <stdio.h>
 #include <pthread.h>
 #include "singletonDCLP.hpp"
 
 pthread_t   threadA;
 pthread_t   threadB;
 
 void* funcA(void* p)
 {
     char*   pName = static_cast<char*>(p);
     printf("%s - SingletonDCLP::instance()\n", pName);
     Object* pObj = SingletonDCLP::instance();
     printf("%s - instance = %x, value = %d\n", pName, pObj, pObj->value);
 }
 
 void* funcB(void* p)
 {
     char*   pName = static_cast<char*>(p);
     printf("%s - SingletonDCLP::instance()\n", pName);
     WAIT();
     Object* pObj = SingletonDCLP::instance();
     printf("%s - instance = %x, value = %d\n", pName, pObj, pObj->value);
 }
 
 char* a="A";
 char* b="B";
 
 int main()
 {
     SingletonDCLP::initializeLock();
 
     pthread_create(&threadA, 0, funcA, a);
     pthread_create(&threadB, 0, funcB, b);
 
     pthread_join(threadA, 0);
     pthread_join(threadB, 0);
 
     SingletonDCLP::finalizeLock();
 }
singletonDCLP.hpp
 #include <pthread.h>
 #include <stdio.h>
 #include <unistd.h> // usleep
 
 #define WAIT()  usleep(10)
 
 struct Object {
     int value;
     Object() : value(3) {
         printf("Object::Object()\n");
     }
     ~Object() {
         printf("Object::~Object()\n");
     }
 };
 
 class SingletonDCLP {
 public:
     static Object*  instance();
 
     static void SingletonDCLP::initializeLock();
     static void SingletonDCLP::finalizeLock();
 
 private:
     SingletonDCLP();
 
 private:
     static Object*  pInstance_;
     static pthread_mutex_t      lock;
 };
singletonDCLP.cpp
 #include <new>  // 配置new
 #include "singletonDCLP.hpp"
 #include <stdio.h>
 
 Object* SingletonDCLP::pInstance_ = 0;
 pthread_mutex_t SingletonDCLP::lock;
 
 void SingletonDCLP::initializeLock()
 {
     pthread_mutex_init(&lock, 0);
 }
 void SingletonDCLP::finalizeLock()
 {
     pthread_mutex_destroy(&lock);
 }
 
 SingletonDCLP::SingletonDCLP() {
 }
 
 Object* SingletonDCLP::instance() {
     if (! pInstance_) {
         pthread_mutex_lock(&lock);
         if (! pInstance_) {
             printf("operator new\n");
             pInstance_ = static_cast<Object*>(operator new(sizeof(Object)));
             WAIT();
             WAIT();
             printf("operator placement new\n");
             pInstance_ = new(pInstance_) Object;
         }
         pthread_mutex_unlock(&lock);
     }
     return pInstance_;
 }
実行結果
 bash-3.2$ ./dclp.exe 
 A - SingletonDCLP::instance()
 operator new
 B - SingletonDCLP::instance()
 B - instance = 6b07e0, value = 0
 operator placement new
 Object::Object()
 A - instance = 6b07e0, value = 3

Bが初期化されてないオブジェクトを取得してしまってます。危ないです。シングルスレッドのうちに初期化してしまわないとダメです。pInstanceへのvolatileも試してみましたがダメでした。

C++ではDouble Checked Locking Patternはさらに深いレベルでの同期を自分で対処する必要があり、(移植性のある形では)使えません。

*1http://www.lambdacs.com/cpt/FAQ.html Q56: Why don't I need to declare shared variables VOLATILE?

2006-12-05

[] VSUG DAY 2006 Winter

風邪で寝込んでいたので日記がしばらく空いてしまいました。


11/25(土)に、VSUG DAY 2006 Winter に参加してきました。

NyaRuRu 氏の DWM のセッションは予想通りレベルが高く、楽しめました。


また、IronPython のセッションもなかなか面白かったです。

タイトに作ったモジュールをスクリプトでつなぎ合わせる、というのはゲームプログラムでもかなり生かせるはず。

MOD なんかをやるなら必須だし、ゲーム用のツールを作る上でもかなり便利。

次の設計ではゲームのコアはライブラリにして、スクリプトで結合させるつもりでいます。


しかし、VS Express Edition ではいろいろ制限が厳しいかも。うーん。

Wiki

自分のメモ書きに使えるような Wiki が欲しいなあ。

自宅サーバは面倒だし、どこかのホスティングサーバを借りようかと考えています。

2006-11-27

[] ATM

MUFG のオンラインバンクの画面に、「残高不足で引き落としできませんでした。本日21時までに入金すれば再度引き落とし処理します」という表示。まずい、今日はクレジットカードの引き落とし日の 27日だ。

別の口座からオンラインで振込して確認すると入金されてない。

もう15時を回っているので翌日の処理になってしまったようだ。


仕方なく自転車で少し離れた MUFG の銀行 ATM に向かう。しかし入金ボタンが無効になっていて入金できない。

備え付けの電話で確認すると入金は18時までしかできないという。

今日の 21時までに入金しないといけないのだと言うと、コンビニの ATM のうち、「e-net」マークがついているもの(ファミリーマート・サンクスなどとローソンなどの一部)なら手数料はかかるものの 19時まで即時入金できるという(19時以降は翌日扱い)。

なぜ銀行の ATM ではだめなのかと聞くと昔から 18時までで後からできたコンビニ ATM が特別なのだという話。

オペレーターに文句を言っても意味がないし、19時も迫っていたのでコンビニに向かい、210円の手数料を払って無事入金できた。

しかし、19時までシステムが入金できるのならどうせ 24時間動かしている銀行の ATM もせめて 19時までは入金できるようにすればいいのにと思うが、なにか理由があるのだろう。