Hi,
trying to learn Rust by doing this year's adventofcode, and really struggling with a double filter_map
.
Would appreciate some help in understanding what needs fixing in my code. Also alternative ways to solve this are welcome.
Basically I have multi line string with digits. I want to map the coordinates (row, col)
of all zero digits in this string.
Example input string:
let input_str = "
102
010
123
".trim();
First I parse that into a Vec<Vec<u32>>
:
let input_vec: Vec<Vec<u32>> =
input_str
.lines()
.map(|line|
line.chars().map(|c|
c.to_digit(10).unwrap()).collect()
).collect();
Then I try to do a double filter_map
, first to filter only the rows that have 0
s, indexed with i
, then only the digits that are 0
, indexed j
:
// creates a tuple (row, col) with all occurences of `0`
// in the example above, it would be
// `[(0, 1), (1, 0), (1, 2)]`
let zeros_idx = input_vec
.iter()
.enumerate()
.filter(|(i, row)| row.contains(&0))
.filter_map(|(i, row)| {
row.iter().enumerate().filter_map(|(j, &c)|
(c == 0).then_some(Some((i, j))))
}
)
.collect();
Rust compiler is not happy with my code telling me this:
| / row.iter().enumerate().filter_map(|(j, &c)|
| | (c == 0).then_some(Some((i, j))))
| |_________________________________________________^ expected `Option<_>`, found `FilterMap<Enumerate<...>, ...>`
Link to this example here: Playground
I tried to collect()
something at that location:
(c == 0).then_some(Some((i, j)))).collect::<Option<(usize, usize)>>()
Then the compiler's rant gets nastier:
| (c == 0).then_some(Some((i, j)))).collect::<Option<(usize, usize)>>()
| ------- ^^^^^^^^^^^^^^^^^^^^^^ the trait `Extend<usize>` is not implemented for `usize`, which is required by `Option<(usize, usize)>: FromIterator<Option<(usize, usize)>>`
| |
| required by a bound introduced by this call
This example here: Playground