Sum of distinct values of vector of tuples in Rust - rust

I have a vector of tuples:
let steel_forces = [(1, 2, 1), (3, 4, 2), (5, 6, 3)];
Is there a way to obtain summation of single components in a single line? Result should be a tuple with these values:
(9, 12, 6)
I'm using following code but it doesn't look very rustic
let mut Ns = 0.0;
let mut Mxs = 0.0;
let mut Mys = 0.0;
for (force, mx, my) in steel_forces.iter() {
Ns = Ns + force;
Mxs = Mxs + mx;
Mys = Mys + my;
}

What about using fold()?
let (Ns, Mxs, Mys) = steel_forces
.iter()
.fold((0, 0, 0), |(Ns, Mxs, Mys), &(force, mx, my)| {
(Ns + force, Mxs + mx, Mys + my)
});

Related

Rust "attempt to multiply with overflow" when using .pow() function

I am trying to solve
Magnet particules in boxes
Here is my code:
fn doubles(maxk: i32, maxn: i32) -> f64 {
let mut result: f64 = 0.0;
let mut k = 1;
let mut n = 1;
while k <= maxk {
while n <= maxn {
result += 1.0 / (k as i64 * (((n + 1) as i32).pow((2 * k) as u32)) as i64) as f64;
n += 1;
}
n = 1;
k += 1;
}
result
}
Tests like gives me an error "attempt to multiply with overflow"
dotest(10, 1000, 0.6921486500921933);
dotest(10, 10000, 0.6930471674194457);
Trouble with pow() function.
How could I modify my code?
Use f64, because it has bigger range than integer.
fn doubles(maxk: i32, maxn: i32) -> f64 {
let mut result: f64 = 0.0;
let mut k = 1;
let mut n = 1;
while k <= maxk {
while n <= maxn {
-- result += 1.0 / (k as i64 * (((n + 1) as i32).pow((2 * k) as u32)) as i64) as f64;
+ result += 1.0 / (k as f64 * (((n + 1) as f64).powf((2 * k) as f64))) as f64;
+ result += 1. / k as f64 / (1. + n as f64).powf(2. * k as f64);
n += 1;
}
n = 1;
k += 1;
}
result
}

When is a Reborrow just a NOP?

I'm interested in this program:
fn main() {
let mut y = 13;
let mut x = &y;
x = &*x;
println!("{}", x);
}
In this case, the statement x = &*x; is translated into the following MIR:
_4 = _2; // scope 2 at src/main.rs:4:9: 4:12
_3 = _4; // scope 2 at src/main.rs:4:9: 4:12
_2 = move _3; // scope 2 at src/main.rs:4:5: 4:12
Basically, x = &*x; is translated as x = x; (i.e. a NOP). If I change the program like so:
fn main() {
let mut i = 13;
let mut j = 13;
let mut y = &i;
let mut x = &j;
x = &*y;
println!("{}", x);
}
Then, again, x = &*y; is essentially translated as x = y;.
Now my question (finally): Is a reborrow &*y when y is an immutable borrow always equivalent to just reading y?
Of course, I understand that if y was a mutable borrow this would be an entirely different thing.

How to group by non consecutive Vec elements in Rust?

I have a Vec<(A, B)> and I want to group by A but not just consecutive but all elements in the Vec. The closest thing I found is Itertools::group_by which only works on consecutive values. I understand that the consecutiveness is related to optimizing allocation but I just want a regular C# group by. Priority is to not have to use a new library just for this.
A is not hashable, only Ord. I want a resulting Vec<(A, Vec<(A, B))> or equivalent
Assuming that "comparable" means A: Ord, i.e. that there is a total ordering on A, you can fold an iterator over items of type (A, B) into a BTreeMap from A to Vec<B>:
use std::collections::BTreeMap;
fn group_pairs<A, B, I>(v: I) -> BTreeMap<A, Vec<B>>
where
A: Ord,
I: IntoIterator<Item = (A, B)>,
{
v.into_iter().fold(BTreeMap::new(), |mut acc, (a, b)| {
acc.entry(a).or_default().push(b);
acc
})
}
Some people prefer a for loop over a fold:
fn group_pairs<A, B, I>(v: I) -> BTreeMap<A, Vec<B>>
where
A: Ord,
I: IntoIterator<Item = (A, B)>,
{
let mut result = BTreeMap::<A, Vec<B>>::new();
for (a, b) in v {
result.entry(a).or_default().push(b);
}
result
}
Example:
let data = vec![(1, 2), (2, 3), (1, 1), (2, 4), (3, 5)];
let grouped = vec![(1, vec![2, 1]), (2, vec![3, 4]), (3, vec![5])];
assert_eq!(group_pairs(data).into_iter().collect::<Vec<_>>(), grouped);

How to average two points in nalgebra?

I have a triangle ABC, and I want to generate triangle DEF.
Triangle DEF is created using the centre of all edges of ABC. Nalgebra doesn't seem to allow me to do add points together, only vectors.
use nalgebra::Point2;
fn get_def(a: Point2<f32>, b: Point2<f32>, c: Point2<f32>) -> [Point2<f32>; 3] {
let d = (a + b) / 2.0; // error
let e = (b + c) / 2.0; // error
let f = (c + a) / 2.0; // error
[d, e, f]
}
.
Nalgebra has a function specifically for this, nalgebra::center.
use nalgebra::{Point2, center};
fn get_def(a: Point2<f32>, b: Point2<f32>, c: Point2<f32>) -> [Point2<f32>; 3] {
let d = center(&a, &b);
let e = center(&b, &c);
let f = center(&c, &a;
[d, e, f]
}

ReplicateM Equivalent in F#

Is there any equivalent function for ReplicateM (of Haskell) in F#?
Example :
replicateM 2 [1,2,3] =
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
You can find it in F#+ and it's defined for both List and Seq:
#r #"c:\packages\FSharpPlus-1.0.0\lib\net45\FSharpPlus.dll"
open FSharpPlus
List.replicateM 2 [1;2;3]
// val it : List<int list> =
// [[1; 1]; [1; 2]; [1; 3]; [2; 1]; [2; 2]; [2; 3]; [3; 1]; [3; 2]; [3; 3]]
Seq.replicateM 2 [1;2;3]
// val it : seq<int> list =
// [seq [1; 1]; seq [1; 2]; seq [1; 3]; seq [2; 1]; seq [2; 2]; seq [2; 3];
// seq [3; 1]; seq [3; 2]; seq [3; 3]]
If you are translating from Haskell there is a Compatibility.Haskell module in this project with that function and other Haskell bindings.
In fact the last argument can be a list or any other Applicative but if you don't want to use the library and you're happy with a version that works only with list you can define it like this:
let replicateM n x =
let k m m' = List.collect (fun x ->
List.collect(fun xs ->
[List.Cons(x,xs)]) m') m
List.foldBack k (List.replicate n x) [[]]
The function is not available in standard libraries, so if you do not want to rely on external libraries, you'll need to write it yourself. The easiest implementation looks like this:
let rec replicateM m l = seq {
if m = 1 then
// If we want just one replication, generate singleton lists
for v in l do yield [v]
else
// Otherwise, iterate over all lists with m-1 replicates
for s in replicateM (m - 1) l do
// .. and append elements from 'l' to the front
for v in l do yield v::s }

Resources