I have two Vecs that can be of different lengths, for example:
let xs = vec![1, 2, 3, 4, 5];
let ys = vec![11, 12, 13];
I want to iterate over them in pairs, printing:
x=1, y=11
x=2, y=12
x=3, y=13
x=4; no matching Y
x=5; no matching Y
I can use Iterator::zip to get the pairs with matching elements in both xs and ys:
for (x, y) in xs.iter().zip(ys.iter()) {
println!("x={}, y={}", x, y);
}
but for the "no matching" bits I need complex code that checks the length and takes a slice of the rest.
I wanted a solution that's fully iterator-based, so I tried:
let mut it_xs = xs.iter();
let mut it_ys = ys.iter();
while let (Some(x), Some(y)) = (it_xs.next(), it_ys.next()) {
println!("x={}, y={}", x, y);
}
while let Some(x) = it_xs.next() {
println!("x={}, no matching Y", x);
}
while let Some(y) = it_ys.next() {
println!("y={}, no matching X", y);
}
which does not work correctly, as the first loop skips the first element that doesn't have a match in the other list (x=4).
Is it possible to solve with the help of an iterator without slicing the rest of the larger Vec?
The implementation without external crates:
let mut it_xs = xs.iter();
let mut it_ys = ys.iter();
loop {
match (it_xs.next(), it_ys.next()) {
(Some(x), Some(y)) => println!("x={}, y={}", x, y),
(Some(x), None) => println!("x={}, no matching Y", x),
(None, Some(y)) => println!("y={}, no matching X", y),
(None, None) => break,
}
}
itertools has a method zip_longest that does just that:
use itertools::Itertools;
use itertools::EitherOrBoth::{Both, Left, Right};
for it in xs.iter().zip_longest(ys.iter()) {
match it {
Both(x, y) => println!("x={}, y={}", x, y),
Left(x) => println!("x={}, no matching Y", x),
Right(y) => println!("y={}, no matching X", y),
}
}
Related
When using the crossterm library with this code:
fn draw_box(stdout: &mut Stdout, x: u16, y: u16) -> Result<()> {
let size = 5;
let outline = (x..x + size)
.map(|i| (i, y))
.chain((y + 1..y + size - 1).map(|i| (x + size - 1, i)))
.chain((y + 1..y + size - 1).map(|i| (x, i)))
.chain((x..x + size).map(|i| (i, y + size - 1)))
.collect::<Vec<_>>();
for (a, b) in outline {
stdout
.queue(cursor::MoveTo(a, b))?
.queue(style::Print("x"))?;
}
stdout.flush()?;
stdout
.queue(cursor::MoveTo(x + 2, y + 2))?
.queue(style::Print("o"))?;
stdout.flush()?;
Ok(())
}
The last draw command clears the rest of the output to give this:
xxxxx
x x
x o%
If I remove that command I get the full box:
xxxxx
x x
x x
x x
xxxxx%
How can I draw the box and then draw the circle inside of the box?
I made a program to calculate the prime numbers of 1 to n in python and rust. Surprisingly python wins with the difference of 0.008 and 0.590. Rust won all other questions with the difference of 0.001 and 0.008.
The only difference here, is that I need to calculate a large number. Python is fine with large numbers, but rust requires a crate knows as num. Without using the num crate, rust wins.
Is there some how that I can avoid using num, without changing my solution?
Here are the rust and python solutions.
from functools import reduce
fact = lambda x: reduce(lambda y, z: y*z, range(1,x+1))
is_prime = lambda x: False if x <= 1 else fact(x-1) % x == x - 1
primes = lambda x, y: tuple(filter(is_prime, range(x,y+1)))
import sys
print(primes(1, int(sys.argv[1])))
macro_rules! number {
(+ $($args:tt),*) => {
num::BigInt::new(num::bigint::Sign::Plus, vec![$($args),*])
};
(- $($args:tt),*) => {
num::BigInt::new(num::bigint::Sign::Minus, vec![$($args),*])
};
}
fn fact(x: u32) -> num::BigInt {
(1..x+1).map(|x| number!(+ x)).reduce(|x, y| x * y).unwrap()
}
fn is_prime(x: u32) -> bool {
x > 1 && fact(x - 1) % x == number!(+ (x - 1))
}
fn main() {
let n = &(std::env::args().collect::<Vec<String>>())[1];
println!("{:#?}", (1..=n.parse::<u32>().unwrap()).filter(|x| is_prime(*x)).collect::<Vec<u32>>());
}
I'm trying to vectorize solving the following
\argmax_{x_i\in Z^+, \sum x_i = S} f(x)
Is there a better way of using vectorization than the following? I only get a 2.1x speedup for N=1 vs N=4 and a 2.4x speedup for N=1 vs N=8 on Skylake.
const N: usize = 4;
type F = Simd<f32, N>;
// Hardcoded for i in 0..3 for ease of reading, but can be easily generated with a macro
pub fn iterate(s: usize) -> [f32; 4] {
let mut max = F::splat(f32::NEG_INFINITY);
let mut max0 = F::splat(f32::NEG_INFINITY);
let mut max1 = F::splat(f32::NEG_INFINITY);
let mut max2 = F::splat(f32::NEG_INFINITY);
let mut max3 = F::splat(f32::NEG_INFINITY);
let remaining = s;
let mut idx0 = 0;
while idx0 <= remaining {
let x0 = F::splat(idx0 as f32);
let remaining = remaining - idx0;
let mut idx1 = 0;
while idx1 <= remaining {
let x1 = F::splat(idx1 as f32);
let remaining = remaining - idx1;
let mut i = 0;
while i <= remaining {
let offset = get_misaligned::<N>(remaining - i);
let x2 = offset + F::splat(i as f32);
let x3 = F::splat(remaining as f32) - x2;
{
let fx = f([x0, x1, x2, x3]);
max = max.simd_gt(fx).select(max, fx);
max0 = max.simd_gt(fx).select(max0, x0);
max1 = max.simd_gt(fx).select(max1, x1);
max2 = max.simd_gt(fx).select(max2, x2);
max3 = max.simd_gt(fx).select(max3, x3);
}
i += N;
}
idx1 += 1;
}
idx0 += 1;
}
let (i, _) = max
.to_array()
.iter()
.enumerate()
.reduce(|(i, x), (j, y)| if x > y { (i, x) } else { (j, y) })
.unwrap();
[max0[i], max1[i], max2[i], max3[i]]
}
Godbolt
The overall question is how to do nested destructuring assignment with type annotations. I'm multiplying two f32 values, but I'm unsure what will happen if the multiple overflows. Therefore, I'd like to assign them as f64 values in order to prevent the overflow.
This example is lightly modified from Rust By Example's chapter on structures:
struct Point {
x: f32,
y: f32,
}
struct Rectangle {
p1: Point,
p2: Point,
}
fn area(rect: Rectangle) -> f64 {
// Here's where I'd like have type annotations
// while doing destructuring assignment:
let Rectangle {
p1: Point { x: x1, y: y1 },
p2: Point { x: x2, y: y2 },
} = rect;
((x2 - x1) * (y2 - y1)).abs() as f64
}
Casts cannot be performed during type destructuring. This is because you cannot annotate the type that will be contained in the type you're destructuring, therefore it doesn't depend on you, and instead on the type that is being destructured. For example:
struct Point {
x: f32,
y: f32,
}
let myOtherPoint = Point { x: 0, y: 0 };
let Point {x, y} = myOtherPoint;
The type of x and y are defined by the type Point. This can, on the other hand be changed in the case of tuples and arrays:
fn main() {
let [x, y, z]: [f32; 3] = [1.2, 2.3, 3.4];
let (x, y, z): (usize, f32, String) = (1, 2.3, "3.4".into());
}
This is mostly because of type annotations needed for tuples when writing function signatures:
fn foo((a, b, c): (usize, f32, String)) {}
But this is only because tuples are not named types, per se, so there is a need to name the tuple, by annotating the type. On the other hand, structs and enums are named and therefore destructurable.
The solution to your specific issue described in the body, and not the title:
Use a separate variable with shadowing to preserve usability. Note too, that the floating point types (f32 and f64) cannot be overflowed (They have an infinity), only integers ([u, i][size, 8, 16, 32, 64, 128]).
fn area(x: Rectangle) -> f64 {
// Here's where I'd like have type annotations
// while doing destructuring assignment:
let Rectangle {
p1: Point { x: x1, y: y1 },
p2: Point { x: x2, y: y2 },
} = rect;
let (x1, x2, y1, y2) = (x1 as f64, x2 as f64,
y1 as f64, y2 as f64);
((x2 - x1) * (y2 - y1)).abs()
}
When a closure's resolveStrategy is set to DELEGATE_ONLY or DELEGATE_FIRST, resolution is different in nested closures between methods and properties of the delegate. For example, in the following, x resolves to f's delegate (what I expect), but keySet() resolves to g's delegate.
def g = {->
def f = {
{-> [x, keySet()]}()
}
f.resolveStrategy = Closure.DELEGATE_ONLY
f.delegate = [x: 1, f: 0]
f()
}
g.delegate = [x: 0, g: 0]
g()
Result: [1, ['x', 'g']]
Whereas without the nested closure
def g = {->
def f = {
[x, keySet()]
}
f.resolveStrategy = Closure.DELEGATE_ONLY
f.delegate = [x: 1, f: 0]
f()
}
g.delegate = [x: 0, g: 0]
g()
Result: [1, ['x', 'f']]
Is this behavior expected and documented somewhere? Is it a bug?
I believe it is a bug. If you change the map for a Expando it behaviors differently:
f = {
g = {
{ -> keySet() }()
}
g.delegate = new Expando(a: 1000, b: 900, c: 800, keySet: { 'g keyset' })
g.resolveStrategy = Closure.DELEGATE_ONLY
g()
}
f.delegate = new Expando(a: 90, x: 9, y: 1, keySet: { 'f keyset' })
assert f() == 'g keyset'
f = {
g = {
{ -> keySet() }()
}
g.delegate = [a: 1000, b: 900, c: 800]
g.resolveStrategy = Closure.DELEGATE_ONLY
g()
}
f.delegate = [a: 90, x: 9, y: 1]
assert f().toList() == ['a', 'b', 'c'] // fails :-(
Maybe filling a JIRA?
I discovered a workaround if you never want to fall through to the owner (ie, DELEGATE_ONLY): you can set both the delegate and the owner to the same value:
def g = {->
def f = {
{-> [x, keySet()]}()
}
def d = [x: 1, f: 0]
f = f.rehydrate(d, d, f.thisObject)
f()
}
g.delegate = [x: 0, g: 0]
g()
Result: [1, ["x", "f"]]
Note that f.owner = d does not work: while there is no error, it seems to be a no-op. You must use rehydrate.