0

数値を同等の文字列に変換するプログラムを作成しようとしています。IE 987,654,321 =987百万6,54,3,21。コンソールから値を読み込み、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;
          }
        }
      }
    }
4

1 に答える 1

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書き出された最大のunsignedlonglong()が何であるか疑問に思ったことはありませんか?

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

編集:待って、逆問題を解決したい場合はどうしますか?適用後、閉じ中括弧の前にこれを挿入するだけです。

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

(実際には適切にフォーマットされていないものを受け入れる場合がいくつかありますが、不正な数値を拒否することにはかなり適しています。)

于 2013-03-04T23:43:52.423 に答える