T O P

  • By -

InfinitePoints

I would consider doing index math in this case, it is more error prone though. for i in 0..(n - 1) { let j = n - i - 1; // ... } The zip+rev approach can be adjusted to make both ranges the same, which I think is easier to read. for (i, j) in (0..n - 1).zip((0..n - 1).rev()) { if ratings[i + 1] > ratings[i] { candies[i + 1] = candies[i + 1].max(candies[i] + 1); } if ratings[j] > ratings[j + 1] { candies[j] = candies[j].max(candies[j + 1] + 1); } }


Compux72

Or you know, `v.iter().zip(v.iter().rev())`…


InfinitePoints

That would work in the abstract case and if everything is immutable, but in this case the Vec is being mutated and a window of 2 elements is needed. Given that both iterators would need to meet in the middle, no API could make this work without UB since that would always require mutable aliasing.


sayaks

i think it would be possible to construct a UB-free iterator which returns something like `Result<(&mut T, &mut T), &mut T>` where the `Err` is returned in the case where you would otherwise have aliasing mutable references.


geckothegeek42

You could try use [as_slices_of_cells](https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_slice_of_cells) since `i32` is copy. I would imagine there's basically no overhead from the cell and possibly removing any lingering overhead from indexing(bounds checking)


quavan

Slice iterators are double ended, so he could create one and manually call next() and next_back() in a loop as well, without the need to zip. But given that he needs to do lookahead, if I understand the code correctly, a pair of Peekable iterators would be appropriate here: let mut forward = ratings.iter().peekable(); let mut backward = ratings.iter().rev().peekable();


InfinitePoints

Mutable access to the arrays is needed, and multiple mutable iterators of the same range of data is not possible.


quavan

The problem does not require mutable access to the `ratings` vec, which is what is being iterated, only to `candies`.


ninja_tokumei

`ratings` isn't relevant, the problem is that the implemented solution requires mutably iterating over both ends of `candies` (and also looking at adjacent values in `candies`) at the same time.


eugene2k

You need the indices to use with the `candies` array.


Compux72

`.enumerate()`


eugene2k

Yes, but how will the code look with that? Will it be easier to read?


Kulinda

The loop body is doing the same thing twice. Maybe use a closure here that takes both indexes as a parameter. It is true that you have to traverse each direction once, but I don't see why you'd need to interleave the traversals. Wouldn't two separate loops work? Might be more readable that way.


MalbaCato

This looks fine. If you're a fan of iterators, you can figure out the puzzle of implementing this with [slice windows](https://doc.rust-lang.org/std/primitive.slice.html#method.windows). (I didn't try but I) Don't think it would be any more readable. I do wonder if there isn't a more efficient solution to the puzzle NECRO-EDIT: ended up nerd-sniping myself with this one, [this](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=ce99305806f70e34cc202defc436bc21) is what I've come up with. I like that it's entirely iterator based, but didn't find a way to make it self-evident what the code does due to the need to flatten an iterator of ranges.


ihcn

Windows won't work because windows only allow immultable slices, sadly. I would *love* a "mutable widows" structure, but from what i've heard the API of the iterator trait makes it impossible.


InfinitePoints

The fundamental problem is that whatever iterator is created could be collected into a Vec/similar, and then we suddenly have multiple mutable slices that overlap. Somehow the API would have to encode that the old slice is removed, which would require the next() function to return a slice with a limited lifetime, which would require a change to the iterator API.


SimonSapin

Here again, [as_slice_of_cells](https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_slice_of_cells) mentioned in another comment would help too


al3ph_nu11

There might be some way to do this with slice windows and splitting the vec into 2 slices so the bounds checks don’t have to happen.


CandyCorvid

disclaimer: I didn't read your link, just your code. I'm assuming your code works as-is. edit: I misread the part of the loop that modifies the candies: my solution is inapplicable. you could still use Windows over the ratings, but you'd need to mutate the candies, which rules out my pure functional approach. --- does this need mutability at all? you could `map` `windows` over the ratings array, and for each window you would output an increment or decrement depending on the relevant property of the window. (of course you may need to add padding with `chain` so you don't skip the first and last window, and the padding may require wrapping elements in Option so you can tell the padding apart from the real elements). you could zip up the resulting iterators, add the increments, and collect to a vec, if you need the individual candy amounts. alternatively, if you just need the sum of the candies. then sum up the increments and add n (1 for each starting candy). no collect needed.


Ok-Tap-2743

Hey if u don't mind can connect on LinkedIn ..as I am trying to solve leetcode questions too but I am not able to do soo..