我使用akka
流编写了一个筛子来查找Int
任意来源的主要成员:
object Sieve extends App {
implicit val system = ActorSystem()
implicit val mat = ActorMaterializer(ActorMaterializerSettings(system))
implicit val ctx = implicitly[ExecutionContext](system.dispatcher)
val NaturalNumbers = Source.fromIterator(() => Iterator.from(2))
val IsPrimeByEurithmethes: Flow[Int, Int, _] = Flow[Int].filter {
case n: Int =>
(2 to Math.floor(Math.sqrt(n)).toInt).par.forall(n % _ != 0)
}
NaturalNumbers.via(IsPrimeByEurithmethes).throttle(100000, 1 second, 100000, ThrottleMode.Shaping).to(Sink.foreach(println)).run()
}
好的,所以这看起来效果不错。但是,至少有一些潜在的关注领域:
par.forall
运行模数检查,即它们完全隐藏在Flow
filter
内,但我可以看到如何{{1}有用从每个Map
的{{1}}到另一个candidate n
。也许。Map
我已经知道的不是素数,还是检查多余的n % _
。事实上,即使我认为n
是素数,也只需检查那时已知的素数就足够了。第二点是我更直接的关注。
我认为我可以很容易地证明存在一种更有效的方法 - 通过过滤掉每个新素数的n % _
。
那么......
n
现在找到source
并过滤来源后,我们需要知道下一个候选人是否为2, 3, 4, 5, 6, 7, 8, 9, 10, 11... => (after finding p=2)
2, 3, 5, 7, 9, , 11... => (after finding p=3)
2, 3, 5, 7, , 11... => ...
。好吧,如果最大的已知素数大于它的根,我们可以肯定地说它是素数,这将永远发生我相信,所以只需选择下一个元素就足够了......
p
在我看来,这就像重写最初提供的筛子一样,以引入严格的顺序依赖为代价进行更少的检查。
另一个想法 - 我可以通过符号来解决约束,比如需要素数的最小模数检查等等。
我是在叫错树吗?如果没有,我怎么能以这种方式搞乱我的来源?答案 0 :(得分:2)
我最近刚刚开始摆弄akka流,所以可能有比这更好的解决方案(特别是因为代码对我来说有点笨拙) - 但你的第二点似乎是我尝试构建的正确挑战akka流中的反馈循环。
在此处找到我的完整解决方案:https://gist.github.com/MartinHH/de62b3b081ccfee4ae7320298edd81ee
主要思想是积累已经找到的素数并将它们与输入的自然数流合并,这样可以根据N的结果完成素数检查:
def isPrime(n: Int, primesSoFar: SortedSet[Int]): Boolean =
!primesSoFar.exists(n % _ == 0) &&
!(primesSoFar.lastOption.getOrElse(2) to Math.floor(Math.sqrt(n)).toInt).par.exists(n % _ == 0)