- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试学习 F#,所以我访问了 Project Euler我目前正在研究 Problem 3 .
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143?
一些需要考虑的事情:
在下面的代码中,我标记了这个问题所涉及的部分。
let isPrime(n:int64) =
let rec check(i:int64) =
i > n / 2L or (n % i <> 0L && check(i + 1L))
check(2L)
let greatestPrimeFactor(n:int64) =
let nextPrime(prime:int64):int64 =
seq { for i = prime + 1L to System.Int64.MaxValue do if isPrime(i) then yield i }
|> Seq.skipWhile(fun v -> n % v <> 0L)
|> Seq.hd
let rec findNextPrimeFactor(number:int64, prime:int64):int64 =
if number = 1L then prime else
//************* No variable
(fun p -> findNextPrimeFactor(number / p, p))(nextPrime(prime))
//*************
//************* Variable
let p = nextPrime(prime)
findNextPrimeFactor(number / p, p)
//*************
findNextPrimeFactor(n, 2L)
更新
根据一些反馈,我重构了代码,使其速度提高了 10 倍。
module Problem3
module private Internal =
let execute(number:int64):int64 =
let rec isPrime(value:int64, current:int64) =
current > value / 2L or (value % current <> 0L && isPrime(value, current + 1L))
let rec nextPrime(prime:int64):int64 =
if number % prime = 0L && isPrime(prime, 2L) then prime else nextPrime(prime + 1L)
let rec greatestPrimeFactor(current:int64, prime:int64):int64 =
if current = 1L then prime else nextPrime(prime + 1L) |> fun p -> greatestPrimeFactor(current / p, p)
greatestPrimeFactor(number, 2L)
let execute() = Internal.execute(600851475143L)
更新
我要感谢大家的建议。这个最新版本是我收到的所有建议的汇编。
module Problem3
module private Internal =
let largestPrimeFactor number =
let rec isPrime value current =
current > value / 2L || (value % current <> 0L && isPrime value (current + 1L))
let rec nextPrime value =
if number % value = 0L && isPrime value 2L then value else nextPrime (value + 1L)
let rec find current prime =
match current / prime with
| 1L -> prime
| current -> nextPrime (prime + 1L) |> find current
find number (nextPrime 2L)
let execute() = Internal.largestPrimeFactor 600851475143L
最佳答案
函数式编程通过练习变得更容易和更自动化,所以如果您在第一次尝试时没有完全正确,请不要担心。
考虑到这一点,让我们来看看您的示例代码:
let rec findNextPrimeFactor(number:int64, prime:int64):int64 =
if number = 1L then prime else
//************* No variable
(fun p -> findNextPrimeFactor(number / p, p))(nextPrime(prime))
//*************
//************* Variable
let p = nextPrime(prime)
findNextPrimeFactor(number / p, p)
//*************
您的no variable
版本很奇怪,不要使用它。我喜欢带有显式 let 绑定(bind)的版本。
另一种写法是:
nextPrime(prime) |> fun p -> findNextPrimeFactor(number / p, p)
ok 像这样写它偶尔也很有用,但仍然让人觉得有点奇怪。大多数时候,我们使用|>
来curry 值而不 需要命名我们的变量(以“pointfree”风格)。尝试预测你的函数将如何被使用,如果可能的话,重写它,这样你就可以在没有显式声明变量的情况下与管道运算符一起使用它。例如:
let rec findNextPrimeFactor number prime =
match number / prime with
| 1L -> prime
| number' -> nextPrime(prime) |> findNextPrimeFactor number'
不再有命名参数 :)
好的,现在我们已经解决了这个问题,让我们看看您的 isPrime
函数:
let isPrime(n:int64) =
let rec check(i:int64) =
i > n / 2L or (n % i <> 0L && check(i + 1L))
check(2L)
您可能听说过使用递归而不是循环,这是对的。但是,只要有可能,您应该使用折叠、映射或高阶函数抽象掉递归。这样做的两个原因:
它更具可读性,并且
递归写得不当会导致栈溢出。例如,您的函数不是尾递归的,因此它会在 n
的大值上爆炸。
我会像这样重写 isPrime
:
let isPrime n = seq { 2L .. n / 2L } |> Seq.exists (fun i -> n % i = 0L) |> not
大多数时候,如果您可以抽象出显式循环,那么您只需对输入序列应用转换,直到获得结果:
let maxFactor n =
seq { 2L .. n - 1L } // test inputs
|> Seq.filter isPrime // primes
|> Seq.filter (fun x -> n % x = 0L) // factors
|> Seq.max // result
我们在这个版本中甚至没有中间变量。凉爽!
My second priority is I would like it to be fast and efficient.
大多数时候,F# 在速度方面与 C# 相当,或者说“足够快”。如果您发现您的代码需要很长时间才能执行,这可能意味着您使用了错误的数据结构或错误的算法。有关具体示例,请阅读评论 on this question .
因此,我编写的代码在某种意义上是“优雅”的,因为它简洁明了,给出了正确的结果,并且不依赖于任何诡计。不幸的是,它不是很快。开始:
它使用试除法创建素数序列,而埃拉托色尼筛法要快得多。 [编辑:我写了一个有点天真的版本的这个筛子,它不适用于大于 Int32.MaxValue 的数字,所以我删除了代码。]
阅读维基百科关于 prime counting function 的文章,它将为您提供有关计算第一个 n
素数以及估计 nth
素数的上限和下限的指导。
[编辑:我包含了一些代码,其中包含了埃拉托色尼筛法的一些天真的实现。它仅适用于小于 int32.MaxValue 的输入,因此它可能不适合欧拉项目。]
关于f# - 在创建中间值时,我应该存储它吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2036073/
我是 Javascript 的新手。由于一些遗留系统,目前我正在将一些 ES6 代码转换回 ES5 代码。我转换了以下代码: $row.find('.gridCellDetailAction') .
这是我的父类,它有 trigger 方法,即 public 方法: class BaseEffect { //properties and contructor... //other
我正在关注构建你的第一个区 block 链教程 (https://www.youtube.com/watch?v=coQ5dg8wM2o&t=494s)。 我的 index.html 中有以下内容:
我是一个使用 ScrollMagic 的菜鸟,并尝试通过复制 ScrollMagic 的示例之一来学习。 http://scrollmagic.io/examples/advanced/advance
需要帮助调试一小段脚本。 我使用“masonry”插件以平铺方式排列多个 div。该脚本似乎工作正常,除了我收到错误 jQuery (intermediate value).imagesLoaded
我使用 jQuery Autosize 插件: http://www.jacklmoore.com/autosize/ 您可以在此处看到脚本本身: http://www.jacklmoore.com/
我必须遵循以下关系: class Course true, :id => false do |t| t.integer :user_id t.integer :course_id t.i
我的路线是这样的 import express from 'express' import mysql from 'mysql2' import { dbusername } from '../con
我正在尝试使用 Chart Js 库生成圆环图,结果抛出错误 Uncaught TypeError: (intermediate value).Doughnut is not a function。我
我在一个名为 StructureWindowComponent 的组件中实现事件处理,并且在 LeggerStructureWindowComponent 中也有一个覆盖它。 在基类(Structur
问题:我想将使用 xlsx 的条件格式 icon_set 应用于列,但没有获得正确值的正确箭头 这是我想要的输出: 这是我当前的输出: 这是我的代码: writer.sheets[sheet].con
这是我的 webpack.config.js "use strict"; var webpack = require('webpack') module.exports = { entry:
请帮助我。当我在 ASP.NET MVC 中使用 jQuery 时出现错误。 Uncaught TypeError: ((x.event.special[i.origType] || (interme
我是一名优秀的程序员,十分优秀!