世界のナベアツに Scala で挑戦する
今更ですが、世界のナベアツに Scala で挑戦してみました。
Scalaだと、
<レシーバ> <メソッド> <引数>
でメソッドを呼び出したりできるので、「.」とか「()」とかを排除できてやばいことになるんじゃね!と思って始めたのだけど、0にするのは無理でした。
import scala.collection.mutable.HashMap import scala.util.matching._ object Nabeatu extends Conversions { def main(args: Array[String]) { 1 から 40 まで数えて ( 3 の 倍数 と ( 3 の つく数字 ) のとき アホ に ( 5 の 倍数 のとき 犬 ) に ( 8 の 倍数 のとき 気持ちよく ) なります ) } def 犬:(IntEx)=>Unit = { def x(i:IntEx) = { println(i.の読み + "バフッ") } x _ } val ahoMap = HashMap.apply( ( "な$", "ぁ〜〜ッ" ), ( "[ちに]$", "ぃ〜〜ッ" ), ( "[くうッ]$", "ぅ〜〜ッ" ), ( "[ご]$", "ぉ〜〜ッ" ) ) def アホ:(IntEx)=>Unit = { def x(i:IntEx) = { var y = i.の読み val result = ahoMap.find( e => new Regex(e._1).findFirstIn(y) != None ) if ( result == None ) println(i.の読み+"〜〜ッ") else { var e = result.get println(i.の読み + e._2) } } x _ } def 気持ちよく:(IntEx)=>Unit = { def x(i:IntEx) = { println(i.の読み) } x _ } def 倍数:(IntEx,Int)=>Boolean = { def x(i:IntEx, x:Int):Boolean = { i.org % x == 0 } x _ } def つく数字:(IntEx,Int)=>Boolean = { def x(i:IntEx, x:Int):Boolean = i.org.toString.indexOf(x.toString) >= 0 x _ } } trait Conversions { implicit def toEx(i:Int):IntEx = new IntEx(i) } trait Condition { def matches(i:IntEx):Boolean def と( c:Condition ):Condition = new Or( this, c ) def のとき(action:IntEx=>Unit):If = new If( this, action ) } class ConditionImpl( e:(IntEx)=>Boolean ) extends Condition { override def matches(i:IntEx):Boolean = e.apply( i ) } class And( a:Condition, b:Condition ) extends Condition { override def matches(i:IntEx):Boolean = a.matches(i) && b.matches(i) } class Or( a:Condition, b:Condition ) extends Condition { override def matches(i:IntEx):Boolean = a.matches(i) || b.matches(i) } class If( condition:Condition, action:IntEx=>Unit ) { var next:If = null var prev:If = null def に(next:If):If = { this.next = next next.prev = this return next } def first:If = if ( prev != null ) prev.first else this def run( i:IntEx ) { if (condition.matches(i)) action.apply( i ) else if (next != null) next.run(i) else println(i.org) } def なります:(IntEx)=>Unit = { def x(i:IntEx) = { first.run( i ) } x _ } } class IntEx(i:Int) { def org:Int = i def から(x:IntEx):RangeEx = new RangeEx(this,x) val KazuYomi = Array("", "いち", "に", "さん", "よん", "ご", "ろく", "なな", "はち", "きゅう") val KetaYomi = Array("", "じゅう", "ひゃく", "せん") def の読み:String = { def toS(i:Int, str:String, k:Int):String = { var s:String = if ( i%10 != 1 || k == 0) KazuYomi(i%10) else "" if ( k >= 1 ) s = s+KetaYomi(k) if (i >= 10) toS( i/10, s+str, k+1 ) else s+str } toS( i, "", 0 ) } def の( e:(IntEx,Int)=>Boolean ):Condition = new ConditionImpl( x => e.apply( x, i ) ) } class RangeEx(from:IntEx, to:IntEx) extends Conversions { def まで数えて( block: (IntEx)=>Unit) { from.org to to.org foreach( i=> block.apply( i ) ) } }
実行結果です。
1 2 さん〜〜ッ 4 ごバフッ ろくぅ〜〜ッ 7 はち きゅうぅ〜〜ッ じゅうバフッ 11 じゅうにぃ〜〜ッ じゅうさん〜〜ッ 14 じゅうごぉ〜〜ッ じゅうろく 17 じゅうはちぃ〜〜ッ 19 にじゅうバフッ にじゅういちぃ〜〜ッ 22 にじゅうさん〜〜ッ にじゅうよん〜〜ッ にじゅうごバフッ 26 にじゅうななぁ〜〜ッ 28 29 さんじゅうぅ〜〜ッ さんじゅういちぃ〜〜ッ さんじゅうにぃ〜〜ッ さんじゅうさん〜〜ッ さんじゅうよん〜〜ッ さんじゅうごぉ〜〜ッ さんじゅうろくぅ〜〜ッ さんじゅうななぁ〜〜ッ さんじゅうはちぃ〜〜ッ さんじゅうきゅうぅ〜〜ッ よんじゅうバフッ
元ネタはこちら。