Scalaを使ってみた

前々からScalaを使ってみたいと思っており、Competitive Programming Advent Calendar Div2012でlizanさんのScalaで競技プログラミングしてみるの記事を見てちょっとやってみようかと使ってみました。

Scalaは最近ちょっと熱い(らしい)、オブジェクト指向と関数型の特徴を併せ持つスケーラビリティを主軸に置く言語。なんでもtwitterに使われているとか。
前に競技プログラミングにおいて「プログラムの実行速度が速い手続きが他言語」か「コードの実装スピードが速いスクリプト言語」か?ということで考えていましたが、Scalaはどちらもそこそこ優れている言語とのことです。もしかしたらオブジェクト指向を広めたC++のように、Scala関数型言語を世界の常識にするかもしれません。

とりあえずここを参考にインストール。
次にIDEです。Scala IDE for EclipseのJuno版をEclipse Junoに入れてみるも、上手く動かず。これはAquamacsかEmacsScala用のプラグインを入れるしかないかと思っていると、Typesafe Scala IDEというのを発見。これはEclipse Indigoに上記のプラグインを入れたものっぽいのですが、なんと上手く動きます。
しかもなんとJunoには入れられなかったCDTC/C++ Development Tooling。C++Eclipseプラグイン)とEclipseFPHaskellEclipseプラグイン)が入れられました。EclipseFPは何故かシンタックスハイライトすらしてくれないので微妙ですが、CDTはXcode3.0より遥かに使いやすくて非常に便利です(始めは「Binary Not Found.」とか出てきて動きませんでしたが、1回ビルドしてから実行したら動きました)。

Codeforces Round #155 (Div. 2)のC. Anagramを解いてみました。

文字列sを文字列tのアナグラムで辞書的最小の文字列にするには何文字変換すればいいかを求める問題。
基本的にsの前から順番に貪欲にやっていけばいいが、変換後の文字の方が大きい場合は注意が必要(もっと後ろの位置で変換した方がよい場合がある)。

import scala.io.Source
import java.io.PrintWriter
import java.io.File
import scala.util.control.Breaks

object CF254c {

    def main(args: Array[String]): Unit = {
            doIt();
    }
    def doIt(){
        /*val sc = new Scanner(System.in);
        val s = sc.next().toCharArray();
        val t = sc.next().toCharArray();*/
        val reader = Source.fromFile("input.txt").getLines;
        val s = reader.next().toCharArray();
        val t = reader.next().toCharArray();
        val writer = new PrintWriter(new File("output.txt" ));
        val loop = new Breaks;
        var as = new Array[Int](26);
        var at = new Array[Int](26);
        var cnts = new Array[Int](26);
        val len = s.length;
        for(e <- s){ //foreach
            as(e - 'A') += 1; //配列は()。++は駄目
            cnts(e - 'A') += 1;
        }
        for(e <- t) at(e - 'A') += 1; //{}は省略可能
        var count = 0;
        for(i <- 0 until len){ //0 .. len - 1
            var idx = s(i) - 'A';
            if(at(idx) < as(idx)){
                loop.breakable{
                    for(j <- 0 until as.length)
                        if(as(j) < at(j) && ((j < idx) || cnts(idx) <= as(idx) - at(idx) )){
                            s(i) = (j + 'A').toChar;
                            as(j) += 1;
                            as(idx) -= 1;
                            count += 1;
                            loop.break;
                        }
                }
            }
            cnts(idx) -= 1;
        }
        writer.println(count);
        writer.println(s.mkString);
        writer.close();
        /*println(count);
        println(s.mkString); //toStringでは駄目*/
    }

}

基本的にJavaみたいなシンタックス

・valは定数宣言、varは変数宣言。

・配列のアクセスはarray(i)と丸括弧。ビックリ。

・String型を作るにはtoStringよりmkStringを使った方がいいっぽい(なぜかtoStringは上手く動かなかった)。

・breakするのは面倒(やり方はこちら)。


ScalaHaskellとかPerlと違って友達になれそうな気がする・・・!
今回のプログラムは完全にjavaで書けるプログラムなので、次はもうちょっと勉強して関数型を活かしてみたいですねー。
とりあえずこれでやってみたい言語は一通りやったので(JavaScriptPHPはやらないだろうなあ・・・)、JavaC++PythonScala、ときどきHaskellを使い分けながらプログラミングしていこうと思います。