このエントリは Scala Advent Calendar jp 2010 : ATND の 24 日のものです。
前日に id:mzp (mzp さん) から「サンタクロース問題というのがあってね」という話を聞いたので、イヴだしやってみることにしました。ネタの提供ありがとう!
サンタクロース問題の詳細については、
とかを見てもらえばいいでしょう。
面倒な人向けに概要:
トナカイ (reindeer) が 9 匹いて、全員揃うとおもちゃを配りに行く。終わったら解散。
こびと (elf) が 10 人いて、そのうち 3 人そろうと次期のおもちゃをどうするかの会議を開く。終わったら解散。
以上です。
これを、Scala のアクター使って書いてみました。
アクター使って何か書くのは初めてだったけど、これは楽でいいですね。
import scala.actors._
import scala.actors.Actor._
// サンタを表す・・・というより、サンタの家を表してる感のあるアクター
object Santa extends Actor {
import scala.collection.mutable._
val reindeers = new ListBuffer[SantaTeam]()
val elves = new ListBuffer[SantaTeam]()
def act() {
def work(team: ListBuffer[SantaTeam], job: String, treat: Symbol) {
println(job)
team.foreach(_ ! treat)
team.clear()
}
// そろったかどうか確認して、そろってたら仕事する
def arrive(member: SantaTeam) {
println(member.name + "到着")
member match {
case r: Reindeer =>
reindeers += r
if (reindeers.length == 9) work(reindeers, "配達!", 'play)
case e: Elf =>
elves += e
if (elves.length == 3) work(elves, "会議!", 'work)
}
}
// 誰か着いたら、そのままarrive関数に丸投げ
loop { react { case m: SantaTeam => arrive(m) } }
}
}
object Thread {
def sleep() = java.lang.Thread.sleep((java.lang.Math.random() * 1000).toLong)
}
// サンタチームを表す抽象クラス
abstract sealed class SantaTeam(val name: String, action: PartialFunction[Any, Unit]) extends Actor {
def act() = loop { Thread.sleep(); react(action) }
}
// トナカイ
case class Reindeer(n: String, santa: Actor)
extends SantaTeam(n, { case 'play => santa ! self })
// こびと
case class Elf(n: String, santa: Actor)
extends SantaTeam(n, { case 'work => santa ! self })
object Main {
def main(args: Array[String]) {
// トナカイたちとこびとたち
val reindeers = for (i <- 1 to 9) yield Reindeer("トナカイ" + i, Santa)
val elves = for (i <- 1 to 10) yield Elf("こびと" + i, Santa)
// 全てのアクターを開始
Santa.start
reindeers.foreach(_.start)
elves.foreach(_.start)
// 最初のメッセージを送る
reindeers.foreach(_ ! 'play)
elves.foreach(_ ! 'work)
}
}
Santa オブジェクトでフィールド使っちゃってるのがちょっと負けた感ありますかね。
Actor で 2 つ List 渡すようにするとかすればもっときれいに書けるのかな?
ということで、クリスマスイヴを Scala と過ごした俺は勝ち組!
Scala は俺の嫁!
・・・はい、ごめんなさい。次はまたまた id:mzp です。超楽しみですね!正座して待機!!
そしてみなさんメリークリスマス!