Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm Scala中具有不可变集合的素数的试验划分_Algorithm_Scala_Data Structures_Functional Programming - Fatal编程技术网

Algorithm Scala中具有不可变集合的素数的试验划分

Algorithm Scala中具有不可变集合的素数的试验划分,algorithm,scala,data-structures,functional-programming,Algorithm,Scala,Data Structures,Functional Programming,我试图通过重写基本练习来学习Scala和函数式编程思想。目前,我对生成素数的幼稚方法“试驾”有困难 下面描述的问题是,我无法以保持函数风格的效率重写著名的算法,因为我没有合适的不变数据结构,如列表,但不仅在头部,而且在末端都有快速操作。 我从编写java代码开始,对于每一个奇数,用已经找到的素数(受测试值的平方根限制)测试其可除性,如果没有找到除数,则将其添加到列表的末尾 List primes=new ArrayList(); 添加(2); int cur=3; while(primes.s

我试图通过重写基本练习来学习Scala和函数式编程思想。目前,我对生成素数的幼稚方法“试驾”有困难

下面描述的问题是,我无法以保持函数风格的效率重写著名的算法,因为我没有合适的不变数据结构,如列表,但不仅在头部,而且在末端都有快速操作。

我从编写java代码开始,对于每一个奇数,用已经找到的素数(受测试值的平方根限制)测试其可除性,如果没有找到除数,则将其添加到列表的末尾

List primes=new ArrayList();
添加(2);
int cur=3;
while(primes.size()<100000){
for(整数x:素数){
如果(x*x>cur){
素数。添加(cur);
打破
}
如果(当前%x==0){
打破
}
}
cur+=2;
}
现在我试图用“函数式”的方式重写它——使用递归代替循环没有问题,但我坚持使用不可变集合。核心思想如下:

def素数(n:Int)={
@泰勒克
def divisibleByAny(x:Int,list:list[Int]):布尔={
if(list.isEmpty)false else{
val h=list.head
h*h根据
Vector
s在追加、前置和查找时有一个摊销的固定成本。事实上,在解决方案中使用Vector而不是列表要快得多

def primes(n: Int) = {
  @tailrec
  def divisibleByAny(x: Int, list: Vector[Int]): Boolean = {
    if (list.isEmpty) false else {
      val (h +: t) = list
      h * h <= x && (x % h == 0 || divisibleByAny(x, t))
    }
  }
  @tailrec
  def morePrimes(from: Int, prev: Vector[Int]): Vector[Int] = {
    if (prev.length == n) prev else
      morePrimes(from + 2, if (divisibleByAny(from, prev)) prev else prev :+ from)
  }
  morePrimes(3, Vector(2))
}
def素数(n:Int)={
@泰勒克
def divisibleByAny(x:Int,list:Vector[Int]):布尔={
if(list.isEmpty)false else{
val(h+:t)=列表
h*h根据
Vector
s在追加、前置和查找时有一个摊销的固定成本。事实上,在解决方案中使用Vector而不是列表要快得多

def primes(n: Int) = {
  @tailrec
  def divisibleByAny(x: Int, list: Vector[Int]): Boolean = {
    if (list.isEmpty) false else {
      val (h +: t) = list
      h * h <= x && (x % h == 0 || divisibleByAny(x, t))
    }
  }
  @tailrec
  def morePrimes(from: Int, prev: Vector[Int]): Vector[Int] = {
    if (prev.length == n) prev else
      morePrimes(from + 2, if (divisibleByAny(from, prev)) prev else prev :+ from)
  }
  morePrimes(3, Vector(2))
}
def素数(n:Int)={
@泰勒克
def divisibleByAny(x:Int,list:Vector[Int]):布尔={
if(list.isEmpty)false else{
val(h+:t)=列表

我想你有两个主要的选择

  • 使用向量-这比列表更好用于追加。它是一个位图Trie数据结构()。它“有效地”追加到O(1)(即平均O(1))
  • 或者…可能是你不想要的答案

  • 使用像ListBuffer这样的可变数据结构-不变性很好尝试实现,应该是您的首选-但有时出于效率原因,您可能会使用可变结构。确保它不会“泄漏”的关键是什么如果你看一下List.scala实现,你会发现ListBuffer在内部使用了很多。但是,它在离开类之前被转换回了一个列表。如果它对核心scala库来说足够好,那么你可以在特殊情况下使用它

  • 我认为你有两个主要的选择

  • 使用向量-这比列表更好用于追加。它是一个位图Trie数据结构()。它“有效地”追加到O(1)(即平均O(1))
  • 或者…可能是你不想要的答案

  • 使用像ListBuffer这样的可变数据结构-不变性很好尝试实现,应该是您的首选-但有时出于效率原因,您可能会使用可变结构。确保它不会“泄漏”的关键是什么如果你看一下List.scala实现,你会发现ListBuffer在内部使用了很多。但是,它在离开类之前被转换回了一个列表。如果它对核心scala库来说足够好,那么你可以在特殊情况下使用它

  • 除了使用<代码>矢量< /代码>之外,还考虑使用高阶函数代替递归。这也是一种完全有效的函数样式。在我的机器上,以下代码的实现<代码> >任何< < /代码>,比运行<代码> Primes(1000000)< /C> >:

    时,比@ PyeTras TraceC实现快8倍左右。
    def divisibleByAny(x:Int,list:Vector[Int]):布尔值=
    
    除了使用<代码>向量< /代码>之外,还考虑使用高阶函数代替递归。这也是一个完全有效的函数样式。在我的机器上,下面的实现<代码>除以任何< /代码>,比运行<代码> Primes(1000000)时的@ PyeTras TraceC实现快8倍左右。

    def divisibleByAny(x:Int,list:Vector[Int]):布尔值=
    
    list.view.takeWhile(el=>el*el
    Vector
    s添加、删除(两端)和检索的成本为O(1)。除此之外,添加到列表开头是O(1),那么为什么不这样做呢?没关系,我明白为什么。
    Vector
    s添加、删除(两端)的成本为O(1)(摊销)除此之外,添加到列表开头的是O(1)那么为什么不这样做呢?没关系,我明白为什么了。谢谢,我试过了,它看起来和我要找的完全一样。我以前浏览这个比较表时,似乎把Vector错当成了类似命名的java类。我现在很高兴!谢谢,我试过了,它和我要找的完全一样。似乎我把Vector错当成了simila我以前浏览这个对照表的时候,给我命名为java类。我现在很高兴!
    def primes(n: Int) = {
        @tailrec
        def divisibleByAny(x: Int, list: Queue[Int]): Boolean = {
            if (list.isEmpty) false else {
                val (h, t) = list.dequeue
                h * h <= x && (x % h == 0 || divisibleByAny(x, t))
            }
        }
        @tailrec
        def morePrimes(from: Int, prev: Queue[Int]): Queue[Int] = {
            if (prev.size == n) prev else
                morePrimes(from + 2, if (divisibleByAny(from, prev)) prev else prev.enqueue(from))
        }
        morePrimes(3, Queue(2))
    }
    
    def primes(n: Int) = {
      @tailrec
      def divisibleByAny(x: Int, list: Vector[Int]): Boolean = {
        if (list.isEmpty) false else {
          val (h +: t) = list
          h * h <= x && (x % h == 0 || divisibleByAny(x, t))
        }
      }
      @tailrec
      def morePrimes(from: Int, prev: Vector[Int]): Vector[Int] = {
        if (prev.length == n) prev else
          morePrimes(from + 2, if (divisibleByAny(from, prev)) prev else prev :+ from)
      }
      morePrimes(3, Vector(2))
    }
    
    def divisibleByAny(x: Int, list: Vector[Int]): Boolean =
      list.view.takeWhile(el => el * el <= x).exists(x % _ == 0)