Rust中tribonaci序列的惯用实现

Rust中tribonaci序列的惯用实现,rust,fibonacci,idioms,fall-through,Rust,Fibonacci,Idioms,Fall Through,我是个新手,但作为哈斯克尔的粉丝,我非常欣赏match在Rust中的工作方式。现在,我面临着一个罕见的情况,我确实需要失败——从某种意义上说,我希望执行多个重叠案例的所有匹配案例。这项工作: fn options(stairs: i32) -> i32 { if stairs == 0 { return 1; } let mut count: i32 = 0; if stairs >= 1 { count += opti

我是个新手,但作为哈斯克尔的粉丝,我非常欣赏match在Rust中的工作方式。现在,我面临着一个罕见的情况,我确实需要失败——从某种意义上说,我希望执行多个重叠案例的所有匹配案例。这项工作:

fn options(stairs: i32) -> i32 {
    if stairs == 0 {
        return 1;
    }
    let mut count: i32 = 0;
    if stairs >= 1 {
        count += options(stairs - 1);
    }
    if stairs >= 2 {
        count += options(stairs - 2);
    }
    if stairs >= 3 {
        count += options(stairs - 3);
    }
    count
}
我的问题是,这是《铁锈》中的惯用说法,还是有更好的方法

上下文是破解编码采访中的一个问题:“一个孩子跑上一个有n步的楼梯,一次可以跳1步、2步或3步。实现一种方法来计算孩子可以跑上楼梯的可能方式。”

基于“我发现你可以用这样更简洁的方式写它:

fn options(stairs: i32) -> i32 {
    match stairs {
        0 => 0,
        1 => 1,
        2 => 1,
        3 => 2,
        _ => options(stairs - 1) + options(stairs - 2) + options(stairs - 3)
    }
}
我还建议将函数定义更改为仅接受正整数,例如u32。

基于我发现的,您可以用以下更简洁的方式编写:

fn options(stairs: i32) -> i32 {
    match stairs {
        0 => 0,
        1 => 1,
        2 => 1,
        3 => 2,
        _ => options(stairs - 1) + options(stairs - 2) + options(stairs - 3)
    }
}

我还建议将函数定义更改为仅接受正整数,例如u32。

要回答一般性问题,我认为匹配和故障排除在某种程度上是对立的

match用于根据不同的模式执行不同的操作。大多数情况下,通过模式匹配提取的值与故障诊断非常不同,没有意义

相反,错误提示指向一系列操作。有很多方法来表达序列:递归,迭代

例如,在您的情况下,可以使用循环:

for i in 1..4 {
    if stairs >= i {
        count += options(stairs - i);
    }
}

当然,在这个特殊的例子中,我发现@ljedrz'的解决方案更加优雅。

为了回答这个一般性的问题,我认为match和fallthrough在某种程度上是对立的

match用于根据不同的模式执行不同的操作。大多数情况下,通过模式匹配提取的值与故障诊断非常不同,没有意义

相反,错误提示指向一系列操作。有很多方法来表达序列:递归,迭代

例如,在您的情况下,可以使用循环:

for i in 1..4 {
    if stairs >= i {
        count += options(stairs - i);
    }
}
当然,在这个特殊的例子中,我发现@ljedrz'的解决方案更为优雅。

我建议在生锈的情况下使用。最好使用:

我劝你不要生锈。最好使用:


在我看来,您的代码非常地道,尽管@ljedrz建议对相同的策略进行更优雅的重写

由于这是一个面试问题,值得一提的是,两种解决方案都不会被视为令人惊讶的答案,因为这两种解决方案在楼梯数量上都需要指数时间

如果我试图破解一个编码面试,我可能会这样写:

fn选项楼梯:使用->u128{ 设muto=vec![1,1,2,4]; 3.楼梯中的uu{ o、 普索[o.len-1]+o[o.len-2]+o[o.len-3]; } o[楼梯] } 我们将每个值缓存在一个数组中,而不是每次重新计算optionsn。所以,这应该是线性时间,而不是指数时间。我还切换到u128,以便能够返回较大输入的解决方案


请记住,这不是最有效的解决方案,因为它使用线性空间。只需跟踪数组的最后三个元素,就可以避免使用常量空间。我选择它是为了在简洁性、可读性和效率之间达成折衷。

我觉得您的代码非常地道,尽管@ljedrz建议对相同的策略进行更优雅的重写

由于这是一个面试问题,值得一提的是,两种解决方案都不会被视为令人惊讶的答案,因为这两种解决方案在楼梯数量上都需要指数时间

如果我试图破解一个编码面试,我可能会这样写:

fn选项楼梯:使用->u128{ 设muto=vec![1,1,2,4]; 3.楼梯中的uu{ o、 普索[o.len-1]+o[o.len-2]+o[o.len-3]; } o[楼梯] } 我们将每个值缓存在一个数组中,而不是每次重新计算optionsn。所以,这应该是线性时间,而不是指数时间。我还切换到u128,以便能够返回较大输入的解决方案


请记住,这不是最有效的解决方案,因为它使用线性空间。只需跟踪数组的最后三个元素,就可以避免使用常量空间。我选择它作为简洁性、可读性和效率之间的折衷。

直到tribonacci序列存在^^。直到tribonacci序列存在^^。好主意!我的代码与那个序列有细微的不同,但感谢您教会我它的存在!但是我可以调整你的想法,通过使用这些锚来返回相同的结果:0=>0,1=>1,2=>2,3=>4。我将为我的问题添加上下文。这段代码当然是惯用的、优雅的,而且可读性非常好!性能/效率方面的一个缺点是它将
以指数级的次数草率调用期权函数。在铁锈操场上,我发现它在计算选项40之前超时了。啊,我认为这实际上应该是:0=>1,1=>1,2=>2,3=>4。想起来有点奇怪,但是有一种方法可以爬零级楼梯。这与为什么0!=一个空产品。好主意!我的代码与那个序列有细微的不同,但感谢您教会我它的存在!但是我可以调整你的想法,通过使用这些锚来返回相同的结果:0=>0,1=>1,2=>2,3=>4。我将为我的问题添加上下文。这段代码当然是惯用的、优雅的,而且可读性非常好!性能/效率方面的一个缺点是,它将以指数级的次数递归调用期权函数。在铁锈操场上,我发现它在计算选项40之前超时了。啊,我认为这实际上应该是:0=>1,1=>1,2=>2,3=>4。想起来有点奇怪,但是有一种方法可以爬零级楼梯。这与为什么0!=一个空的产品。谢谢!不确定接受哪个答案。你的问题和我的问题一样一般,基本上是“不,这很好。”与我的特定示例相比,Ljedrz是一个非常受欢迎的改进。丹尼斯德雷舍:我建议接受勒杰兹的回答。在测试中,答案的分数表示其总体有用性,而接受分数表示其对OP的有用性;因此,既然勒杰德兹的回答是针对这一特殊情况的一个非常优雅的解决方案,我个人会接受它,而不是一个更笼统和模糊的陈述。我明白了,谢谢!我没有意识到意思上的区别-谢谢不确定接受哪个答案。你的问题和我的问题一样一般,基本上是“不,这很好。”与我的特定示例相比,Ljedrz是一个非常受欢迎的改进。丹尼斯德雷舍:我建议接受勒杰兹的回答。在测试中,答案的分数表示其总体有用性,而接受分数表示其对OP的有用性;因此,既然勒杰德兹的回答是针对这一特殊情况的一个非常优雅的解决方案,我个人会接受它,而不是一个更笼统和模糊的陈述。我明白了,谢谢!我没有意识到意思上的区别-哦,该死,但作为一个蟒蛇学家,我不能抱怨。您的代码非常有趣,我需要进行一些研究才能理解。谢谢哦,该死,但作为一个蟒蛇学家,我不能抱怨。您的代码非常有趣,我需要进行一些研究才能理解。谢谢