- You should definitely use `scala.io.Source` for File-IO
- I wouldn't consider String splitting a responsibility of a general-purpose class. This should be done in the main loop
- For tuples you can write map{ case (one,two) => ... }, which is often clearer than using x._1 and x._2
- You don't need to write return if it's the last statement of the block
- You can use pattern matching when defining vals: `val Array(x, y, z) = line.split(" ")`
Here is my attempt:
case class Langs(num:String, srcLang:String, dstLang:String)
object Langs {
def fromLine(line:String):Langs = {
val Array(num, srcLang, dstLang) = line.split(" ")
Langs(num, srcLang, dstLang)
}
}
object Translate {
def lang2int(lang:String,num:String):Long = {
val dmap = lang.toList.zipWithIndex.toMap
val digitsList = num map dmap
val valueList = digitsList.reverse.zipWithIndex map {
case (one, two) => one -> math.pow(dmap.size, two)}
valueList.map{case (one,two) => one*two}.sum.toLong
}
def int2lang(lang:String, num:Long):String = {
val dmap = (0.toLong to lang.size zip lang).toMap
Iterator.iterate(num)( _/dmap.size).takeWhile(_ > 0).map(n =>
dmap(n % dmap.size)).mkString.reverse
}
def lang2lang(l:Langs):String = int2lang(l.dstLang,lang2int(l.srcLang,l.num))
}
Eliminating the while loop isn't that straight-forward, maybe someone else has an idea how to avoid that Iterator train-wreck.
**[Edit]**
I asked in [another forum][1] for a better solution for `int2lang`, and got this answer:
def int2lang(lang: String, num: Long): String = {
val dmap = (0L to lang.size) zip lang toMap
val size = dmap.size
def loop(num: Long, l: List[Char]): List[Char] =
if (num == 0) l else loop(num/size, dmap(num%size) :: l)
loop(num, Nil).mkString
}
The nice thing about this is that the `reverse` is gone.
[1]: http://scala-forum.org/read.php?3,314,314#msg-314