在scala中迭代while循环

时间:2013-03-04 21:39:36

标签: scala

我正在尝试编写一个将数字转换为等效字符串的程序。 IE 987,654,321 =九十八七百万六五十四数千三百二十一。我从控制台读取值,我想迭代从i = 0到string.length的while循环

示例

   var s = "987654321"
   var characters = s.toString;
   var i = 0;
   while(i < characters.length){
     do something
   }

我的代码在

之下
    object project1 {
      def main(args: Array[String]) {
        println("Enter a number")
        val s = Console.readLine

        println(eval(s));
      }

      def tens(c: Char) : String = ( 
        if (c.toInt == 9){
          return "Ninety";
        } else if (c.toInt == 8){
          return "Eighty";
        } else if(c.toInt == 7){
          return "Seventy";
        } else if(c.toInt == 6){
          return "Sixty";
        } else if(c.toInt == 5){
          return "Fifty";
        } else if(c.toInt == 4){
          return "Fourty";
        } else if(c.toInt == 3){
          return "Thirty";
        } else if(c.toInt == 2){
          return "Twenty";
        } else{
          return "";
        }
  )

      def everyThingElse(c : Char): String = (
        if (c.toInt == 9){
          return "Nine";
        } else if (c.toInt == 8){
          return "Eight";
        } else if(c.toInt == 7){
          return "Seven";
        } else if(c.toInt  == 6){
          return "Six";
        } else if(c.toInt  == 5){
          return "Five";
        } else if(c.toInt  == 4){
          return "Four";
        } else if(c.toInt  == 3){
          return "Three";
        } else if(c.toInt  == 2){
          return "Two";
        } else if(c.toInt  == 1){
          return "One";
        } else{
          return "";
        }
      );

      def eval(s: String): String = {
        val characters = s.toCharArray;
        var word = "";
        var i = 0;
        while( i < characters.length ){
          if((i == 14) || (i == 11) || (i == 8) || (i == 5) || (i == 2)){
            word = word + everyThingElse(characters(i));
            word = word + " Hundred ";
            i += 1;
          } else if ((i == 13) || (i == 10) || (i == 7) || (i == 4) || (i == 1)){
            if(characters(i).toInt != 1){
              word = word + tens(characters(i));
              i += 1;
            } else{
              i += 1;
              if(characters(i).toInt == 9){
                word = word + " Nineteen ";
              } else if(characters(i).toInt == 8){
                word = word + " Eighteen ";
              } else if(characters(i).toInt ==7){
                word = word + " Seventeen ";
              } else if(characters(i).toInt == 6){
                word = word + " Sixteen ";
              } else if(characters(i).toInt == 5){
                word = word + " Fifteen ";
              } else if(characters(i).toInt == 4){
                word = word + " Fourteen ";
              } else if(characters(i).toInt == 3){
                word = word + " Thirdteen ";
              } else if(characters(i).toInt == 2){
                word = word + " Twelve ";
              } else if(characters(i).toInt == 1){
                word = word + " Ten ";
              }
              i += 1;
            }
          } else if (i == 9){
            word = word + everyThingElse(characters(i));
            word = word + " Billion ";
            i += 1;
          } else if(i == 6){
            word = word + everyThingElse(characters(i));
            word = word + " Million ";
            i += 1;
          } else if (i == 12){
            word = word + everyThingElse(characters(i));
            word = word + " Trillion ";
            i += 1;
          } else if (i == 0){
            word = word + everyThingElse(characters(i));
            i += 1;
          }
        }
      }
    }

1 个答案:

答案 0 :(得分:7)

我决定将输出作为选项很有趣,所以我创建了:

object Longhand {
  val small = (
    " one two three four five six seven eight nine ten eleven twelve " +
    "thirteen fourteen fifteen sixteen seventeen eighteen nineteen"
  ).split(' ')

  val mid = "twen thir for fif six seven eigh nine".split(' ').map(_ + "ty")

  lazy val big: Stream[String] = {
    Stream("", "thousand") #::: 
    "m b tr quadr quint sext sept oct non dec".split(' ').map(_+"illion").toStream #:::
    big.drop(1).map(_ + "-decillion")
  }

  def duo(n: Int) = {
    if (n >= 20) List(mid(n/10 - 2), small(n % 10)).filterNot(_.isEmpty)
    else List(small(n)).filterNot(_.isEmpty)
  }

  def trio(n: Int, and: Boolean = false) = {
    val tens = duo(n % 100) match {
      case Nil => Nil
      case x => if (and) "and" :: x else x
    }
    List(small(n/100)).filterNot(_.isEmpty).map(_ + " hundred") ::: tens
  }

  def triples(s: String) = s.reverse.grouped(3).map(_.reverse.toInt).toList

  def apply(s: String): String = {
    val and = (s.length>2) #:: Stream.continually(false)
    val tri = (triples(s) zip and).map{ case (s,a) => trio(s,a) }
    val all = (tri zip big).collect{ case (t,b) if !t.isEmpty => t :+ b }
    all.reverse.flatten.filterNot(_.isEmpty).mkString(" ")
  }
  def apply(l: Long): String = if (l<0) "minus "+apply(-l) else apply(l.toString)
  def apply(b: BigInt): String = if (b<0) "minus "+apply(-b) else apply(b.toString)
}

处理任意长度的字符串。它拥有一切和厨房水槽(更适合代码高尔夫而不是教学目的),但也许你可以从中得到一些指示。特别是,你应该尝试使用列表(数组,向量,某些东西),以避免一遍又一遍地反复重复自己....

有没有想过最大的无符号长long(Long)写出来了什么?

scala> Longhand(BigInt(2).pow(64)-1)
res32: String = eighteen quintillion four hundred forty six quadrillion
  seven hundred forty four trillion seventy three billion seven hundred nine million
  five hundred fifty one thousand six hundred and fifteen

编辑:等等,如果你想解决反问题怎么办?只需在apply之后和右括号之前插入:

val bigset = big.take(12).filterNot(_.isEmpty).toSet
val smallset = small.filterNot(_.isEmpty).toSet
val midset = mid.toSet
val valid = (bigset ++ smallset ++ mid) + "hundred"
val bignum = Iterator.iterate(BigInt(1000))(_ * 1000).take(11).toArray

def unapply(text: String): Option[BigInt] = {
  val bits = text.toLowerCase.trim.split(" +|-").filter(x => !x.isEmpty && x!="and")
  if (!bits.forall(valid contains _)) return None
  val parts = bits.map{ case s =>
    if (bigset contains s) Right(bignum(big.indexOf(s)-1))
    else if (smallset contains s) Left(small.indexOf(s))
    else if (midset contains s) Left(20 + 10*mid.indexOf(s))
    else Left(100)
  }.foldLeft(List[Either[Int,BigInt]]()){ (xs,x) =>
    x match {
      case Left(i) => xs match {
        case Left(j) :: more =>
          if (i==100) {
            if (j>=10) return None else Left(i*j) :: more
          }
          else if (i > 10 && (j%100) != 0) return None
          else if ((j%10) != 0) return None
          else Left(i+j) :: more
        case _ => Left(i) :: xs
      }
      case Right(n) => xs match {
        case Right(m) :: more => Right(n*m) :: more
        case Left(j) :: more => Right(n*j) :: more
        case Nil => Right(n) :: Nil
      }
    }
  }.collect{ case Right(n) => n; case Left(i) => BigInt(i) }
  Some(parts.foldLeft(BigInt(0)){ (acc,x) =>
    if (acc > x) return None else acc+x
  })
}

现在你可以:

scala> "five million eight hundred and one thousand and sixty-two"
res0: String = five million eight hundred and one thousand and sixty-two

scala> res0 match { case Longhand(n) => n }
res1: BigInt = 5801062

scala> Longhand.unapply("one and hundred billion five seven million")
res2: Option[BigInt] = None

(在某些情况下,它会接受实际上没有正确格式化的内容,但拒绝格式错误的数字非常好。)