Aug 20, 2017

Raspberry Pi + Raspbian OSで試験運用中

このweblogは9年もの間、玄箱HGの自宅サーバーで運用して来たが、昨年辺りからHDDがすごい音を出すようになり、そろそろハードウェア的に限界が来ていると思っていたのと、少し前にこの玄箱を木製の密閉式のサイドボードに入れるようにしてから、えらく高温になり、その内発火しそうなので、サーバーを引っ越すことにした。

当初、24h運転の自宅サーバーを設置した理由は、weblogを始めようと思ったら、プロバイダーの無料のホームページ設置スペースではMovableType等のCMSが使えなかったからであり、その後、Javaアプレットを公開したり、色々なCGIやJavaのサーブレットを動かして遊ぶようになって手放せなくなったが、現在はそういったことまでできる、自由が効く安価なレンタルサーバーがあるので、自宅サーバーにこだわる理由が無くなった。

しかし、今回はRaspberry Piを購入して、自宅サーバーの運用を継続することに決めた。
あの高価な、少し前まで40万超えだったMathematicaを無料で使えるということで、いつかRaspberry Piを買おうと思っていたのだが、さらに先月、Raspberry Piで個人的に思い入れのあるFreeBSDが動作することを知り、この夏休みにFreeBSDでサーバー構築すべく、Raspberry Piを購入したのである。

最新のRaspberry Pi 3はFreeBSDが未対応ということなので、Raspberry Pi 2を購入した。
microSDカードは、相性があるそうでよくわからなかったので、とりあえず日本製であれば何でも良いかと思って、Amazonで安かったTOSHIBAのMSDAR40N32Gを合わせて購入した。

とりあえず動かしてみようと、セットアップマニュアルに従って、microSDに"NOOBS"を焼き込み、HDMIケーブルでテレビと繋ぎ、電源端子にmicroUSBケーブルを挿してUSB給電可能な玄箱HGを繋ぐと、セットアップ画面が表示された。
OSの選択をしないと先に進まないようだったので、USBマウスを繋いでRaspbian OSを選択すると、1時間くらいしてOSのインストールが終わり、再起動するとRaspbianのデスクトップ画面が開いて、上部のMathematicaアイコンをクリックするとMathematicaが起動したので、とりあえず感動しておいた。

続いて、FreeBSD-11.1-RELEASE-arm-armv6-RPI2.img.xzをダウンロードして、このページに従ってmicroSDに焼き込んで起動すると、テレビにカラフルな四角形が表示されたのだが、SDカードのアクセスランプが点滅を繰り返すばかりで、そこから先に進まなかった。
何がおかしいのだろうと調べると、Raspberry Pi 2 v1.2ではSoCがBCM2836からBCM2837に変更され、ARMプロセッサーがCortex-A7からCortex-A53に変わったので、同じカーネルでは起動できなくなったらしい。
せっかくPi 3より少し割高だったPi 2を買ったのに、ガッカリである。

大量に出回っているPi 3用のFreeBSDはその内正式リリースされるだろうが、主に既にPi 2を使ってるシステムの為に販売されるPi 2 v1.2向けにもリリースされるとは限らないので、FreeBSDのリリースを待たず、Raspbianでサーバー構築することにした。

まだまだ不完全ながら、夏休みを丸々費やして、とりあえずweblogのデータを引っ越して最低限動作するようになったので、Webサーバーをこれに置き換えた。

以下、やったことを大まかに控えておく。

1. VNCの有効化
 最初からRealVNCサーバーがインストールされており、デスクトップの「設定」→「Raspberry Piの設定」→「インターフェース」で有効化するだけだった。

2. aptitudeでmovabletype, apache2, mysql-serverをインストール
 まずupdateする必要があった。
 aptのパッケージにmovabletype 5.2.7があったので、これまでマニュアルインストールして使っていた3.3.5から移行することにした。今はWordPressが圧倒的に人気で、MovableTypeはほとんど使われなくなっているそうだが、MovableTypeはHTMLを静的に生成できるので、依然としてスペックの低いマシンに向いていると思う。
 movabletypeのインストール中に、設定ファイルを自動生成するか何かのダイアログが出たが、自動設定しないを選択した。

3. Apache2の設定
 /etc/apache2/sites-enabled/000-default.conf のDocumentRootを変更
 /etc/apache2/mods-enabled/ にcgid.conf, cgid.loadのsymlink追加
 /etc/apache2/conf-enabled/serve-cgi-bin.conf にアクセス可能アドレス設定

4. MovableTypeの試運転
 mt.cgiにアクセスすると

You don't have permission to access /XXX/mt-wizard.cgi on this server.

 というエラーになるので、
 /etc/apache2/conf-enabled/movabletype-opensource.conf
 の
Require all denied

 の行をコメントアウトしてmt_wizard.cgiを有効にする必要があった。
 (/usr/share/doc/movabletype-opensource参照)

 それから、何故か/usr/lib/cgi-bin/movabletype/にthemesへのsymlinkが無かったのを修正した。

5. MovableTypeのデータベースの移行
 MySQLのデータベースをimportした後、
 https://www.movabletype.jp/documentation/mt5/upgrade/
 の「既存のデータベースを上書きする方式」に従ってアップグレードした。

6. BlogのDesign Themeを"Rainier"に変更
 デフォルトのデザインがもう1つな感じがしたので、定番の1つらしい"Rainier"をインストールした。
 MT5.2対応と書いてあるが、html_head.mtmlの <$mt:StatsSnippet$>がMT6.0以降にしか無いので、コメントアウトする必要があった。
 それから、本文と追記の境界がわからなかったので、間に線を引くようにした。

7. MT-Keystrokes v0.1.5の導入
 keystrokes.plを/usr/share/movabletype/plugins/にコピー
 keystrokes.plは以下の2行をコメントアウト
 ・"return 1 unless $MT::VERSION =~ m(^3\.);"の行
 ・"$eh->error("keystroke id: " . $obj->blog_id);"の行
 MovableTypeの管理画面でテンプレートのComment Formを以下のように変更
 ・<form>タグの直後に<$MTKeystrokes$>を追加
 ・<textarea>タグ内にonkeypress="keystrokes(this.form)"を追加
 ・<input type="submit" value="Submit">タグ(2ヶ所)内にonclick="keystrokes(this.form)"を追加

8. ローカルメールサーバー立ち上げ
 aptでmovabletypeをインストールした時にexim4がインストールされたので、SMTPサーバーはこれを使用した。
 dpkg-reconfigure exim4-configで設定画面を開き、適当に設定した。
 POP3サーバーはDovecotをインストールした。

9. 固定IP化
 /etc/dhcpcd.confの末尾に次の4行を挿入

interface eth0
static ip_address=192.168.0.XX/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1

 (man dhcpcd.confのstaticの所参照)

See more ...

WriteBacks

Aug 10, 2017

野球のポジション当てゲームをプログラムで解いてみた

一昨日、野球のポジション当てゲームというのを知った。

http://heart-quake.com/article.php?p=527より:

1.藤山選手はサードと同じアパートに住んでいるということだ。
2.センターはライトより背は高いが、足はライトの方が早い。
3.鈴木選手の妹さんはセカンドと婚約中だそうで、どうも挙式は来春だそうだ。
4.キャッチャーの長男とサードの次女は同じ小学校の同級生だそうだ。
5.ショートとサードそれに桜井選手の3人はよく揃って競馬に行くそうだ。
6.ピッチャーはとても麻雀が強く、今月も梅田選手と菊池選手から5000円ずつまきあげたそうだ。
7.外野選手のうち一人はどうも木下選手か松村選手らしい。
8.小川選手はどうも奥さんとうまくいっていないようだ。近々離婚するのではないかとの噂がとんでいる。
9.選手達はよく揃ってゴルフに行くが、梅田・藤山・桜井の3選手はどうしてもキャッチャーとセカンドには勝てないようだ。
10.ピッチャーの奥さんはサードの妹さんだそうだ。
11.松村選手はキャッチャーと、又、桜井選手はピッチャーととても仲が良いようである。
12.選手たちのうちで、独身なのは、鈴木・梅田・山田の3選手、それにセンターとライトの5人である。
13.山田選手は桜井選手より背が高く、木下選手は桜井選手より背が低い。しかし、この3人はいずれもファーストより低い。

ここからは、問題文を一部改変しております。
製品をご購入いただくと正式な問題文が閲覧可能です。

14.選手たちのうちで酒を飲まないのは、XXX選手とXXX選手。それにショートの3人だけだそうだ。
15.バッテリーと内野の全員はXXX・XXX・XXXの3選手を除くとみんな外野の小川選手より背が低い。
16.鈴木選手は外野手のX人と一緒に麻雀をよくするそうだ。
こういう論理パズルで、色々制約のあるグループワークで解くもので、何らかの研修とかで使われるものらしい。

これが、色々制約のあるグループワークだから難しいが、一人でやったら簡単に解けるということだったので、上記XXXの部分を入手して、早速その日の夜にやってみたら、1時間くらいかけても解けなかった。

次の日の夜も、前日と同様、「藤山 not 5, 8 > 9, 鈴木 not 4, 4 single, ...」と紙に書き出すと、読み易い文字で書き直した為か、20分くらいで何らか解が出たのだが、解は複数あるような感じで、出した解は別途入手した答えと違った。

本当に解は1つしかないのだろうか?と気になって、今日、次のような簡単なプログラムを書いて探させてみたら、確かに解は1つしか無かった。

#!/opt/local/bin/python3
from itertools import permutations
names = ('藤山', '鈴木', '桜井', '梅田', '菊池', '木下', '松村', '小川', '山田')

def taller(name1, name2):
    dict1 = {'山田':3, '桜井':2, '木下':1}	#13
    if name1 in dict1 and name2 in dict1:
        if dict1[name1] > dict1[name2]: return True
    if name1 in ['XXX', 'XXX', 'XXX'] and name2 == '小川': return True	#15
    return False

def single(name):
    return name in ['鈴木', '梅田', '山田']	#12

def married(name):
    return name in ['小川']	#8

def judge(position):
    name_by_pos = {v:k for k,v in position.items()}

    if position['藤山'] == 5: return False	#1
    if taller(name_by_pos[9], name_by_pos[8]): return False	#2
    if position['鈴木'] == 4 or married(name_by_pos[4]): return False	#3
    if single(name_by_pos[2]) or single(name_by_pos[5]): return False	#4
    if position['桜井'] == 5 or position['桜井'] == 6: return False	#5
    if position['梅田'] == 1 or position['菊池'] == 1: return False	#6
    if (position['木下'] >= 7 and position['松村'] >= 7) \
       or (position['木下'] <= 6 and position['松村'] <= 6): return False	#7
    #8
    if position['梅田'] in (2,4) or position['藤山'] in (2,4) \
       or position['桜井'] in (2,4): return False	#9
    if single(name_by_pos[1]): return False	#10
    if position['松村'] == 2 or position['桜井'] == 1: return False	#11
    if position['鈴木'] >= 8 or position['梅田'] >= 8 or position['山田'] >= 8 \
       or married(name_by_pos[8]) or married(name_by_pos[9]): return False	#12
    if position['山田'] == 3 or position['桜井'] == 3 \
       or position['木下'] == 3: return False	#13
    if position['XXX'] == 6 or position['XXX'] == 6: return False	#14
    if position['XXX'] >= 7 or position['XXX'] >= 7 or position['XXX'] >= 7 \
       or position['小川'] <= 6: return False	#15
    if XXXXXXXXXXXXXXXXXXXXX: return False	#16
    return True

for p in permutations(range(9)):
    position = {names[i]: p[i]+1 for i in range(9)}
    if judge(position) == True:
        print(position)
(上記問題文で伏字にされている部分がわかる部分は伏字にしている)

プログラムのデバッグ中に、次のような表を作ってこれを埋めていく形で解き直したら、10分もかからずに解けた。問題を半分くらい覚えてしまったから早く解けたということもあるが、最初からこうやれば良かったと思った。

藤山 0 00
鈴木00 00
桜井00 000
梅田00 00
菊池0
木下 0 777
松村 0 777
小川 0 00
山田000 0
(1.〜13.まで読んでマークした状態、0は偽、7は7.参照の意)

See more ...

Posted at 21:06 in 数学 | WriteBacks (0)
WriteBacks