pg09

テーマ:数値計算とプログラム

内容 確率シミュレーション

扱う言語は Python を予定していたが、 Scala に変更する

http://qiita.com/oubakiou/items/31fd45ca337d76113a1e Scala採用企業のまとめ

前振り: iPad のダイスアプリ紹介

統合開発環境(IDE: Integrated Development Environment )

eclipse の起動と設定

スタート → コンピュータ → ボリューム(D:) → scala → eclipse.exe をダブルクリックで起動

プロジェクトの保存先の設定

標準の保存先が ../workspace となっているが、変更する。

Browse…ボタンを押して、アカウント名のフォルダ(氏名または学籍番号)を選択 →

マイドキュメント を選択 → 新しいフォルダの作成 ボタンを押す →

フォルダ名を pg09 に変更する → OK を押す

→ OK を押す

eclipse が起動する。

Scala 開発環境の設定

eclipse
 -> Package Explorer(パッケージエクスプローラ)を右クリック
->  New(新規)
-> Other...(その他)
->Scala Wizards(ウィザード)
-> ScalaProject(プロジェクト) → Next(次へ)
Project name(プロジェクト名) pg09 と入力 → Finish(完了)

練習用アプリケーション作成:

パッケージエクスプローラ から
pg09 プロジェクト 
src フォルダ
→右クリック Scala App(アプリ) 作成
name(名前)  Test と入力
Finish

2017年度用変更点:

↓のREPLの準備はスキップする。

REPL(Read Eval Print Loop)の準備:

Console(コンソール)(+マークの付いたアイコン) ▼メニュー

Scala Console をメニューから選択

2017年度は以下を使用:

Scala ConsoleのREPLは不便な点があるので、Scala Interpreter を利用することにする。

ウインドウ → ビューの表示 → Scala Interpreter

コードを入力後、 Ctrl + Enter で実行。

複数行のコードを書いて、Ctrl + Enterでまとめて実行できる。カーソルの位置はどこにあってもOK

複数の式を評価できる。ブロックにしたり、; で複数の式を記述して実行できる。

※ 1+2;3+4;5+6 の実行結果は 11 になるが、1+2 と 3+4 の式は無駄なコードになるので、warning がでる。

Ctrl + ↑ ↓ で、履歴を辿れる。(行単位でなく、実行単位)

メニューに、コードのリセットや再実行のボタンがある。

:help など ScalaのREPLコマンドは使えない。

文字入力の練習

以下の例で、あ 以外は 漢字入力OFF で入力する。

"あ"
1+2*3
val a = 1234+5678*9012
a*3

scala> 一番下のの行に文字が入力されるように、マウスでクリックする

文字を入力後、Enterを押すと入力内容がプログラムとして実行される

デモ: トラブルが起きたときの対処法(このページ最下部参照)

・複数行コピペして貼り付けると、続けて入力ができなくなり困ったことになるので、避ける。←わざとやって見せる

・回復方法を示す。

REPLコンソールで以下を実行:

scala> 1+1

scala> 2*3

scala> "abc" + "xyz"

scala> "abc" * 3
scala> "abc"(1)
scala> "abc"(0)
scala> "abc" map ( _ + " ")
scala> "abc" map ( _ + " ") mkString
scala> val hw = "Hello world!"
scala> hw.size
scala> hw(0)
scala> List(1,2,3)
scala> val a = List(1,2,3)
scala> a(1)
scala> a.sum
scala> a map ( x => if(x>2) 1 else 0)
scala> a map ( x => if(x>2) 1 else 0) sum
scala> a count (_>2)

ランダムを利用したシミュレーション

import scala.util.Random
Random.nextInt(10)
Random.nextInt(10)
Random.nextInt(100)
Random.nextInt(100)
(1 to 100) map ( _ => Random.nextInt(100) )
(1 to 100) map ( _ => Random.nextInt(100) ) sum
val rand = (1 to 1000) map ( _ => Random.nextInt(100) )

rand に対していろいろな処理を試す

処理は、

結果の集計 sum

ある数値以下か判定して個数を集計 map ( x => if( x < 10 ) 1 else 0) sum

ある数値の個数を集計 map ( x => if( x == 0 ) 1 else 0) sum

ある数値の個数を集計 count( _ == 0)

※map と sum を使用した個数の集計よりもシンプルなコード

文字列化して結合 mkString

ガチャガチャのシミュレーション

Rare 希少 大当り

Uncommon 珍しい 当り

Common 普通 はずれ

scala> val gacha = "R"*3 + "U"*15 + "C"*82
scala> gacha.size
scala> gacha(0)
scala> gacha(50)
scala> gacha(Random.nextInt(100))
何回かガチャを回してみよう

連続ガチャのシミュレーション

scala> val rg = (1 to 100) map ( _ => gacha(Random.nextInt(100)) )

scala> rg count(_ == 'R')

種類ごとに集計する

scala> val kekka = rg map { case 'R' => (1,0,0); case 'U' => (0,1,0); case 'C' => (0,0,1) }
scala> kekka./: (0,0,0) { case ((ar,au,ac),(r,u,c)) => (ar+r,au+u,ac+c) }

解説:

rg map { case 'R' => (1,0,0); 引いたいたカードの各種類 R U C に応じて、 (Rが1枚, Uが1枚, Cが1枚) に変換する

kekka./: (0,0,0) 初期値 RUCの所持枚数は各0枚。 /: は map と同様、 kekkaの各要素に対して順番に処理を繰り返す。map と異なり、各要素ごとに個別に結果を残さずに、処理結果を累積して処理する。全要素の処理後に、累積値を計算結果とする。

(ar,au,ac) 累積中のRUCの枚数。

(r,u,c) kekkaから順に取り出された要素。

(ar+r,au+u,ac+c) 累積方法。 kekkaから順に取り出した要素を、対応する累積値に加える。 例) 累積値 (0,3,10) に対して、 要素が(1,0,0) なら、累積値は (1,3,10)に更新される

時間に余裕があるなら、条件を変えて実験する

例)

ガチャの構成比率の修正

val gacha = "R"*1 + "U"*17 + "C"*82

ガチャの種類を増やす。集計方法も (1,0,0,0) のように4種類分で集計するように変更する。

val gacha = "S"*1 + "R"*3+ "U"*15 + "C"*81

※ SR や UR など2文字で表現されるレアリティーは、今回のコードではうまく動かない

YやXなど1文字に置き換えて表現する

ガチャをひくプログラムを、

scala> gacha(Random.nextInt(gacha.size))

に修正すれば、カードの種類数に応じてガチャを回すプログラムになる。

↑修正後、手動で何回かガチャを回したり(ひく)、連続ガチャのシミュレーションをする。

結果を集計してみよう。

※ 0.1% などの比率を設定したい場合は、ガチャの総種類数を1000など、大きく変更する。さらにガチャの範囲を Random.nextInt(1000) と調整する。

応用編: ガチャはこわい

0が出てくるまで、引き直した回数を求める。

結果が0なら、最初の1回目で0が出たことになる。

Stream.from(1).indexWhere(_ => Random.nextInt(100) == 0)

応用編: ガチャガチャマシンのシミュレーション

今回の課題は、デジタルなガチャなので、アイテムの個数に制限は無く、いくらでもガチャを回せる。

このプログラムを、実在のガチャのように1つアイテムを出すと、機械の中のカプセルが1つ減るようにプログラムを修正する。

※ Scala の文字列処理などを検索して、使えるコードを探して下さい。

サブページ参照

提出方法

コンソールのメニューアイコン(フロッピーディスク) を押して

保存したファイルを、編集するか聞いてくるので 「いいえ」 を選択する

デスクトップに保存する(ファイル名は適当でOK)

例)

3116999.log

WebClass の第13回課題にアップロードする。

トラブル対応1

// Entering paste mode (ctrl-D to finish)

コンソールに ↑ と表示されたら、入力が受け付けられなくなる。 赤い四角の停止ボタンを押して、REPLを止める。

できたところまでを、↑↑ の提出方法を参考に保存しておく。

Scalaコンソールを開きなおす

続けて演習を行う。

トラブル対応2

コンソールのログを保存する際に、「保存したファイルを、編集するかで 「はい」 を選択」した場合、Scalaコンソールが開けない。

eclipse の編集画面(コンソールの上の部分)のタブを、ログファイルから、Test.scala にクリックして切替える。

トラブル対応3

コンソールタブを閉じてしまった場合、 再び表示するには: eclipse のメニュー → ウインドウ → ビューの表示 → その他 → 一般 → コンソール

トラブル対応4

コンソール停止後に演習を再開するとプログラムにエラーが出る

import scala.util.Random
val で定義した行

などを再実行する。

トラブルの原因:

複数行でコピペしたときに発生する?

Webからコピペしたときに、先頭文字から選択してコピペすると、改行文字がコピペされることが原因かも。

メモ

素数+アニメーション

マルコフ連鎖

すごろく