2013-12-06 17 views
3

Предположим, что fn scan(int, int) -> int.Проблемы со складками в ржавчине

При использовании

fn count(x: int, y: int) -> int 
{ 
    scan(x - 1, y - 1) + scan(x - 1, y) + scan(x - 1, y + 1) + scan(x, y - 1) 
     + scan(x, y + 1) + scan(x + 1, y - 1) + scan(x + 1, y) + scan(x + 1, y + 1) 
} 

я получить правильные результаты. Я пытаюсь получить те же результаты по fold с функцией scan по заданным диапазонам значений; однако, я не могу понять, как это правильно. Моя текущая попытка:

fn count_fold(x: int, y: int) -> int 
{ 
    std::iter::range_inclusive(-1, 1).zip(std::iter::range_inclusive(-1, 1)).fold(0, |a, (i, j)| { a + scan(x + i, y + j) }) 
} 

, который, кажется, возвращает только подмножество правильных результатов. Что я делаю не так? ТИА.

ответ

4

Когда вы используете zip двух итераторов, вы не создаете «продукт» итераций, как будто вы, похоже, хотите сделать. Скорее, вы повторяете оба итератора одновременно и создаете пару с итерированными значениями. Таким образом, в версии count_fold, закрытие будет вызываться только со следующими парами:

(-1, -1) 
(0, 0) 
(1, 1) 

Так что ваша count_fold функция на самом деле сродни

scan(x - 1, y - 1) + scan(x, y) + scan(x - 1, y + 1) 

Я могу ошибаться, но я не думаю, есть функция в std, которая создает произведение двух итераторов.

Кроме того, ваш метод count не использует scan(x, y) в сумме, поэтому он даже не является продуктом итераторов; вы должны быть осторожны в этом, если хотите создать свой собственный итератор продукта и использовать его для этой цели.

+0

Чтобы немного прояснить ситуацию, мне не нужно «сканировать (x, y)» там. Идея состоит в том, чтобы отсканировать [sic] окрестность Мура данных координат. –

4

Кирилл прав, говоря, что нет функции итератора-продукта. Тем не менее, можно вручную взять произведение двух итераторов путем складывания дважды:

use std::iter::range_inclusive; 

fn count_fold(x: int, y: int) -> int { 
    range_inclusive(-1, 1).fold(0, 
     |a, i| range_inclusive(-1, 1).fold(a, |b, j| b + scan(x + i, y + j))) 
} 

Хотя это выглядит как вам нужно фильтровать тот случай, когда i == 0 && j == 0, т.е.

fn count_fold(x: int, y: int) -> int { 
    range_inclusive(-1, 1).fold(0, 
     |a, i| range_inclusive(-1, 1).fold(a, 
      |b, j| if i == 0 && j == 0 {b} else {b + scan(x + i, y + j)})) 
} 

или

fn count_fold(x: int, y: int) -> int { 
    range_inclusive(-1, 1).fold(0, 
     |a, i| range_inclusive(-1, 1) 
      .filter(|&j| !(i == 0 && j == 0)) 
      .fold(a, |b, j| b + scan(x + i, y + j))) 
} 

Однако я почти сказать, что это понятнее повелительно:

fn count_fold(x: int, y: int) -> int { 
    let mut a = 0; 
    for i in range_inclusive(-1, 1) { 
     for j in range_inclusive(-1, 1) { 
      if !(i == 0 && j == 0) { a += scan(x + i, y + j) } 
     } 
    } 
    a 
} 
+0

Это странно. Ваша императивная версия, как и моя, дает правильные результаты, но ваша функциональная версия не работает (также, 'scan' фильтрует случаи, когда' i == 0 && j == 0', поэтому 'count' не нужно делать это). –

Смежные вопросы