Найти произведение каждого ди git в данном номере - PullRequest
1 голос
/ 08 января 2020

В scala мне нужно написать метод, чтобы найти произведение каждого ди git в заданном числе. У меня есть следующий фрагмент.

  def productDigits(number: Int): Int = {
    def helper(current: Int, accumulator: Int): Int = {
      current match {
        case current if current < 10 => accumulator * current
        case _ => helper(current / 10, accumulator * (current % 10))
      }
    }
    helper(number, 1)
  }

Есть ли лучший способ сделать?

1 Ответ

3 голосов
/ 08 января 2020

Вот эталонный тест рекурсивного решения OP по сравнению с одним вкладышем Луиса.

Выполнение

sbt "jmh:run -i 10 -wi 10 -f 2 -t 1 bench.So59652263"

где

@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So59652263 {
  def _dexter2305(number: Int): Int = {
    def helper(current: Int, accumulator: Int): Int = {
      current match {
        case current if current < 10 => accumulator * current
        case _ => helper(current / 10, accumulator * (current % 10))
      }
    }
    helper(number, 1)
  }

  def _luis(number: Int): Int = number.toString.map(_.asDigit).product

  val num: Int = (math.random * 100000000).toInt
  @Benchmark def dexter2305: Int = _dexter2305(num)
  @Benchmark def luis: Int = _luis(num)
}

дает

[info] So59652263.dexter2305  thrpt   20  89093066.408 ± 1825286.801  ops/s
[info] So59652263.luis        thrpt   20  11585098.230 ±  272966.526  ops/s

, где мы видим, что рекурсивное решение, кажется, имеет Пропускная способность в 7 раз больше, чем у одной линии.


Сравнительный анализ, когда number равен String вместо Int

@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So59652263 {
  def _dexter2305(number: String): Int = {
    def helper(current: Int, accumulator: Int): Int = {
      current match {
        case current if current < 10 => accumulator * current
        case _ => helper(current / 10, accumulator * (current % 10))
      }
    }
    helper(number.toInt, 1)
  }

  def _luis(number: String): Int = number.map(_.asDigit).product

  val num: String = (math.random * 100000000).toInt.toString
  @Benchmark def dexter2305: Int = _dexter2305(num)
  @Benchmark def luis: Int = _luis(num)
}

, дает

[info] Benchmark               Mode  Cnt         Score         Error  Units
[info] So59652263.dexter2305  thrpt   20  36237007.844 ± 1631349.975  ops/s
[info] So59652263.luis        thrpt   20  13975984.042 ± 1890083.941  ops/s

, где мы видим, что рекурсивное решение еще выше пропускная способность, однако, в 2,5 раза меньше, чем когда number был Int.

...