【问题标题】:Generate a custom pattern number sequence in one go一次性生成自定义图案编号序列
【发布时间】:2020-05-11 02:49:02
【问题描述】:

我想使用函数初始化构造一次性生成以下数字序列:

Array(0, 0, 0, 0, 3, 3, 6, 6, 9, 9, ..., n*3, n*3)

一种方法是:

Array.fill[Int](2)(0) ++ Array.tabulate(4)(_*3)

但我需要将构造的第二部分的每个值加倍,即得到0, 0,然后是3, 3 等。如何复制第二个构造的值?

我也想不出一个能生成这样序列的数学函数。

【问题讨论】:

  • 我假设 Scala 支持整数除法?如果是这样,您可以在乘以 3 之前将索引除以 2;将从 0 和 1 映射到 0,从 2 和 3 映射到 3,从 4 和 5 映射到 6,等等
  • @ruakh 好主意,我没想到 :)

标签: arrays algorithm scala functional-programming


【解决方案1】:

Array(0,0) ++ (0 to 2*n).map(_ / 2 * 3)

【讨论】:

    【解决方案2】:

    考虑单次通过的尾递归解决方案

    def pattern(n: Int): List[Int] = {
      @tailrec def run(n: Int, acc: List[Int]): List[Int] = {
        n match {
          case 0 => 0 :: 0 :: 0 :: 0 :: acc
          case i => run(i - 1, (i * 3) :: (i * 3) :: acc)
        }
      }
      run(n-1, Nil)
    }
    

    【讨论】:

    • @SkyWalker 请注意,当我的意思是 Arrays 不是 flattening 的最佳数据类型时。我的意思是你可以/应该使用这样的东西。
    • 它“向后”工作,允许我们在恒定时间内将元素添加到List
    【解决方案3】:

    你可以这样做:

    def create(n: Int): Array[Int] =
      Array.tabulate(n)(i => Array.fill(if (i == 0) 4 else 2)(3 * i)).flatten
    

    但是,数组并不是扁平化的最佳数据类型。

    【讨论】:

      【解决方案4】:

      这是使用flatMap 的可能解决方案:

      Array.fill[Int](2)(0) ++ Array.tabulate(4)(_*3).flatMap(x => Array(x, x))
      

      【讨论】:

        【解决方案5】:

        jmh 答案基准

        @State(Scope.Benchmark)
        @BenchmarkMode(Array(Mode.Throughput))
        class So59902144 {
          def Luis(n: Int) = Array.tabulate(n)(i => Array.fill(if (i == 0) 4 else 2)(3 * i)).flatten
          def Dima(n: Int) = Array(0,0) ++ (0 until 2*n).map(_ / 2 * 3)
          def SkyWalker(n: Int) = Array.fill[Int](2)(0) ++ Array.tabulate(n)(_*3).flatMap(x => Array(x, x))
          def MarioGalic(n: Int) =  {
            @tailrec def run(n: Int, acc: List[Int]): List[Int] = {
              n match {
                case 0 => 0 :: 0 :: 0 :: 0 :: acc
                case i => run(i - 1, (i * 3) :: (i * 3) :: acc)
              }
            }
            run(n-1, Nil)
          }
        
          val n = 10000
          @Benchmark def _Luis = Luis(n)
          @Benchmark def _Dima = Dima(n)
          @Benchmark def _SkyWalker = SkyWalker(n)
          @Benchmark def _MarioGalic = MarioGalic(n)
        }
        
        sbt "jmh:run -i 5 -wi 2 -f 1 -t 1 -prof gc bench.So59902144"
        
        [info] Benchmark                   Mode   Cnt        Score       Error   Units
        [info] So59902144._Dima            thrpt    5     5178.171 ±   837.780   ops/s
        [info] So59902144._Luis            thrpt    5     3649.262 ±   309.027   ops/s
        [info] So59902144._MarioGalic      thrpt    5    10926.546 ±  3587.691   ops/s
        [info] So59902144._SkyWalker       thrpt    5     6088.413 ±   474.100   ops/s
        

        【讨论】:

        • 芜湖,我是最慢的,这很好,因为我确信flatten 是一个非常糟糕的主意。它表明,如果使用得当,Lists 可以非常高效。
        • @SkyWalker Credit 转至 Travis Brown 的 excelent answer,它演示了如何进行这些测量。
        猜你喜欢
        • 2019-11-25
        • 1970-01-01
        • 1970-01-01
        • 2017-03-03
        • 1970-01-01
        • 2021-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多