2014-11-28 3 views
4

Я изучаю Rust, поэтому я занимаюсь проблемами Project Euler, так как они хорошие упражнения imho. Но я уже застрял на второй проблеме. Идея состоит в том, чтобы найти сумму всех четных чисел, которые меньше 4000000 в последовательности Фибоначчи. Так что я пытался сделать это немного функциональный способ, и с помощью пользовательского итератора:Project Euler # 2 in Rust

use std::mem; 
static LIMIT: uint = 4000000u; 
struct Fibonacci { 
    current: uint, 
    next: uint, 
    limit: uint, 
} 
fn fibo(lim: uint) -> Fibonacci { 
    Fibonacci { 
     current: 1u, next: 1u, limit: lim 
    } 
} 

impl Iterator<uint> for Fibonacci { 
    fn next(&mut self) -> Option<uint> { 
     let nex = self.current + self.next; 
     let cur = mem::replace(&mut self.next, nex); 
     if cur >= self.limit { return None; } 
     Some(mem::replace(&mut self.current, cur)) 
    } 
} 

fn main() { 
    let sum = fibo(LIMIT).filter(|&x| x%2 == 0).fold(0, |sum, x| sum + x); 
    println!("Sum of fibs : {}", sum); 
} 

Он выглядит хорошо, и это дает правильную последовательность Фибоначчи (я проверил с println! с). Проблема в том, что она не дает правильную сумму: она выводит 1089154, тогда как она должна выводить 4613732. Мне кажется, что сбрасывает последнее число, но я не понимаю, почему!

Я полный новичок с Rust, поэтому любая помощь будет принята с благодарностью, спасибо!

+0

Вы протестировали ваш итератор Фибоначчи и проверили, что он произвел правильную последовательность чисел? Я [попробовал это здесь] (http://is.gd/ZutSp3), и последние два добавленных числа произведут 3524578, что меньше предела ... и похоже, что именно вас не хватает. –

+0

Спасибо, Matthieu, но вы получите тот же результат, что и я ... Я добавил фальцовку, и это дает мне неправильную сумму: вы можете проверить это [здесь] (http://is.gd/uLKa3G) – flure

+0

Да действительно , мой чек просто показывает, что проблема не в «фильтре», ни в 'fold', а в реализации вашего итератора. –

ответ

3

Что вы должны тестировать в своей выходной ветви - это значение self.current; вместо этого вы тестируете значение self.next. Другими словами, вы не можете вывести последнее число в последовательности (как предположил Маттие).

Я проверил, что если итератор правильно реализован, то он должен давать правильный результат с этим (с использованием grabbag_macros = "0.0.1" как Грузовое зависимость):

#![feature(phase)] 
#[phase(plugin, link)] extern crate grabbag_macros; 

static LIMIT: u64 = 4000000; 

fn main() { 
    let sum = recurrence![f[n]: u64 = 1, 1... f[n-1] + f[n-2]] 
     .take_while(|&n| n <= LIMIT) 
     .filter(|&n| n % 2 == 0) 
     .fold(0, |a, b| a + b); 
    println!("Sum of fibs: {}", sum); 
} 

Несколько других случайных заметок: Я бы избежать uint для это, поскольку это зависит от платформы. Вам не нужен суффикс u, если вам не нужно указывать тип. Вы можете использовать take_while или простой старый take вместо жесткого кодирования лимита в свой итератор.

+0

Большое спасибо, он решает мою проблему. Это была действительно глупая ошибка с моей стороны. Спасибо также за ваши советы и показывая использование 'reccurrence!'. которого я не знал. – flure

+0

Хорошая идея рекомендовать 'take_while', а тем более подвержен ошибкам! –