2016年度目標: 昨年同様
2015年度目標: あきすとぜねこ 占いのプログラムを関数スタイルで作成。
Scalaの文字列処理
http://gendosu.jp/archives/1344
ストリーム練習
object Main {
def main(args: Array[String]) = {
def Ones:Stream[Int] = 1 #:: Ones
println(Ones.take(8).toList)
def PlusOnes:Stream[Int] = 1 #:: PlusOnes.map( _ + 1)
println(PlusOnes.take(8).toList)
}}
あきすとぜねこ ヒント
scala> val AK:Stream[Char] = 'あ' #::'き' #::'す' #::'と' #::'ぜ' #::'ね' #:: 'こ' #:: AKAK: Stream[Char] = Stream(あ, ?)scala> AK(3)res18: Char = とscala> AK.take(3)res19: scala.collection.immutable.Stream[Char] = Stream(あ, ?)scala> AK.take(3).toListres20: List[Char] = List(あ, き, す)scala> "KOBASHI".filter("AIUEON" contains _)res21: String = OAIscala> "KOBASHI".filter("SXYZ" contains _)res26: String = S制作例) 一部省略しているので、完成させてみよう。
※Test.scala に以下を追記
※プログラムを実行する際には、 実行の構成 から メイン・クラス を Main に変更する。
object Main { def main(args: Array[String]) = { // あきすとぜねこ 判定用の遅延リストで判定用数字が7を超えた場合に対応 // ※普通は、遅延リストを使わずに、判定用数字を7で割った余りに変換して、Listを使う lazy val AK: Stream[Char] = 'あ' #:: 'き' #:: 'す' #:: 'と' #:: 'ぜ' #:: 'ね' #:: 'こ' #:: AK def kekka(n: Int) = ('う' #:: AK)(n) match { case 'う' => "運命の人" case 'あ' => "愛してる" case _ => "内緒" } // ひらがなの名前を、AIUEON に変換 長音記号 - やカタカナにも対応させてみよう def RtoAIU(str: String) = str.map(_ match { case c if "あかがさざただなはばぱまやらわ" contains c => 'A' case c if "いきぎしじちぢにひびぴみり" contains c => 'I' case c if "うくぐすずつづっぬふぶぷむゆゅる" contains c => 'U' case c if "えけげせぜてでねへべぺめれ" contains c => 'E' case c if "おこごそぞとどのほぼぽもよろを" contains c => 'O' case 'ん' => 'N' }) def HtoNums(str: String) = str.map(_ match { case 'A' => 1 case 'I' => 2 case 'U' => 3 case 'E' => 4 case 'O' => 5 case 'N' => 1 }) def ZNK(str1: String, str2: String) = { val R1 = RtoAIU(str1) val R2 = RtoAIU(str2) val D1 = R1.filter(c => !(R2 contains c)) val D2 = R2.filter(c => !(R1 contains c)) val N1 = D1.sum val N2 = D2.sum (kekka(N1), kekka(N2)) } def printZNK(str1: String, str2: String) { val s = ZNK(str1, str2) println(s"${str1} → ${str2} 結果は ${s._1}") println(s"${str2} → ${str1} 結果は ${s._2}") } // 本来、姓の後に名を記入して占う val name1 = "こばし" val name2 = "はせがわ" val name3 = "はっとり" printZNK(name1,name2) printZNK(name1,name3) }}実行結果:
こばし → はせがわ 結果は 内緒はせがわ → こばし 結果は 内緒こばし → はっとり 結果は 運命の人はっとり → こばし 結果は 愛してる(先週の資料 後半部分の続き)
Scala のデータ型である リスト を関数型スタイルで処理し、 サウンド再生用データを作成する。
音響合成プログラミングを行う。
応用 「エンジニアでも恋がしたい!」 http://paiza.jp/poh/enkoi の問題に Scala で挑戦
解答編:
問2
object Main extends App{ override def main(args:Array[String]) = { val sc = new java.util.Scanner(System.in) val n = sc.nextInt var sum = 0 for(i <- 1 to n) { val a,b,c = sc.nextInt if(a>b) { sum += (a-b)*c } } println(sum) }}問3
配列版
object Main extends App{ override def main(args:Array[String]) = { val sc = new java.util.Scanner(System.in) val t = sc.nextInt val n = sc.nextInt val ms = new Array[Int](t) for(i <- 0 to t - 1) { ms(i) = sc.nextInt } var sum = ms.sum var max = sum for(i <- 0 to n - t - 1) { val a = ms(i % t) val b = sc.nextInt ms(i % t) = b sum = sum - a + b if(sum > max) { max = sum } } println(max) }}リスト版(単純版)
object Main extends App{ override def main(args:Array[String]) = { val sc = new java.util.Scanner(System.in) val t = sc.nextInt val n = sc.nextInt var max = 0 var ms:List[Int] = Nil for(i <- 1 to t) { ms = ms :+ sc.nextInt } max = ms.sum for(i <- 1 to n-t) { ms = ms.tail :+ sc.nextInt val sum = ms.sum if(sum > max) { max = sum } } println(max) }}リスト版(高速化版)
object Main extends App{ override def main(args:Array[String]) = { val sc = new java.util.Scanner(System.in) val t = sc.nextInt val n = sc.nextInt var ms:List[Int] = Nil for(i <- 1 to t) { ms = ms :+ sc.nextInt } var sum = ms.sum var max = sum for(i <- 1 to n-t) { val b = sc.nextInt val a = ms.head ms = ms.tail :+ b sum = sum - a + b if(sum > max) { max = sum } } println(max) }}Scala のリスト処理の参考サイト:
Scalaの配列について:
Scalaプログラミングで知っておきたい基本構文まとめ (1/2)
Scalaのストリームについて
https://sites.google.com/site/scalajp/home/documentation/scala-by-example/chapter12
http://scalajp.github.io/scala-collections-doc-ja/collections_14.html
Java8 のストリームAPIについて Stream APIの始め方
例)
object Main {def main(args:Array[String]) = {
println( fix(1).take(10).toList )
println( up(1).take(10).toList )
println( up(10).take(20).filter(_%2==0).toList )
println( up(10).filter(_%2==0).take(20).toList )
}
def fix(x:Int):Stream[Int] = x #:: fix(x)
def up(x:Int):Stream[Int] = x #:: up(x+1)
}出力結果
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1) List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) List(10, 12, 14, 16, 18, 20, 22, 24, 26, 28) List(10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48) 演習課題:
・環境構築
レポートフォルダ オブジェクト指向(小橋) にある scala フォルダを D: ドライブにコピー。 もしも時間がかかり過ぎるようなら、コピーしない方式も検討。
環境変数に java のパスを設定
JAVA_HOME = D:\java\8windowsのコマンドプロンプトを開く
scala REPL の起動
Scalaのインストールされたフォルダに移動
> d:> cd \scala\bin
> scala(参考)
Javaでピコピコシンセを作ってみよう!(1) - ピコピコ音の正体を暴く http://www.hakkaku.net/articles/20090423-422
Programming music http://vigtig.it/blog/blog/2011/04/12/programming-music/
ビープ音の合成
import javax.sound.sampled._// オーディオ形式を指定val SAMPLE_RATE = 44100; // 44.1KHzval audio_format = new AudioFormat(SAMPLE_RATE, 8, 1, true, true)val line = AudioSystem.getSourceDataLine(audio_format)line.open()line.start()// バイト列に適当な矩形波を作成val frequency = 440val b = new Array[Byte](SAMPLE_RATE)for (i <- 0 to b.size) { val r = i / (SAMPLE_RATE / frequency) if( r % 2 == 0) { b(i) = 100 } else { b(i) = -100 }}// 再生(バイト列を line に書き込む)line.write(b, 0, b.length);line.drain(); // 終了まで待機波形を修正する。
ループ部分の式を 調整して 音を変えてみる。
試したたコードを、 学籍番号Scala2.txt のテキストファイルにコピペして提出。
// Testval i = 123println(i * 2)import javax.sound.sampled._// Test 1// オーディオ形式を指定val SAMPLE_RATE = 44100; // 44.1KHzval audio_format = new AudioFormat(SAMPLE_RATE, 8, 1, true, true)val line = AudioSystem.getSourceDataLine(audio_format)line.open()line.start()// バイト列に適当な矩形波を作成val frequency = 440val b = new Array[Byte](SAMPLE_RATE)for (i <- 0 to b.size) { val r = i / (SAMPLE_RATE / frequency) if( r % 2 == 0) { b(i) = 100 } else { b(i) = -100 }}// 再生(バイト列を line に書き込む)line.write(b, 0, b.length);line.drain(); // 終了まで待機// Test 2 再生時間を10倍 長くするval SAMPLE_RATE = 44100; // 44.1KHzval audio_format = new AudioFormat(SAMPLE_RATE, 8, 1, true, true)val line = AudioSystem.getSourceDataLine(audio_format)line.open()line.start()val frequency = 440val b = new Array[Byte](SAMPLE_RATE * 10)for (i <- 0 to b.size) { val r = i / (SAMPLE_RATE / frequency) if( r % 2 == 0) { b(i) = 100 } else { b(i) = -100 }}line.write(b, 0, b.length);line.drain(); // 終了まで待機// Test 3 再生時間を半分にして 音の周波数を 2倍(1オクターブ上)にするval frequency = 880val b = new Array[Byte](SAMPLE_RATE/2)for (i <- 0 to b.size) { val r = i / (SAMPLE_RATE / frequency) if( r % 2 == 0) { b(i) = 100 } else { b(i) = -100 }}line.write(b, 0, b.length);line.drain(); // 終了まで待機// Test 3 2オクターブ上にするval frequency = 880*2val b = new Array[Byte](SAMPLE_RATE/2)for (i <- 0 to b.size) { val r = i / (SAMPLE_RATE / frequency) if( r % 2 == 0) { b(i) = 100 } else { b(i) = -100 }}line.write(b, 0, b.length);line.drain(); // 終了まで待機// r = i / 500// Test 4 ホワイトノイズimport scala.util.RandomList.fill(10)(Random.nextInt(10))val b = List.fill(SAMPLE_RATE)((Random.nextInt(200)-100).toByte).toArrayline.write(b, 0, b.length);line.drain(); // 終了まで待機音源データの波形を表示する。
// b1 から100個データを取り出し、 各データの値 e を e個の "." で1行に表示するb1.take(100) foreach {e => println( "." * e )}// b1 から300個データを取り出し、 各データの値 e を e/2個の "." で1行に表示する
// 高さが半分になる
b1.take(300) foreach {e => println( "." * e/2 )}
// データの値 e が -128..0 の場合、-128 は0個 -127 は1個のように、"."を表示する
//
b1.take(300) foreach {e => println( "." * (e+128) )}