【问题标题】:Scala stream to find primes in specific intervalScala流以查找特定间隔内的素数
【发布时间】:2015-12-04 21:44:28
【问题描述】:

问题:

我需要创建一个 Scala 程序,它使用 Stream 类并从区间 [i, j] 中找到第 n 个素数(而 1

更多信息:

我是 Scala 的新手,但我已经寻找了有关如何使用 Stream 在 Scala 中查找素数的各种示例。他们都没有帮助我实现我的目标。

我似乎无法理解如何使流成为区间 [i, j] 中的有限列表以及如何从该区间中获取第 n 个素数。

到目前为止我的代码:

def primeStream(args: Array[String], s: Stream[Int]): Stream[Int] =
        Stream.cons(s.head, primeStream(args,s.tail filter {_ % s.head != 0 }))

if (args(0).toInt < 1) {
        println("Entered parameter i does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
        sys.exit(1)
} else if (args(1).toInt < args(0).toInt) {
        println("Entered parameter j does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
        sys.exit(1)
}

val primes = primeStream(args,Stream.from(args(0).toInt)) // start from i element

primes take args(1).toInt foreach println //Take j elements

任何帮助将不胜感激!

解决方案:

def primeStream(s: Stream[Int]): Stream[Int] =
        Stream.cons(s.head, primeStream(s.tail filter {_ % s.head != 0 }))

if (args(0).toInt < 1) {
        println("Entered parameter i does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
        sys.exit(1)
} else if (args(1).toInt < args(0).toInt) {
        println("Entered parameter j does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
        sys.exit(1)
} else if (args(0).toInt == 1) {
        println("1 is not a prime by definition!") 
        sys.exit(1)  // if args(0) is 1 then function hangs up - didn't come up with a better solution for this
}

val primes = primeStream(Stream.from(args(0).toInt)) // get primes starting from given parameter

println(primes.takeWhile( _ < args(1).toInt).take(args(2).toInt).last) // get n-th prime and print it out

【问题讨论】:

  • 为什么primeStream 带args 参数?
  • 我从控制台运行这个脚本并将 3 个参数传递给 args 数组。
  • 我只是想让您了解一个事实,即在您的示例中,参数在单行 primeStream 方法中没有任何作用:它只是不断传递,因此完全没用.
  • 哦!你是对的。我正在努力通过任何方式让它工作。

标签: scala stream functional-programming primes


【解决方案1】:

您只需要在满足特定条件时让您的流生成值:

primes takeWhile(_ < j) take n foreach println

当然,您需要正确使用primeStream 函数。

算法部分,你最好在stackoverflow上搜索:

【讨论】:

  • 谢谢!这现在给了我区间 [i; j] 我应该从中获取特定的第 n 个元素。我如何取这个第 n 个元素?我假设,我传递了 3 个参数: i j k
  • 你需要在结果流中取最后一个元素,即primes takeWhile(_ &lt; j) take n last
  • 嗯,我现在感觉有点笨。为什么最后?例如,我有一个间隔 [2; 13] 中的素数列表,我想取第 5 个(第 n 个)元素,即 11 [2,3,5,7,11,13 ]。如何检查 11 是第 5 个元素?
  • 它是 last 在你 之后你得到 n 元素。
  • 不,我无法让它工作。如果我像这样运行它:primes takeWhile( _ &lt; args(1).toInt) take args(2).toInt last,那么会有一个警告说明 “有一个功能警告;使用 -feature 重新运行以获取详细信息”。如果我这样离开它:primes takeWhile( _ &lt; args(1).toInt) take args(2).toInt last println 那么它会显示错误“Int 不接受参数”。请详细说明一下好吗?
【解决方案2】:

这是一个学习练习,还是您在生产中需要它?对于后者,我建议使用来自spire 库的 spire.math.prime.stream。它使用 Eratosthenes 的分段流 实现,这可能比您在短时间内自己想出的要好。它还使用任意精度整数,因此适用于大于 2^64 的数字。

scala> import spire.math._
import spire.math._

scala> prime.stream.drop(10).take(10).toArray
res16: Array[spire.math.SafeLong] = Array(31, 37, 41, 43, 47, 53, 59, 61, 67, 71)

【讨论】:

  • 是的,这是一个学习练习。非常感谢您的评论 - 它确实看起来更容易更好,但我会采用我的解决方案。
  • 我发现了一个问题,如果我将间隔从 [2,..] 更改为大于 2 的值,例如[20,30] 并执行 scala prime.scala 20 30 2 它返回 21 但它应该返回 29,因为它是此特定间隔中的第二个素数。我尝试使用takeWhile 进行操作以达到所需的结果,但到目前为止还没有运气。为了实现这一目标,我应该在我的程序中进行哪些更改?你能帮忙吗?
猜你喜欢
  • 1970-01-01
  • 2020-09-18
  • 2021-08-22
  • 2021-12-04
  • 2015-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多