サンタクロース問題
このエントリは 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 です。超楽しみですね!正座して待機!!
そしてみなさんメリークリスマス!