Amazon Primeを海外で見たい時があるんだけど、制限が掛かっててみれない。VPN Gateとか使わせてもらってたんだけど、最近これも制限されてきたみたいで、大概のホストがダメ。
あきらめるしかないかと思ってHulu.comをクローズド・キャプションで見てたりしたんだけど、自宅をVPNサーバ化すればいいんだよなと思いつき、調べてみたらDD-WRTDD-WRTなる単語を発見。余ってたWZR-HP-G301NHを調べてみるとしっかりサポートされてるみたい。

ということで、これから遊んでみる。

DD-WRTのデータベースから、お目当てのルータを探す。

ファームウェアのファイルが2つあるけど、

  • ? buffalo_to_ddwrt_webflash-MULTI.bin
  • ? wzr-hp-g301nh-dd-wrt-webupgrade-MULTI.bin

説明とファイル名から分かるように、最初に?をインストールして、バッファロー純正からDD-WRTすればよいみたい。
一旦、DD-WRT化してあるなら、DD-WRTの管理画面から?を選んで更新すればよいらしい。

ファームウェア更新後は、ローカル側IPアドレスはデフォルトの192.168.11.1になる。
WAN側IPアドレスは、NUROのルータにぶら下げていたので、DHCPで決まった模様。

デフォルトではpingに応答を返さなかったり、リモートからのWebGUIも使えないようになっているので、
PCのネットワークアドレスを合わせて(DHCPに設定しとけばよい)、直接LANを指してやらないといけない。

pandasで株価データのダウンロード

pandas.io.dataはpandas_datareaderに分離されたらしい。
Yahooとかからデータ落とすだけなら、こんなにカンタンにできていいの?というくらいとてもカンタンにできる。(下の例は日経平均だけど、当然、シンボルを変えれば個別株のデータもダウンロードできる。)


ただ、データの入手元がyahoo.comなので、データはドル建てがキホン(日経平均は円建てのデータだったけど)。円建ての日本株データが欲しかったら、YahooJapan用のReaderを自前でこさえないといけなそう(チラッと中を見た感じ、難しくはなさそうだけど)

from pandas_datareader.data import get_data_yahoo
import pandas as pd

#日経平均のヒストリカルデータをYahooからダウンロード
df = get_data_yahoo(symbols='^N225', start='1/1/1970')
#ダウンロードしたデータをcsvに保存
df.to_csv('n225.csv')

#csvに保存したデータを読み込み
df = pd.read_csv('n225.csv')

Mac/Finderでファイルの移動(Command+C/Command+option+V)

いまだにFinderは使い慣れない。
キーボードショートカットがよく分からない。

Finderの操作をキチンと説明しきってるようなサイトは見当たらないし、特に、ファイルをカット&ペーストして移動するのができなかった。Windowsユーザからすると致命的。
「ファイルのカットは安全のために禁止されている」なんて説明しているブログもあったりして、半ばあきらめてFinderは使わずTerminalで操作したり。

今日になってやっと分かったのでメモしておく

  • ファイルの移動
    • 移動元のファイルをセレクト
    • Command+C (コピー)
    • 移動先のフォルダを開いておく <-- こいつがミソ
    • Command+option+V (ペースト)

ダブルクリックか「新規タブを開く」で、移動先のフォルダを開いておくのがミソ。
移動先は、開かれているタブの直下に固定されているようで、そのタブでどのフォルダを選択していようが関係ない。

ついでに、キーボードショートカットのまとめ:

http://inforati.jp/apple/mac-tips-techniques/system-hints/how-to-use-mac-finder-with-keyboard-shortcut.html#command

homebrewのエラー

年末年始はいつものとおりカミさんの実家。
暇つぶしに用にMacBookAirを持ち込む。

予てから遊んでみようと思っていたpandasを触ろううと、ひさびさにTerminalを立ち上げた。
pythonのバージョンを確認してみると3.3。たしか、最新は3.5だったハズ。
バージョンアップしようとbrewを叩いたらエラーの山が出力される。

my-mba:hoge unya$ brew
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- language/java (LoadError)
	from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/Library/Homebrew/requirements/java_requirement.rb:1:in `<top (required)>'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'

ちょっとググってみると、どうもこの現象が似ているようだ。

http://stackoverflow.com/questions/24652996/homebrew-not-working-on-osx

$cd /usr/local
$git status

を実行してみると、かなりのファイルがmodifiedかuntrackedになっていたので、

$ git reset --hard && git clean -df

を実行してみると、とりあえずエラーは出なくなった。

マトモなソフト技術者ならBNFくらい常識にしよう

 人と具体的な設計のハナシをしていて気になるのは、データの個数をどうとらえているか。1データだけの処理なのか、複数データの処理なのかで、ハナシがまったく変わってくる。たいがい、最初の段階は、大雑把に複数データのハナシをしているんだけど、どこかでそれを1データに絞り込む必要が出てくる。絞込むには、別のデータが必要になったりするんだけど、データの個数を気にしない人は、別のデータが必要になることに気がつかなかったりする。

 また、同じコトバで表わされる処理が、あるところでは1データ用で、違うところでは複数データ用だったりということもしばしば。そういうことが原因で、システム全体ではあちこちで整合性に綻びが出てくる。上位設計がこういう人ばっかり(たいがいそうだけど)だと、後のフェーズでつじつまを合わせなければならない。それで、ここは1ですか複数ですかと聞くことになるんだけど、そもそも気がつかない人たちは何を聞かれているのか分からない。相手がお客さんやSEさんだったりすると、プログラマというのは下らないことばかり聞いてくるアホな人種だと思ってくれたりするのだが、その辺はしょうがないのであきらめることにしている。

 問題はプログラマさんで、この人達には分かってもらわなくてはならない。で、具体的なデータ構造を書かせたりするんだけど、みなさん、設計書のデータ構造は表で書くもんだと思っているので、ホワイトボードに向かって、「データ構造書いてみて」と言っても、躊躇してなかなか動かない。「購入=購入先+{品目+数量}」的な、BNF風味な書き方で例を示してあげると、その後、スラスラ書ける人と書けない人に分かれる。スラスラ書ける人は、BNF風味な表記(データ辞書の表記としてはわりかし一般的だと思うけど)に抵抗がないし、アタマの中が整理されている。書けない人は表記の意味が分からないか、アタマが整理されてない。
 その状態で自分で設計ができているつもになっているのはどういうことか分からないけど、いずれにしろ、BNF風味のデータ表記はコミュニケーションをとる上で有用でもっと使われていいハズだし、「BNFナニソレ?オイシイノ?」なエンジニアは少なくなってほしいと思う。

ラテン方陣(標準形)

 前回、作ったコードで作成できるラテン方陣は、各行を巡回配置したパターンだけでした。実験計画法などで使うにはいいかも知れませんが、配置が単純なので数独のようなパズルには不十分です。
 そこで、今回は標準形のラテン方陣を作成するコードを書いてみました。標準形とはラテン方陣の1行目と1列目が自然な順序(自然数なら1,2,3,...、アルファベットならA,B,C,...とか)で並んでいるモノを指します。すべてのラテン方陣は行または列を入替えることにより、標準形に変換することができます。逆に言えば、標準形が得られれば、行列を入替えることで全パターンのラテン方陣を生成することができるという訳です。

作成したコードは次のとおりです。一応、縦型探索で枝切りしてるつもりなんですけど、配列のコピーのコストでやたらと遅いような気がします。素直に、総当たりでチェックした方が早いかも。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import argparse
import copy

class Square(object):
    def __init__(self, n):
        self.n = n
        self.rows = []
        self.status = 'unknown'
        for i in range(n):
            row = []
            for j in range(n):
                row.append(range(1,n+1))
            self.rows.append(row)
        self.row = 0
        self.col = 0

    def get(self, row, col):
        return self.rows[row][col]
        
    def next(self):
        self.col = self.col + 1
        if self.col >= self.n:
            self.col = 0
            self.row = self.row + 1
        if self.row >= self.n:
            self.row = -1
            self.col = -1

    def _set(self, row, col, value):
        self.rows[row][col] = value

    def _remove(self, row, col, value):
        v = self.get(row, col)
        if type(v) != list:
            return
        try:
            v.remove(value)
        except:
            pass
        if len(v) == 0:
            self.status = 'error'

    def set(self, row, col, value):
        v = self.get(row, col)
        for i in range(self.n):
            if i == col:
                continue
            self._remove(row, i, value)
        for i in range(self.n):
            if i == row:
                continue
            self._remove(i, col, value)
        self._set(row, col, value)

    def print_sq(self):
        for i in range(self.n):
            for j in range(self.n):
                print self.rows[i][j],
            print
    
    def clone(self):
        o = Square(0)
        o.n = self.n
        o.rows = copy.deepcopy(self.rows)
        o.status = self.status
        o.row = self.row
        o.col = self.col
        return o
    
    @staticmethod
    def initial(n):
        sq = Square(n)
        if n == 1:
            sq.set(0,0,1)
        else:
            for i in range(sq.n):
                sq.set(0,i,i+1)
                for i in range(sq.n):
                    sq.set(i,0,i+1)
            sq.row = 1
            sq.col = 1
        return sq


def ReducedLatinSquareGenerator(n):
    queue = [Square.initial(n)]
    while len(queue) > 0:
        e = queue.pop(0)
        if e.row == -1 and e.col == -1:
            if e.status == 'error':
                continue
            e.status = 'ok'
            yield e
        else:
            v = e.get(e.row, e.col)
            if type(v) == int:
                e.next()
                queue.insert(0,e)
                continue
            for i in range(len(v)):
                cp = e.clone()
                cp.set(cp.row, cp.col, v[i])
                if cp.status == 'error':
                    continue
                cp.next()
                queue.insert(i,cp)
        
def main():
    parser = argparse.ArgumentParser(
                description="""ラテン方格標準形作成""")
    parser.add_argument('-n', default=3,
                dest='size',
                type=int,
                help='方格の大きさ')
    args = parser.parse_args()
    if args.size <= 0:
        print "The size of latin-square must be more than zero."
    bar = "-"*args.size*2
    n = 0
    for e in ReducedLatinSquareGenerator(args.size):
        n = n + 1
        print bar
        print "No:%d" % n 
        print bar
        e.print_sq()
    print bar
    print u'The number of reduced latin squares of size %d = %d' % (args.size, n)
    
if __name__ == "__main__":
    main()


実行してみた結果は、次のような感じになります。

$ ./reducedlatinsquare.py -n 4
--------
No:1
--------
1 2 3 4
2 1 4 3
3 4 1 2
4 3 2 1
--------
No:2
--------
1 2 3 4
2 1 4 3
3 4 2 1
4 3 1 2
--------
No:3
--------
1 2 3 4
2 4 1 3
3 1 4 2
4 3 2 1
--------
No:4
--------
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
--------
The number of reduced latin squares of size 4 = 4
$