Is it possible to implement a custom Iterator::sum in Rust? - iterator

I am trying to learn about iterators with an iterator that produces triangle numbers. Triangle numbers are 1, 3, 6, 10, 15 where 1 = 1, 3 = 1 + 2, 6 = 1 + 2 + 3 etc. I have the basics of this created:
pub struct Triangle {
cur: u32,
n: u32,
m: u32,
}
impl Iterator for Triangle {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.n == self.m {
return None;
}
self.n = self.n + 1;
self.cur = self.cur + self.n;
Some(self.cur)
}
}
A quick runnable example of this is
let t = Triangle { cur: 0, n: 0, m: 10 };
let s: u32 = t.sum();
println!("{}", s); // prints 220
Is it possible to create a custom summation function for the iterator that returns type u32? I was hoping to be able to do this with the default iterator and sum functions, and not have to make my own specialized function.
What I was hoping to be able to do is:
use std::iter::Sum;
impl Sum<u32> for u32 {
fn sum<I>(iter: I) -> Self
where
I: Triangle,
{
let nsum = (self.n * (self.n + 1) * (self.n + 2)) / 6;
let msum = (self.m * (self.m + 1) * (self.m + 2)) / 6;
msum - nsum
}
}
but this does not work. The error that I get with this is
error[E0404]: expected trait, found struct `Triangle`
--> src/main.rs:26:12
|
26 | I: Triangle,
| ^^^^^^^^ not a trait
I could change it from Triangle to Iterator like it wants, but that would prevent me from accessing the m and n values of the Triangle struct.
How do I do this? Is it impossible? I know that I could write my own function like my_sum(), but I was hoping to be able to do it in the context of an iterator.

You cannot specialize the existing implementation of Sum, but you can specialize Iterator::sum in your iterator! It's a bit tricky, though, since its return type is generic.
use std::iter::{self, Sum};
impl Iterator for Triangle {
// existing members are unchanged
fn sum<S>(self) -> S
where
S: Sum<Self::Item>,
{
let nsum = (self.n * (self.n + 1) * (self.n + 2)) / 6;
let msum = (self.m * (self.m + 1) * (self.m + 2)) / 6;
S::sum(iter::once(msum - nsum))
}
}
We cannot return a fixed type (such as u32), as that would not respect the contract defined by the Iterator trait. All we know about the return type S is that it implements Sum<Self::Item>. Sum has a single method, sum, that returns Self, so we can use it to produce a value of type S. The method expects an iterator; we feed it a Once, "an iterator that yields an element exactly once". Since that iterator will iterate a fixed number of times, we can expect sum to perform a fixed number of operations.
When you compile the program in release mode and S is u32, the whole sum call is optimized away, and the function returns msum - nsum directly.

Related

Why does `variable++` increment the variable but `variable + 1` does not?

Here's the problem in which I encountered this issue:
The function should compare the value at each index position and score a point if the value for that position is higher. No point if they are the same. Given a = [1, 1, 1] b = [1, 0, 0] output should be [2, 0]
fun compareArrays(a: Array<Int>, b: Array<Int>): Array<Int> {
var aRetVal:Int = 0
var bRetVal:Int = 0
for(i in 0..2){
when {
a[i] > b[i] -> aRetVal + 1 // This does not add 1 to the variable
b[i] > a[i] -> bRetVal++ // This does...
}
}
return arrayOf(aRetVal, bRetVal)
}
The IDE even says that aRetVal is unmodified and should be declared as a val
What others said is true, but in Kotlin there's more. ++ is just syntactic sugar and under the hood it will call inc() on that variable. The same applies to --, which causes dec() to be invoked (see documentation). In other words a++ is equivalent to a.inc() (for Int or other primitive types that gets optimised by the compiler and increment happens without any method call) followed by a reassignment of a to the incremented value.
As a bonus, consider the following code:
fun main() {
var i = 0
val x = when {
i < 5 -> i++
else -> -1
}
println(x) // prints 0
println(i) // prints 1
val y = when {
i < 5 -> ++i
else -> -1
}
println(y) // prints 2
println(i) // prints 2
}
The explanation for that comes from the documentation I linked above:
The compiler performs the following steps for resolution of an operator in the postfix form, e.g. a++:
Store the initial value of a to a temporary storage a0;
Assign the result of a.inc() to a;
Return a0 as a result of the expression.
...
For the prefix forms ++a and --a resolution works the same way, and the effect is:
Assign the result of a.inc() to a;
Return the new value of a as a result of the expression.
Because
variable++ is shortcut for variable = variable + 1 (i.e. with assignment)
and
variable + 1 is "shortcut" for variable + 1 (i.e. without assignment, and actually not a shortcut at all).
That is because what notation a++ does is actually a=a+1, not just a+1. As you can see, a+1 will return a value that is bigger by one than a, but not overwrite a itself.
Hope this helps. Cheers!
The equivalent to a++ is a = a + 1, you have to do a reassignment which the inc operator does as well.
This is not related to Kotlin but a thing you'll find in pretty much any other language

Iterating over a range of generic type

I have a trait
trait B {
type Index: Sized + Copy;
fn bounds(&self) -> (Self::Index, Self::Index);
}
I want to get all the Indexes within bounds:
fn iterate<T: B>(it: &T) {
let (low, high) = it.bounds();
for i in low..high {}
}
This won't work since there's no constraint that the type T can be "ranged" over, and the compiler says as much:
error[E0277]: the trait bound `<T as B>::Index: std::iter::Step` is not satisfied
--> src/main.rs:8:5
|
8 | for i in low..high {}
| ^^^^^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `<T as B>::Index`
|
= help: consider adding a `where <T as B>::Index: std::iter::Step` bound
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range<<T as B>::Index>`
I tried adding the Step bound to Index
use std::iter::Step;
trait B {
type Index: Sized + Copy + Step;
fn bounds(&self) -> (Self::Index, Self::Index);
}
but apparently it isn't stable:
error: use of unstable library feature 'step_trait': likely to be replaced by finer-grained traits (see issue #42168)
--> src/main.rs:1:5
|
1 | use std::iter::Step;
| ^^^^^^^^^^^^^^^
error: use of unstable library feature 'step_trait': likely to be replaced by finer-grained traits (see issue #42168)
--> src/main.rs:4:32
|
4 | type Index: Sized + Copy + Step;
| ^^^^
Am I missing something or is it just not possible to do so right now?
If you want to require that a Range<T> can be iterated over, just use that as your trait bound:
trait Bounded {
type Index: Sized + Copy;
fn bounds(&self) -> (Self::Index, Self::Index);
}
fn iterate<T>(it: &T)
where
T: Bounded,
std::ops::Range<T::Index>: IntoIterator,
{
let (low, high) = it.bounds();
for i in low..high {}
}
fn main() {}
To do this kind of thing generically the num crate is helpful.
extern crate num;
use num::{Num, One};
use std::fmt::Debug;
fn iterate<T>(low: T, high: T)
where
T: Num + One + PartialOrd + Copy + Clone + Debug,
{
let one = T::one();
let mut i = low;
loop {
if i > high {
break;
}
println!("{:?}", i);
i = i + one;
}
}
fn main() {
iterate(0i32, 10i32);
iterate(5u8, 7u8);
iterate(0f64, 10f64);
}

Implement a pairwise iterator

I have trouble writing code for a function that takes an iterator and returns an iterator that iterates in pairs (Option<T>, T) like so
a = [1,2,3]
assert pairwise(a) == `[(None, 1), (Some(1), 2), (Some(2), 3)]
fn pairwise<I, T>(&xs: &I) -> I
where
I: Iterator<Item = T>,
{
[None].iter().chain(xs.iter().map(Some)).zip(xs.iter())
}
fn main() {
let data: Vec<i32> = vec![1, 2, 3];
let newdata: Vec<Option<i32>, i32> = pairwise(&data).collect();
println!("{:?}", newdata);
}
error[E0599]: no method named `iter` found for type `I` in the current scope
--> src/main.rs:3:28
|
3 | [None].iter().chain(xs.iter().map(Some)).zip(xs.iter())
| ^^^^
|
Not sure why xs isn't iterable. I've stated it in the where clause haven't I?
fn pairwise<I, T>(&xs: &I) -> I
This doesn't make sense. See What is the correct way to return an Iterator (or any other trait)? and What is the difference between `e1` and `&e2` when used as the for-loop variable?.
I: Iterator<Item = T>,
There's no reason to specify that the Item is a T.
[None].iter()
It's better to use iter::once.
xs.iter()
There's no trait in the standard library that defines an iter method. Perhaps you meant IntoIterator?
let data: Vec<i32> = vec![1, 2, 3]
There's no reason to specify the type here; i32 is the default integral type.
Vec<Option<i32>, i32>
Vec<Option<i32>, i32>> // original version
This is not a valid type for Vec, and your original form doesn't even have balanced symbols.
After all that, you are faced with tough choices. Your example code passes in an iterator which has references to the slice but you've written your assertion such that you expect to get non-references back. You've also attempted to use an arbitrary iterator twice; there's no guarantee that such a thing is viable.
The most generic form I see is:
use std::iter;
fn pairwise<I>(right: I) -> impl Iterator<Item = (Option<I::Item>, I::Item)>
where
I: IntoIterator + Clone,
{
let left = iter::once(None).chain(right.clone().into_iter().map(Some));
left.zip(right)
}
fn main() {
let data = vec![1, 2, 3];
let newdata: Vec<_> = pairwise(&data).collect();
assert_eq!(newdata, [(None, &1), (Some(&1), &2), (Some(&2), &3)]);
let newdata: Vec<_> = pairwise(data.iter().copied()).collect();
assert_eq!(newdata, [(None, 1), (Some(1), 2), (Some(2), 3)]);
}
See also:
Iterating over a slice's values instead of references in Rust?
How to iterate over and filter an array?
How to create a non consuming iterator from a Vector
Why can I iterate over a slice twice, but not a vector?
The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want
What is the correct way to return an Iterator (or any other trait)?
I know OP asked for "outer pairwise" ([(None, 1), (Some(1), 2), (Some(2), 3)]), but here is how I adapted it for "inner pairwise" ([(1, 2), (2, 3)]):
fn inner_pairwise<I>(right: I) -> impl Iterator<Item = (I::Item, I::Item)>
where
I: IntoIterator + Clone,
{
let left = right.clone().into_iter().skip(1);
left.zip(right)
}
For anyone here for "inner pairwise", you're looking for Itertools::tuple_windows.

Golang OOP architecture, passing a slice into a constructor, creating a slice object

I just started with go language, everything looks cool, I coded everything I need but I have two problems, actually it is passing an slice into a Struct or so called object, and how to create a method that I can add for example another matrix, but this is minor problem I think.
Code:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
a := Matrix(nonsingularRandomMatrix())
fmt.Println(a)
}
type Matrix struct {
inputMatrix [][]int
}
func NewThing(inMatrix [][]int) *Matrix {
p := new(Matrix)
p.inputMatrix = inMatrix
return p
}
func nonsingularRandomMatrix() [][]int {
rand.Seed(time.Now().UTC().UnixNano())
var matrixDeterminant int = 0
nm := make([][]int, 4)
for i := 0; i < 4; i++ {
nm[i] = make([]int, 4)
for j := 0; j < 4; j++ {
nm[i][j] = rand.Intn(100)
}
}
matrixDeterminant =
nm[0][0]*nm[1][1]*nm[2][2]*nm[3][3] - nm[0][0]*nm[1][1]*nm[2][3]*nm[3][2] -
nm[0][0]*nm[1][2]*nm[2][1]*nm[3][3] + nm[0][0]*nm[1][2]*nm[2][3]*nm[3][1] +
nm[0][0]*nm[1][3]*nm[2][1]*nm[3][2] - nm[0][0]*nm[1][3]*nm[2][2]*nm[3][1] -
nm[0][1]*nm[1][0]*nm[2][2]*nm[3][3] + nm[0][1]*nm[1][0]*nm[2][3]*nm[3][2] +
nm[0][1]*nm[1][2]*nm[2][0]*nm[3][3] - nm[0][1]*nm[1][2]*nm[2][3]*nm[3][0] -
nm[0][1]*nm[1][3]*nm[2][0]*nm[3][2] + nm[0][1]*nm[1][3]*nm[2][2]*nm[3][0] +
nm[0][2]*nm[1][0]*nm[2][1]*nm[3][3] - nm[0][2]*nm[1][0]*nm[2][3]*nm[3][1] -
nm[0][2]*nm[1][1]*nm[2][0]*nm[3][3] + nm[0][2]*nm[1][1]*nm[2][3]*nm[3][0] +
nm[0][2]*nm[1][3]*nm[2][0]*nm[3][1] - nm[0][2]*nm[1][3]*nm[2][1]*nm[3][0] -
nm[0][3]*nm[1][0]*nm[2][1]*nm[3][2] + nm[0][3]*nm[1][0]*nm[2][2]*nm[3][1] +
nm[0][3]*nm[1][1]*nm[2][0]*nm[3][2] - nm[0][3]*nm[1][1]*nm[2][2]*nm[3][0] -
nm[0][3]*nm[1][2]*nm[2][0]*nm[3][1] + nm[0][3]*nm[1][2]*nm[2][1]*nm[3][0]
if matrixDeterminant == 0 {
nonsingularRandomMatrix()
}
return nm
}
Output from my console:
go run oop.go
command-line-arguments
.\oop.go:10: cannot convert nonsingularRandomMatrix() (type [][]int) to type Matrix
Any clue?
Greets!
What your compiler is saying is that [][]int and Matrix are two totally unrelated types. You can not convert from one to the other. Thats because Matrix is a struct which contains a [][]int, but Matrix is not an [][]int. To create a Matrix out of it you'd need to create a new Matrix and set the [][]int to the only member:
a := Matrix{nonsingularRandomMatrix()}
An easier way would be if Matrix were a [][]int.
type Matrix [][]int
This would just create a new name (Matrix) for [][]int, and in this case, a simple (explicit) conversion would work
Matrix(nonsingularRandomMatrix())

Project Euler #2 in Rust

I'm learning Rust, so I'm doing the Project Euler problems, as they are good exercises imho.
But I'm already stuck on the second problem. The idea is to find the sum of all the even numbers that are less than 4000000 in the Fibonacci sequence.
So I tried to do it a bit the functional way, and using a custom iterator :
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);
}
It looks good, and it gives the correct Fibonacci sequence (I verified with println!s).
The problem is that it doesn't give the correct sum : it outputs 1089154 whereas it should output 4613732. To me it seems that the fold misses the last number, but I can't see why !
I'm a total beginner with Rust, so any help would be greatly appreciated, thanks !
What you should be testing in your exit branch is the value of self.current; instead, you're testing the value of self.next. In other words, you're failing to output the last number in the sequence (as Matthieu suggested).
I verified that if the iterator is implemented correctly, it should produce the correct result with this (using grabbag_macros = "0.0.1" as a Cargo dependency):
#![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);
}
A few other random notes: I'd avoid uint for this, since it's platform-dependent. You don't need the u suffix unless you need to be specific about the type. You can use take_while or plain old take instead of hard-coding a limit into your iterator.