(未完成)やってみた。麻雀の上がりチェックプログラム

洗濯の合間1時間ほどでできたところまでです。
問題の要件的には未完成で、重複がでる状況があり、コードの最後に書いてあります。

基本のアルゴリズムは簡単です(ただし七対子チェックは入ってません)。

  • 全体的には、各通りツモってみて、その14牌で上がりパターンかチェックして、上がってれば出力する
  • 上がりチェックは、まず頭の対子をすべて列挙し、各対子に対しそれを除いた12牌で4面子になるか検査する

コードはPythonで、generatorを多用しています。
一番時間かかったのは用語選びでしょうか。呼び方がわからないものもありました:

  • 手配+ツモ牌 のことをなんて呼ぶのだろうか
  • 面子と対子(や単騎、カンチャン、両面なども)といった組になるものをなんと呼ぶのだろうか

識別子は漢字で書けばよかったかな(とはいえgoogle入力も麻雀用語には強くないようで、読みからは変換できないので大変ですが)。

以下コード:

# -*- coding: utf-8 -*-

class Hai(object):
    def __init__(self, num, tsumo=False):
        self.num = num
        self.tsumo = tsumo
        pass
    def __eq__(self, other):
        return self.num == other.num and self.tsumo == other.tsumo
    pass

def main():
    tehai_str = raw_input("haipai> ").strip()
    tehai = parse(tehai_str)
    tsumo_list = [Hai(i, True) for i in range(1, 10)]
    # TBD: validate: count of same num <= 4
    for tsumo in tsumo_list:
        tsumotehai = rihai(tehai + [tsumo])
        for toitsu, rest in iter_toitsu(tsumotehai):
            for sumentsu in iter_allmentsu(rest):
                print(format_tenpai(toitsu, sumentsu))
                pass
            pass
        pass
    pass

def parse(tehai):
    if len(tehai) != 13: raise Exception("tehai should be 13 hai")
    return [Hai(int(tehai[i])) for i in range(len(tehai))]

def rihai(tsumo_and_tehai):
    return sorted(tsumo_and_tehai, lambda a, b: cmp(a.num, b.num))

def iter_toitsu(ritsumo):
    same = []
    for i in range(len(ritsumo) - 1):
        if ritsumo[i].num == ritsumo[i+1].num:
            toitsu = ritsumo[i:i+2]
            rest = ritsumo[:i] + ritsumo[i+2:]
            if toitsu in same: continue
            same.append(toitsu)
            yield (toitsu, rest)
            pass
        pass
    pass

def is_juntsu(mentsu):
    return (mentsu[0].num + 1 == mentsu[1].num and 
            mentsu[0].num + 2 == mentsu[2].num)
def is_kotsu(mentsu):
    return mentsu[0].num == mentsu[1].num == mentsu[2].num
def is_mentsu(mentsu):
    return is_juntsu(mentsu) or is_kotsu(mentsu)

def pick1(hailist):
    for i in range(len(hailist)):
        yield (hailist[i], hailist[:i] + hailist[i+1:])
        pass
    pass

def iter_allmentsu(rest):
    if len(rest) == 0:
        yield []
        return
    a = rest[0]
    r1 = rest[1:]
    same = []
    for b, r2 in pick1(r1):
        for c, r3 in pick1(r2):
            mentsu = [a, b, c]
            if mentsu in same: continue
            same.append(mentsu)
            if not is_mentsu(mentsu): continue
            for allmentsu in iter_allmentsu(r3):
                yield [mentsu] + allmentsu
                pass
            pass
        pass
    pass

def format_tenpai(toitsu, sumentsu):
    return (format_group(toitsu) + 
            "".join(format_group(mentsu) for mentsu in sumentsu))

def format_group(group):
    if any(hai.tsumo for hai in group):
        return "[%s]" % "".join(str(hai.num) for hai in group if not hai.tsumo)
    else:
        return "(%s)" % "".join(str(hai.num) for hai in group)
    pass

if __name__ == "__main__": main()

# TODO: unify tamen machi: 1113335557778 makes same two pattern
# TODO: unify juntsu/kotsu order: 1111222233339 makes same two pattern but different order 

Windows7でHYBRID W-ZERO3をインターネット共有するのに苦労した

http://willcom-blog.com/archives/2010/01/00484.phpを読んでやってみても全く上手くいかない。色々調べたりした結果、なんとかWindows7標準UIで、Bluetooth PAN接続できるようになりました。

以下、ハマった点

  • デフォルトのアイドル時間設定が1分なので長くしておく
    • "スタート"-"設定"-"システム"-"バックライト"/"パワーマネジメント"の時間を5分とかにするか、切る
  • ペアリングするときのパスワードの入れ方
    • Windows7には自動生成したパスワードを表示して電話側にいれさせるのが一番上にきてるが、それだと入力が間に合わなくタイムアウトする
    • タイムアウトしたらまた繰り返せばいい
    • 二番目の自分で設定するようにする
  • バイス一覧で、ダブルクリックしてはいけない
    • 一覧上でシングルクリックすると、上のツールバー?に「接続方法」が出てくる。その「アクセスポイント」を選ぶ
    • ダブルクリックで出てきたダイアログの「接続」はモデム接続のためのもので、PANとは無関係

手順

1.HYBRID W-ZERO3Bluetoothを有効にする。

2.Windows7のタスクバーのBluetoothアイコンをクリックすると出すメニューから、「Bluetoothバイスの表示」を選ぶ

3.ダイアログのツールバー?から「デバイスの追加」を選ぶ

4.「WS027SH」が見つかるので選択して「次へ」


5.次のダイアログで、「デバイスのペアリングコードの入力」を選ぶ

6.W-ZERO3側に入れるコード(自由に決めていい)を入れ、「次へ」を押します


7.W-ZERO3で同じコードをいれ下の「次へ」を押す。
http://willcom-blog.com/archives/2010/01/00484.phpの7

  • 注: ソフトキーボードのEnterでは入力されません

ペアリングはタイムアウトなどして失敗しやすいです。失敗したら3から繰り返します。
成功すると以下のような画面が出ます。


8.デバイス一覧に、WS027SHが追加されているので、それをシングルクリックし選択します

  • 注: ダブルクリックしてはいけません(これをやると別な道にハマります)

9.選択するとツールバー?に、「接続方法」メニューが出ます。その「アクセスポイント」を選べばインターネットにつながります。


二回目以降は、WZERO3側で、「インターネット共有」を実行し、そのあとWindows7側で「アクセスポイント」を選ぶことになります。

感想

電話としては色々問題ありだけど(BTヘッドセット接続が有効な状態でBluetoothをつなげたまま、電話かけてベルが鳴ったら即切るとフリーズするしね)、設定が面倒なもののルータとしてはなかなかいい感じでした。

cygwin-1.7.1になったついでにminttyに乗り換えた

cygwinでパッケージを追加しようとしたら、setup.exe更新の警告が出たので、公式からダウンロードしてアップデートかけたら、普段使っていたターミナルckが立ち上がらなくなりました。

バージョンを意識してみるとcygwin1.7系になっていて、検索かけると年末の記事でみなck3が動かなくなってたらしい。ck2はうごくとか。

cygwin-1.7の大きな変更はutf-8で、公式のターミナルを試すと、確かにlsで日本語表示も日本語入力も、日本語ファイルのタブ補完もできる。ただ、このターミナルの難点はコピペがしにくいところです。

そこで、cygwinパッケージにあるminttyを使ってみました。以前試したときは日本語関係がダメダメだったが、UTF-8化されたならうまく行くのではと。そしてその予想通りでした。

setup.exeでminttyのパッケージを入れると、スタートメニューのCygwinの中にショートカットが追加されます。ターミナルを起動するには、それを実行すればいいです。

Optionsで、フォントを「MSゴシック」10ptに変え、透過を「Med」に、マウスを「Copy on select」にし、右クリックを「Paste」に割り当ててました。上のように日本語表示も入力もTAB補完もOKです。

基本的にckで必要だったことはすべてできたので、ターミナルはこのminttyに乗り換えました。



minttyがckと大きく違うのは、ckが自動文字判定してくれる点です。たとえばWindowsではjavacコマンドはエラーメッセージをSJISで出力します。ckだとこれはふつうに表示してくれますが、minttyでは文字化けします。(ちなみに"-J-Dfile.encoding=UTF-8"オプションをつければメッセージはUTF-8で出せます)。

Virtual Routerを使ってみた

Windows7専用ですが、無線LANバイスをシェアしてWindows7機を無線LANルータ化してくれるプログラムVirtual Routerを試してみました:

入れたのはUL20A(Windows7 Home Premium 64bit)です。結果としては満足でした。USBアクセスポイントでよくあるブリッジ式ではなく、ホストPCの接続先とは別のプライベートネットをつくり、接続したマシンには(DHCPで?)ブリッジせずに独自にIPを振ってくれたからです。暗号化方式は選択肢はなくWPA2になります(なのでDS LitePSPではつなげないですが)。

インストールすると、"Virtual Router Manager"がメニューに追加されるので、そこで8文字以上のパスワードを入れて、"Start Virtual Router"ボタンを押すだけで、無線アクセスできるようになります。PCで接続すると以下のようにアイコンが追加されます。

この窓は閉じてもサービスとして動いてるので大丈夫です。止めるときは"Stop Virtual Router"ボタンを押せばOKです。

ここに接続したPC(WindowsXP)の設定では、このときはホストPC側のIPアドレス192.168.137.1がgateway, DNSに設定されました(ホストのWindows7の通常のIPアドレスは192.168.10.23でした)。ちなみに、以下、確認したことです:

  • ホスト側で(ファイアウォールブロックを解除しておいた)railsを起動し、http://192.168.137.1:3000/ でXP側からブラウザでアクセスした
  • ホスト側でVirtualBoxSSHを2122へポートフォワードしかつ2122をファイアウォールを解除し、XP側から192.168.137.1:2122にPuTTYで接続した
  • 有線接続へ送る無線LANルータにした: ホスト側の無線接続を切ってLANケーブルでインターネット側に接続し、Virtual Routerを立ち上げ、XPから無線でVirtual Routerに接続してインターネットアクセスした

ソースコードC#で書かれています。ソースではWlanapi.dllのDllImportが大部分でしょうけど。DOT11_CIPHER_ALGORITHMとかあるので、WEPでも選べるようにしたらDSとかでもつかえるようになるのかな。。。

XMouse設定ツールにGUIをつけてみた

Windows7用X Mouse設定ツール(コマンドライン)を作ってみた - ラシウラのX-Mouseレジストリ設定ツールにGUIをつけてみました。
GUIのライブラリは、Windows7に入ってるWPFを使いました(これも初挑戦か)。.NET SDKは不要なままです。

exe実行で出るWindow


saveボタンを押した後出るログオフするかどうかのダイアログ

コマンドライン機能はそのまま残してあります。

リソース

(追記: アイコンイメージを加え、見た目は若干変えました)

ローカル変数の型は明示するのをやめ、なるべくvarを使うようにしました。

C#からのログオフ処理は、.NET Lock, Logoff, Reboot, Shutdown, Hibernate, Standbyを参考にしてます。

また、WPFC#で使う方法は、http://msdn.microsoft.com/ja-jp/library/ms752324.aspxから調べていきました。いまいちよい書き方がつかめてません(全部windowのコンストラクタ内で作れないかな...)。

Windows7用X Mouse設定ツール(コマンドライン)を作ってみた

(追記: GUIつけました→ XMouse設定ツールにGUIをつけてみた - ラシウラ)

UL20A Windows7セットアップ - ラシウラのXMouse化ですが、Vistaのときでも同じことやっていて、いちいち覚えてられないので、C#でX-Mouse設定のレジストリをいじるコードを書きました(UL20Aでの初プログラミングです)。このツールは、コンソールで使うようになってます。

ビルド

XMouse.exeのビルドは、上記gistからrawでファイルを落としてから、cscにかけるだけです。

cygwinがあれば、以下の二行を実行すればいけるでしょう:

wget http://gist.github.com/raw/247329/cb6c5cf89c8b9453d502310fb4e6a6c2b4b4f78b/XMouse.cs
/cygdrive/c/Windows/Microsoft.NET/Framework64/v3.5/csc.exe XMouse.cs

また、Windows7標準添付のPowerShellを使うなら、以下の二行で同じことができます:

(New-Object System.Net.WebClient).DownloadFile("http://gist.github.com/raw/247329/cb6c5cf89c8b9453d502310fb4e6a6c2b4b4f78b/XMouse.cs", "XMouse.cs")
C:\Windows\Microsoft.NET\Framework64\v3.5\csc.exe .\XMouse.cs

(gistは編集するとrawのURLが変わるため、実際のXMouse.csのURLは違うかもしれません。また環境によっては、csc.exeのありかは、Framework64がFrameworkだったり、v3.5がv3.0だったりするかも)

使い方

注: 設定変更後にマウス設定が機能するのは、いったんログアウトして再ログインしたときになります。

ヘルプと現在のX-Mouse設定

(引数なしで実行)

$ ./XMouse.exe 
Usage: XMouse [on [NUM]|off]
Options: 
 on: follow mouse activation
 on NUM: follow activation then auto raise after NUM msec
 off: disable follow activation/auto raise
Current XMouse Setings:
  Follow Activation: True
  Auto Raise: True
  Raise Time (msec): 500
自動フォーカスを有効にする
./XMouse.exe on
自動フォーカスに加え、500msec後にオートレイズを有効にする
./XMouse.exe on 500
X-Mouse設定をやめる
./XMouse.exe off

ソース

感想

cscでは、

masks[0] |= 0x40

コンパイルがとおるのに

masks[0] &= ~0x40

コンパイルがとおらないんだなあ。

Windows7で初BSOD

VirtualBox-3.1.0で、ゲストubuntu amd64を立ち上げたまま、ゲストubuntu x86を立ち上げようとしたらおきた。


3.1.0でゲスト→ホストでクリップボード共有できてる模様。以下はゲストからコピーしてホスト側でペーストした現在の.emacs

(set-language-environment "Japanese")
(prefer-coding-system 'utf-8-unix)
(set-keyboard-coding-system 'utf-8-unix)
(set-terminal-coding-system 'utf-8-unix)
(toggle-input-method nil)
(global-set-key "\C-q" 'toggle-input-method)
(global-set-key [delete] 'delete-char)
(global-font-lock-mode t)
(setq indent-tabs-mode nil)
(setq make-backup-files nil)