Search code examples
scalanumbersproductdigits

Find product of every digit in the given number


In scala, I need to write a method to find product of every digit in the given number. I have the following snippet.

  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)
  }

Is there a better way to do?


Solution

  • Here is jmh benchmark of OP's recursive solution vs Luis' one-liner.

    Executing

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

    where

    @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)
    }
    

    gives

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

    where we see recursive solution seems to have 7x more throughput than the one-liner.


    Benchmarking when number is String instead of 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)
    }
    

    gives

    [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
    

    where we see recursive solution still has higher throughput, however, by a smaller factor of 2.5 than when number was Int.