diff options
| author | Federico Igne <git@federicoigne.com> | 2020-12-26 17:48:38 +0000 |
|---|---|---|
| committer | Federico Igne <git@federicoigne.com> | 2021-11-03 18:55:08 +0000 |
| commit | 02481656966b0a8dfc95cf3c22bcc049660ff7d4 (patch) | |
| tree | 8e39798fcaf27931d91c2088423fd4e97adcfc2d /beer-song/src/intersperse.rs | |
| parent | 4e2052c4d792540c2f742b2c2a081b11117ed41d (diff) | |
| download | exercism-02481656966b0a8dfc95cf3c22bcc049660ff7d4.tar.gz exercism-02481656966b0a8dfc95cf3c22bcc049660ff7d4.zip | |
Move Rust exercises in a subdirectory
Diffstat (limited to 'beer-song/src/intersperse.rs')
| -rw-r--r-- | beer-song/src/intersperse.rs | 52 |
1 files changed, 0 insertions, 52 deletions
diff --git a/beer-song/src/intersperse.rs b/beer-song/src/intersperse.rs deleted file mode 100644 index 51580e6..0000000 --- a/beer-song/src/intersperse.rs +++ /dev/null | |||
| @@ -1,52 +0,0 @@ | |||
| 1 | use std::rc::Rc; | ||
| 2 | |||
| 3 | /// An iterator that allows to insert a given element `elem` every `interval` elements of the input | ||
| 4 | /// iterator. | ||
| 5 | /// | ||
| 6 | /// The interleaved element is wrapped in a `Rc` smart pointer to avoid hard copies. | ||
| 7 | pub struct Intersperse<I: Iterator> { | ||
| 8 | inner: std::iter::Peekable<I>, // required to have `peek(..)` | ||
| 9 | elem: Rc<I::Item>, | ||
| 10 | interval: u32, | ||
| 11 | intersperse: u32, | ||
| 12 | } | ||
| 13 | |||
| 14 | impl<I: Iterator> Intersperse<I> { | ||
| 15 | pub fn new(inner: I, elem: I::Item, interval: u32) -> Intersperse<I> { | ||
| 16 | Intersperse { | ||
| 17 | inner: inner.peekable(), | ||
| 18 | elem: Rc::new(elem), | ||
| 19 | interval: interval + 1, // `+ 1` needed to align semantics and implementation | ||
| 20 | intersperse: 0, | ||
| 21 | } | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | impl<I: Iterator> Iterator for Intersperse<I> { | ||
| 26 | type Item = Rc<I::Item>; | ||
| 27 | |||
| 28 | fn next(&mut self) -> Option<Self::Item> { | ||
| 29 | // Counter rotation | ||
| 30 | self.intersperse = (self.intersperse + 1) % self.interval; | ||
| 31 | // Insert a copy of the element only when counter goes to 0 and we haven't reached the end | ||
| 32 | // of the inner iterator. | ||
| 33 | if self.intersperse == 0 && self.inner.peek().is_some() { | ||
| 34 | Some(Rc::clone(&self.elem)) | ||
| 35 | } else { | ||
| 36 | self.inner.next() | ||
| 37 | .map(|x| Rc::new(x)) // Go from Option<I::Item> to Option<Rc<I::Item>> | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | /// Extend `Iterator`s with `intersperse` function. | ||
| 43 | pub trait IntersperseIterator: Iterator { | ||
| 44 | fn intersperse(self, elem: Self::Item, interval: u32) -> Intersperse<Self> | ||
| 45 | where | ||
| 46 | Self: Sized, | ||
| 47 | { | ||
| 48 | Intersperse::new(self, elem, interval) | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | impl<I: Iterator> IntersperseIterator for I {} | ||
