2

私はScalaの初心者です。トルコの市民権番号検証アルゴリズムを試しました。

このscalaコードを実装して最適化するにはどうすればよいですか?

私のJavaバージョンは、このリンクhttps://gist.github.com/hasanozgan/5601623で見つけることができます

trait TurkishCitizenshipNumberValidator {

  private def odd(tckn: String): Int = {
    tckn.zipWithIndex.foldLeft(0) {
      (total, x) =>
        x match {
          case i if ((i._2 % 2 == 0 && i._2 < 10)) => ((i._1.asDigit) + total)
          case _ => total
        }
    }
  }

  private def even(tckn: String): Int = {
    tckn.zipWithIndex.foldLeft(0) {
      (total, x) =>
        x match {
          case i if ((i._2 % 2 == 1) && i._2 < 9) => ((i._1.asDigit) + total)
          case _ => total
        }
    }
  }

  private def total(tckn: String): Int = {
    tckn.zipWithIndex.foldLeft(0) {
      (total, x) =>
        x match {
          case i if (i._2 < 10) => ((i._1.asDigit) + total)
          case _ => total
        }
    }
  }

  def turkishCitizenshipNumberValidator(t: String): Boolean = {
    val digit10 = total(t) % 10
    val digit9 = ((odd(t) * 7) - even(t)) % 10

    ((t(9).asDigit == digit9) && t(10).asDigit == digit10)
  }
}

object test extends TurkishCitizenshipNumberValidator {
  // http://tckimliknouretici.appspot.com/
    turkishCitizenshipNumberValidator("29419391592")
                                                  //> res0: Boolean = true
}
4

4 に答える 4

2

コンパクトでクリアなものが必要で、基本的な入力検証 (適切な長さ、数字) が必要な場合は、

def turkishCitizenshipNumberValidator(t: String): Boolean = {
  if (t.length != 11 || !t.forall(_.isDigit)) false
  else {
    val n = t.map(_.asDigit)
    val evens = n.grouped(2).take(5).map(_(0)).sum
    val odds = n.grouped(2).take(4).map(_(1)).sum
    n(10) == (n.take(10).sum % 10) && n(9) == ((odds*7 - evens) % 10)
  }
}

ここでのキーはgrouped、文字列を偶数と奇数のペアに引き離し、最初に数字を数字にマッピングするために使用しているため、それらを操作するのはそれほど面倒ではありません。


編集: コードを難読化したい場合は、これを試してください!

def tCNV(t: String) = t.map(_.asDigit).foldLeft(Seq(0,0,0)){ (v,n) => v(2) match {
  case 10 => Seq(v(0)-n,v(1),0); case 9 => Seq(v(0)+n,v(1)-n,10)
  case i => Seq(v(0)+n, v(1)+n*(7*(i%2)+(i%2-1)), i+1)
}}.take(2).map(_%10).forall(_ == 0)
于 2013-05-17T23:15:04.840 に答える
1

これはどう?

def turkishCitizenshipNumberValidator(t: String): Boolean = {
  val digits = t.init.map(_.asDigit)
  val digit10 = digits.sum % 10
  val (odd, even) = digits.zipWithIndex.partition(_._2 % 2 == 0)
  val digit9 = ((odd.map(_._1).sum * 7) - even.init.map(_._1).sum) % 10

  ((t(9).asDigit == digit9) && t(10).asDigit == digit10)
}
于 2013-05-17T21:52:33.363 に答える
1

まあ、あなたはわずかな違いで 3 倍の同じ体を持っています。したがって、インデックスをテストする追加の関数引数を使用して、その本体を 1 つの補助メソッドとして除外する必要があります。

private def check(tckn: String)(pred: Int => Boolean): Int = {
  tckn.zipWithIndex.foldLeft(0) {
    (total, x) =>
      x match {
        case i if pred(i._2) => ((i._1.asDigit) + total)
        case _ => total
      }
  }
}

private def odd(tckn: String): Int = check(tckn)(i => i % 2 == 0 && i < 10)


次に、check文字とインデックスのタプルを抽出することで、コードを少し単純化できます。ガードが 1 つしかない場合は、パターン マッチは必要ありませんif

private def check(tckn: String)(pred: Int => Boolean): Int =
  tckn.zipWithIndex.foldLeft(0) { case (total, (char, idx)) =>
    if (pred(idx)) char.asDigit + total else total
  }
于 2013-05-17T20:24:17.463 に答える