【问题标题】:Recursive function that returns a Vec返回 Vec 的递归函数
【发布时间】:2017-09-20 16:23:07
【问题描述】:

我继续与递归的概念作斗争。我有一个函数,它接受 u64 并返回该整数因子的 Vec<u64>。我想在Vec 中的每个项目上递归调用此函数,返回一个扁平的Vec,直到函数为每个项目返回Vec<self>,即每个项目都是素数。

fn prime_factors(x: u64) -> Vec<u64> {
    let factors = factoring_method(x);
    factors.iter().flat_map(|&i| factoring_method(i)).collect()
}

(The complete code)

这仅返回最终迭代的 Vec 因子,并且没有条件允许它继续运行,直到项目全部为素数。

factoring_method 是一个我很满意的正方形的全等。我确信有很大的优化空间,但我希望在重构之前得到一个完整的工作版本。我认为递归应该在congruence_of_squares 中调用它返回的Vec 的每个成员,但我不确定如何构建条件以防止它无限地这样做。

【问题讨论】:

  • 实际上,如果没有factoring_method,就很难回答。请提供minimal reproducible example
  • factoring_methodprime_factors 应该是同一个函数吗?
  • @sellibitze -- 没有分解方法是分开的,您遇到了 Shepmaster 指出的相同概念问题。对于没有使用 E_net4 请求的代码更新问题,我深表歉意。病了几天。我会在今晚尝试更新以澄清。
  • congruence_of_squares(9) 返回[1, 9] 似乎不正确。
  • @Shepmaster 为什么不呢?小于或等于 9 的平方只有 4 和 9。4 不是 9 的因数,所以它应该返回 9 及其互补因数 1。

标签: recursion rust flatten


【解决方案1】:

有用的递归需要两件事:

  1. 函数直接或间接调用自身。
  2. 有一些终止案例。

一个数的素因数分解的定义是:

  • 如果数是素数,那是唯一的素数因数
  • 否则,组合数的一对因数的质因数

由此,我们可以确定终止条件(“如果它是素数”)和递归调用(“因子的素数”)。

请注意,我们还没有编写任何代码——到目前为止,一切都是概念性的。

然后我们可以将这个想法转录为 Rust:

fn prime_factors(x: u64) -> Vec<u64> {
    if is_prime(x) {
        vec![x]
    } else {
        factors(x).into_iter().flat_map(prime_factors).collect()
    }
}

这里有有趣的部分:

  • 我们使用into_iter 来避免取消引用迭代值的需要​​。
  • 我们可以直接将函数名作为闭包传递,因为类型对齐。

一些(低效的)辅助函数完善了实现:

fn is_prime(x: u64) -> bool {
    !(2..x).any(|i| x % i == 0)
}

fn factors(x: u64) -> Vec<u64> {
    match (2..x).filter(|i| x % i == 0).next() {
        Some(v) => vec![v, x / v],
        None => vec![],
    }
}

【讨论】:

    猜你喜欢
    • 2022-01-16
    • 1970-01-01
    • 2013-09-21
    • 2017-01-12
    • 2015-10-22
    • 1970-01-01
    相关资源
    最近更新 更多