2013年8月31日土曜日

BlackJackシミュレータ作ってみた

ブラックジャックのそれぞれの手の場合にどれくらいの期待値で
勝てるのかを調べるために、Scalaでモンテカルロシミュレーションプログラムを作ってみた。


  • プレイヤーの手札が8~20の時に対して、ディーラーのアップカードが2~Aのそれぞれに対して、HIT/STAND/DOUBLEDOWNを500000回繰り返したときの期待値を求める。
  • カードは無限にあるものとする(カウンティングの要素は含まない)
  • 乱数は擬似乱数を使用する
  • サレンダーは考慮しない(アーリーサレンダーとレイトサレンダーを分けるのがしんどいので)
  • ディーラーはソフト17スタンドとする

結果



 こんな感じになった。表の各数値はHIT / STAND / DOUBLE DOWN をずっと繰り返したときの期待値です。各セル内の最大値となるものが、最適戦略となる。


他のサイトとの比較

 このあたりに掲載されているベーシックストラテジーと比較すると、一部微妙に違いがあるが、このあたりは乱数の性能の限界なのかもしれない。




作成したプログラム


GitHubに置いています。

2013年4月13日土曜日

家に帰ってブログ書くまでがシェル芸



春爛漫シェル芸人撩乱勉強会に参加してきた。
本日はwget, curl, sedさんたちが活躍する内容。 curlなんて入ってたっけ?と思うぐらい何もしない状態での参加をしてしまった。
 前回と同じく以下、自分の知らなかったことの(断片的な)まとめ。

curl, wget で画像URL収集

curl, wgetでhtmlファイルを持ってきて、そこからは必要なデータを切り出すという作業。
以下はimgタグにある画像データを取ってくる場合。

$ curl http://www.yahoo.co.jp | sed -e 's/<img src/\n&/g' | grep "img src" | grep http | sed -e 's/^[^"]*"//' | sed -e 's/".*$//'

http://k.yimg.jp/images/clear.gif
http://k.yimg.jp/images/clear.gif
http://k.yimg.jp/images/clear.gif
http://k.yimg.jp/images/clear.gif
・・・以下略

上のコマンドを見て気持ち悪いと持った人は正常な感性を持ってると思う。オレならこう書けるとか思った人は変態やと思う。

ひたすらsedでテキストをいじってるけど、このURL抜き出しに必要なsedイディオムは以下のようだった。
  • img srcタグ1つにつき1行にするように抜き出したいタグ(この場合img)の前に改行をぶちこむ
  • 先頭からURLの直前の'"'までと、URL以降を削除する。
正規表現は普通に書くと最長一致となり意図しない部分まで削られてしまうので、 ^[^"]*"のような気持ち悪い書き方になる。これは何とかならない物なのか。

grep -oオプションを使えばもう少し簡単にかけて、以下のような感じになった。
$ curl http://www.yahoo.co.jp | sed -e 's/<img src/\n&amp//g' | grep "img src" | grep -o 'http://[^"]*"' | tr -d \"


-oオプションは行単位ではなく、マッチした部分のみ出力する。これは一番明日から使える内容かもしれない。 

いずれにしろ、こういう書き方はワンライナーだから許されるものであってこんなのがスクリプトとして残っていたら見るほうが発狂しそう。

あと便利なgrepオプションついでに-A -B -C (NUM)オプションも素晴らしい。これはマッチした行の前後もあわせて表示すると言うもの。

% seq 1 10 | sort -R
% seq 100 110                                           
100
101
102
103
104
105
106
107
108
109
110

# マッチした次の行も表示
% seq 100 110 | grep -A 1 105
105
106
# マッチした前の行も表示
% seq 100 110 | grep -B 1 105  
104
105
# マッチした前後の行も表示
% seq 100 110 | grep -C 1 105 
104
105
106


curl, wgetでPOSTリクエスト

以下のようにすれば、wget, curlでもPOSTリクエストが送れる。 cronで定期的にリクエスト投げたいときに使えるかもしれない。
$ wget -O - --post-data=test http://www.usptomo.com/XXXXXXX
$ curl -d test  http://www.usptomo.com/XXXXXX


他にもいろいろあったけど、とりあえず酒が入ってものすごい眠いので今日はここまで!

2013年1月27日日曜日

Windows環境へPython, easy_installインストール手順


Linux環境ならすぐできたけど、Windows環境では環境変数の
設定などが多少必要だったのでメモ

環境:Windows 7
入れるもの: python2.7, easy_install

  1. Python公式サイトからpython2.7インストーラをダウンロード・実行
  2. すべてデフォルトでインストールすると、C:\Python27以下にディレクトリ・ファイルが生成される。
  3. 環境変数PATHに"C:\Python27"と"C:\Python27\Scripts"を追加。
  4. 環境変数PYTHON_HOMEにも"C:\Python27"追加。
  5. コマンドプロンプトからpythonと実行すると反応があることを確認。
以上でpythonインストール完了。
ついでにeasy_installも入れる。
  1. このWebサイトからez_setup.pyをダウンロード
  2. python ez_setup.py でインストール
  3. コマンドプロンプトからeasy_installと実行すると反応があることを確認。
以上




2013年1月2日水曜日

cmdおみくじ

正月で暇だからコマンドプロンプトで貼り付けたらおみくじの結果を表示するワンライナー書いてみた。 シェルだとすぐにできるけどDOSのコマンドだとどうやっていいのかなかなか分からなかったので、メモ代わりに残しておく。
SET /A R=%RANDOM% % 6+1 >null & for /f "tokens=%R%" %i in ("大吉 中吉 小吉 末吉 凶 大凶") do echo おみくじの結果は"%i"です。

おみくじの結果は"中吉"です。

2012年12月8日土曜日

シェル芸人への道


第2回シェル芸人養成勉強会に参加してきた。
hbsstudyハンズオンにも参加していたので、なんとなく雰囲気が掴めていて前回よりついていけたような気がする。 前回と同じく以下、自分の知らなかったことの(断片的な)まとめ。

パイプステータス

パイプを何個もつなげると、最後の終了ステータスしか分からないと思っていたが、
実はPIPESTATUSに最後のステータス以外も配列として格納されている。
% echo hoge | cat
hoge
% echo hoge | cat | cat | cat | cat
hoge
% echo ${PIPESTATUS[@]}
0 0 0 0 0
% echo hoge | cat | cat error | cat | cat
cat: error: No such file or directory
% echo ${PIPESTATUS[@]}
0 0 1 0 0

フィールドを指定したソート

-kn,m (nは開始フィールド、mは終了フィールド)オプションでソートに使用する基準を指定できる。
-kオプションを使うことは知っていたけど、このあたりの理解が曖昧になっていた。
% cat hoge
a 12
a 13
b 13
a 432
b 111
b 43
# フィールド1番目、2番目の順でそれらをキーとしてソート
% sort hoge | sort -k1,1 -k2,2nr
a 432
a 13
a 12
b 111
b 43
b 13

ランダムソート

要素をランダム(ハッシュに応じて)ソートする。
これはソートと言っていいのか?という疑問はある。
% seq 1 10 | sort -R
5
9
1
2
6
3
10
8
4
7

grep検索パターンをファイルから指定

-fオプションを使うことにより、検索するパターンをファイルから取得できる。これは便利。
% cat fuga
hoge
fuga
piyo
% cat fuga2
fuga
piyo
piyopiyo
# fuga2の内容をパターンとしてfugaからgrep
% grep -f fuga2 fuga
fuga
piyo

プロセス置換

これを一般的になんて表現したらいいのか分からないけど、以下のようにするとファイルに出力を意識することなく、ファイル出力されたものとして他のコマンドに結果を渡せる。
# 裏側ではファイル出力してるのやろうけど、使用者からは意識しなくて言いと言う意味
(ご指摘を受けたので修正)

以下のようにすると、プロセスの入出力をファイルのように取り扱うことができる(ファイルは出力していない)。
% cat hoge
a 12
a 13
b 13
a 432
b 111
b 43
% wc <(cat hoge)
      6      12      32 /dev/fd/63

どれも明日使える内容ばかりですね!!

しかしこれくらいで感心しているようでは、シェル芸人の道のりはまだまだ遠い。。

2012年11月20日火曜日

[Android] AVDの作成時に"Error: null"と表示されて作成失敗する。


 Androidのエミュレータを作成するときに作成ボタンを押しても反応せずに、 "Error:null"とだけログに表示される。


 困ったときのStackOverFlowがやはり役に立って、このあたりの回答と参考にすると、 結局のところ環境変数ANDROID_SKD_HOMEに.androidの上のディレクトリ(\Users\toyuserなど)を指定してやればこのエラーは出なくなった。


 問題はなんで今まで作成できたものが出来なくなったのかは分からないけど、とりあえず解決したらかクローズ。

2012年11月9日金曜日

[Android]スライドで大きさを変えられる可変ビュー作ってみた


Androidっていわゆるスライドバーみたいな感じでビューの大きさを変えることって
標準のウィジェットでは用意されていない。

やからスライド(ドラッグ)で大きさを可変にできるビューを作ってみた。

なまえは適当にSlideBarDrugViewControllerとしてみた。
ソースはコチラ(Github)。以下は使い方の簡単なメモ。

レイアウト

スライドバー用のビューと、その上下にビューを用意する。
今回は例なのでビューの種類は何でもいい。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello"
        android:id="@+id/view0"
        android:gravity="center" />

    <TextView
        android:id="@+id/view1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="SlideBar"
        android:background="#6090ef"
        android:gravity="center" />
    
    <Button
        android:id="@+id/view2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="BottomView" />


</LinearLayout>


MainActivity

Mainのアクティビティにレイアウトを読み込ませる。
以下の2点を使用する。
  • (1)で書かれている4つの引数を与える
  • (2)のようにonTouchイベントをcontrollerに渡す

public class SlideBarWidgetActivity extends Activity {
    
 Context context;
 SlideBarDrugViewController controller;
 View upperView;
 View slidebarView;
 View bottomView;
 
 
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        upperView = (View)this.findViewById(R.id.view0);
        slidebarView = (View)this.findViewById(R.id.view1);
        bottomView = (View)this.findViewById(R.id.view2);
        context = this;
        
    }
    
 public void onWindowFocusChanged(boolean hasFocus) {
  WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  Display display = wm.getDefaultDisplay();
  final int screenHeight = display.getHeight();
  
        Rect r = new Rect();
        this.upperView.getGlobalVisibleRect(r);
  if(controller == null){
      /**
  * (1)以下の4つの引数を与える
  * drugView 可変ビュー(スライドバーの上部ビュー)
  * slideBarView スライドバーとなるビュー
  * minpx 可変ビューの上部(top)の絶対座標
  * maxHeight スライドバーが下に動く最大サイズ。画面全体の大きさを入れると最下端まで移動させられる
  */
   controller = new SlideBarDrugViewController(upperView, slidebarView, r.top, screenHeight);
  } 
 }
  
 @Override
 public boolean onTouchEvent(MotionEvent event){
           // (2) onTouchイベントをcontrollerに委譲
   return controller.onTouchEvent(event);   
 }
    
}

実行結果

画像では分かりにくいけど、ScrollBarをスライドさせるとそれにあわせて上下のビューの大きさが変化する。