I am trying to execute the below program.
fn main() {
let a: u8 = 0b00000001;
let b: u8 = 0b10101010;
let c: u8 = 0b00001111;
let length = a.count_ones() + a.count_zeros();
for n in 0..length {
println!("{}", a[n]);
println!("{}", b[n]);
println!("{}", c[n]);
}
}
But I am getting error[E0608]: cannot index into a value of type `u8`
Rust doesn't provide indexes into individual bits of an integer. You need to use bitwise operators instead:
This will count from the right (least to most significant bits):
fn main() {
let a: u8 = 0b00000001;
let b: u8 = 0b10101010;
let c: u8 = 0b00001111;
let length = a.count_ones() + a.count_zeros();
for n in 0..length {
println!("{}", a >> n & 1);
println!("{}", b >> n & 1);
println!("{}", c >> n & 1);
}
}
The reason why this isn't provided is that the Index trait is defined like this:
pub trait Index<Idx>
where
Idx: ?Sized,
{
type Output: ?Sized;
fn index(&self, index: Idx) -> &Self::Output;
}
index() returns a reference, but references are always to a byte address; you can't make a reference to a single bit.
Depending on your actual use case, you may also be interested in one of these crates:
bitfield
bitvec.
Related
expected type parameter T, found type parameter A error display. I have written lifetime implementation code also but it stills doesn't solve the problem. What's wrong I am doing?
fn main() {
let x = 3;
let y = 5.0;
let max_value = max(x, y);
println!("The maximum value is {}", max_value);
}
fn max<T: PartialOrd, A: PartialOrd>(x: T, y: A) -> T {
if x > y {
x
} else {
y
}
}
// fn main() {
// let x = 3;
// let y = 5.0;
// let max_value = max(&x, &y);
// println!("The maximum value is {}", max_value);
// }
// fn max<'a, T: PartialOrd + Copy, A: PartialOrd + Copy>(x: &'a T, y: &'a A) -> &'a T {
// if x > y {
// x
// } else {
// y
// }
// }
T and A do not have to be the same type, so you have two problems.
The first is that you constrain T and A to be PartialOrd, which is the same thing as PartialOrd<Self>. So your actual constraints are T: PartialOrd<T>, A: PartialOrd<A>. This means you can compare the order of T's to other T's and A's to other A's, but x > y compares a T to an A.
Instead, you need to constrain T: PartialOrd<A>. (This also fails, but because of the invocation in main() -- more on that later.)
Second, the function is declared to return T but the else block returns y, which is not a T. Rust is statically typed, so it expects the types to exactly match.
This could be fixed by requiring that A can be converted to T (that is, A: Into<T>) and then you can return y.into() from the else block.
So at this point, we have:
fn main() {
let x = 3;
let y = 5.0;
let max_value = max(x, y);
println!("The maximum value is {}", max_value);
}
fn max<T: PartialOrd<A>, A: Into<T>>(x: T, y: A) -> T {
if x > y {
x
} else {
y.into()
}
}
But now you are left with more problems:
There are no types T and A satisfying T: PartialOrd<A> where T is an integer and A is a float, therefore you cannot call this function with 3 and 5.0 as you do in main().
Likewise, there's no implementation of Into<T> on A for an integer type T and a float type A.
x > y will move x and y, and then you cannot return them later. This is trivially fixed by constraining both T and A to be Copy.
The second issue could be fixed by having an enum that means "either T or A" and returning that instead. The either crate has such a type called Either, which we can use here as Either<T, A>:
use either::Either;
fn main() {
let x = 3;
let y = 5.0;
let max_value = max(x, y);
println!("The maximum value is {}", max_value);
}
fn max<T: PartialOrd<A> + Copy, A: Copy>(x: T, y: A) -> Either<T, A> {
if x > y {
Either::Left(x)
} else {
Either::Right(y)
}
}
(The println! works because Either<T, A> implements Display when both T and A do.)
You are still left with the problem where there's no built-in ordering implementation between integers and floats.
A "hail mary" solution could be to require that T and A can both be converted to f64 and then convert x and y to f64 before comparing them:
use either::Either;
fn main() {
let x = 3;
let y = 5.0;
let max_value = max(x, y);
println!("The maximum value is {}", max_value);
}
fn max<T: Copy + Into<f64>, A: Copy + Into<f64>>(x: T, y: A) -> Either<T, A> {
if x.into() > y.into() {
Either::Left(x)
} else {
Either::Right(y)
}
}
This is the first bit of code we have that actually compiles, and this might be good enough for your purposes. There are still some issues that remain, however:
i64 and u64 cannot be losslessy converted to f64, therefore they do not implement Into<f64>, and so if you change let x = 3; to let x = 3u64; (or 3i64) compilation will again fail.
f64 does not implement Ord because it's possible for there to be two f64 values x and y that are not equal but neither is greater than the other -- if either value is NaN, for example. This won't cause your program to crash, but it may produce an unexpected or incorrect result.
I suspect that this is a learning exercise, so hopefully this answer helps you understand what is wrong with the original code. I would not recommend a function like this in a real-world program; instead, it would be far better to convert both arguments to be of the same Ord-implementing type ahead of time and then you can use the built-in std::cmp::max function (or Ord::max).
I'm trying to implement the Add trait for a Vector type that I defined.
use std::ops::Add;
use num::traits::Float;
#[derive(PartialEq, Debug, Clone)]
pub struct Vector<T>(Vec<T>);
impl<T: Float> Add for Vector<T> {
type Output = Vector<T>;
fn add(self, w: Self) -> Self::Output {
let dim = self.0.len();
let mut t = vec![T::zero(); dim];
for i in 0..dim {
t[i] = self.0[i] + w.0[i];
}
Vector(t)
}
}
Adding vector of float values works fine.
let v = Vector(vec![1., 2., 3.]);
let w = Vector(vec![1., 2., 6.]);
let result = v + w;
println!("{:?}", result);
However, when I try to add a vector of complex numbers, it doesn't work. Also, the error is a little vague.
let x = Complex::new(1., 3.);
let y = Complex::new(9., -1.);
let z = Complex::new(0.32, 81.);
let v: Vector<Complex<f32>> = Vector(vec![x, y, z]);
// cannot add `vector::Vector<num::Complex<f32>>` to `vector::Vector<num::Complex<f32>>`rustc(E0369)
let result = v + v;
Am I missing something about the Add implementation? How would I enable the add operation for vector of complex numbers?
Link to code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c5d3b0314968fa261287a19be4ad9536
So, I think the reason my code doesn't work is because num::traits::Float is not the right type to use. The reason being is that it has too many methods.
To make it work, I defined a trait Num, which is "narrower" compared to Float.
pub trait Num: Add + Zero + Clone + Copy {}
impl<T> Num for T where T: Add + Zero + Clone + Copy {}
Then, use that trait instead of Float.
impl<T: Num> Add for Vector<T> {
type Output = Vector<T>;
fn add(self, w: Self) -> Self::Output {
let dim = self.0.len();
let mut t = vec![T::zero(); dim];
for i in 0..dim {
t[i] = self.0[i] + w.0[i];
}
Vector(t)
}
}
With the above change, adding vector of floats and complex numbers now works.
// Adding vector of floats works.
let v = Vector(vec![1., 2., 3.]);
let w = Vector(vec![1., 2., 6.]);
let result = v + w;
println!("{:?}", result);
let x = Complex::new(1., 3.);
let y = Complex::new(9., -1.);
let z = Complex::new(0.32, 81.);
let v: Vector<Complex<f32>> = Vector(vec![x, y, z]);
let w: Vector<Complex<f32>> = Vector(vec![x, y, z]);
// Adding vector of complex numbers also works!
let result = v + w;
println!("{:?}", result);
On the side note, I'm also implementing other traits (Sub, Div, Mul, etc.) and having a different issue, but that's another thing.
Link to playground
Thanks #RobinZigmond and #Dogbert!
What am I doing wrong with the variable i below? Why does the compiler say I cannot index a Vec with a u32 and how do I fix it?
fn main() {
let a: Vec<u32> = vec![1, 2, 3, 4];
let number: u32 = 4;
let mut count = 0;
for i in 0..number {
if a[i] % 2 != 0 {
count += 1;
} else {
continue;
}
}
println!("{}", count);
}
Error:
error[E0277]: the type `[u32]` cannot be indexed by `u32`
--> src/main.rs:7:12
|
7 | if a[i] % 2 != 0 {
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `SliceIndex<[u32]>` is not implemented for `u32`
= note: required because of the requirements on the impl of `Index<u32>` for `Vec<u32>`
Playground
Indexing is made possible by Index and IndexMut traits.
You are using a Vec and it implements Index and IndexMut traits.
Although, it imposes a trait bound that type used to index should implement SliceIndex<[T]>:
impl<T, I> Index<I> for Vec<T>
where
I: SliceIndex<[T]>
SliceIndex is implemented for usize because of which it is possible to use type usize as index.
It is not implmented for u32 because of which you can't use u32 as index.
i has a type u32 because it is received from the range 0..number where number has type u32.
A simple fix would be to cast i to usize:
if a[i as usize] % 2 != 0
This cast can be safely done as long as you are on at least a 32 bit machine.
As per the definition of usize:
The size of this primitive is how many bytes it takes to reference any location in memory
Moreover, your code doesn't require you to use u32. Instead you should use usize from the start.
Quick remark: instead of changing the type of number to usize forever or constantly casting i to usize one may use the following construction which casts number to usize for the purposes of the for loop only:
fn main() {
let a: Vec<u32> = vec![1, 2, 3, 4];
let number: u32 = 4;
let mut count = 0;
for i in 0..number as usize {
if a[i] % 2 != 0 {
count += 1;
} else {
continue;
}
}
println!("{}", count);
}
Change the type of number to usize, so the range for i in 0..number will also iterate over usizes. Indexing is typically done with usize
I'd like to have a function that takes an iterable and returns its smallest and largest elements. This is part of an exercise in learning Rust, but I'm struggling in being able to handle reference types and value types at the same time.
This is what I have:
fn min_max<'a, I, T>(mut iter: I) -> Option<(&'a T, &'a T)>
where
I: Iterator<Item = &'a T>,
T: PartialOrd,
{
let mut min = match iter.next() {
Some(x) => x,
// The collection is empty
None => return None,
};
let mut max = min;
for el in iter {
if el < min {
min = el;
}
if el >= max {
max = el;
}
}
Some((min, max))
}
Then, I give this an iterator over some integers.
let nums: [u32; 6] = [4, 3, 9, 10, 4, 3];
if let Some((min, max)) = min_max(nums.iter()) {
println!("{} {}", min, max);
}
This works, and prints 3 10. But then I want to do some operations on the numbers before I compute the minimum and maximum, like a map and/or a filter.
let doubled = nums.iter().map(|x| 2 * x);
if let Some((min, max)) = min_max(doubled) {
println!("{} {}", min, max);
}
This gives a compiler error:
error[E0271]: type mismatch resolving `<[closure#src/main.rs:31:35: 31:44] as std::ops::FnOnce<(&u32,)>>::Output == &_`
--> src/main.rs:32:31
|
32 | if let Some((min, max)) = min_max(doubled) {
| ^^^^^^^ expected u32, found reference
|
= note: expected type `u32`
found type `&_`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<std::slice::Iter<'_, u32>, [closure#src/main.rs:31:35: 31:44]>`
= note: required by `min_max`
This confused me, because if nums.iter() works as an argument, why shouldn't nums.iter().map(...)?
I understand the error message in principle: my array is of u32, not &u32, whereas my function requires Iterator::Item to be of type &'a T. But then I don't get why it errors only on the second sample (using .iter().map()) and not on the first (just .iter()).
I've made a playground with this example and a commented out example where I construct an iterable of integers from a string. This fails in exactly the same way as the second example above (and is closer to my actual use case).
let s = "4 3 9 10 4 3";
let parsed = s.split(" ").map(|x| x.parse::<u32>().unwrap());
if let Some((min, max)) = min_max(parsed) {
println!("{} {}", min, max);
}
I'd like to have a function that takes an iterable and returns its smallest and largest elements.
Use Itertools::minmax.
handle reference types and value types at the same time.
You don't need to — references to numbers can also be compared:
fn foo(a: &i32, b: &i32) -> bool {
a < b
}
In your case, remember that a value and a reference to that value are different types. That means you can accept an iterator of any type so long as the yielded values are comparable, and this includes both references and values, as requested:
fn min_max<I>(mut iter: I) -> Option<(I::Item, I::Item)>
where
I: Iterator,
I::Item: Clone + PartialOrd,
{
let mut min = match iter.next() {
Some(x) => x,
// The collection is empty
None => return None,
};
let mut max = min.clone();
for el in iter {
if el < min {
min = el;
} else if el >= max {
max = el;
}
}
Some((min, max))
}
I chose to add the Clone bound although to be more true to your original I could have used the Copy bound. Itertools returns an enum to avoid placing any restrictions on being able to duplicate the value.
This works with all three of your examples:
fn main() {
let nums: [u32; 6] = [4, 3, 9, 10, 4, 3];
if let Some((min, max)) = min_max(nums.iter()) {
println!("{} {}", min, max);
}
let doubled = nums.iter().map(|x| 2 * x);
if let Some((min, max)) = min_max(doubled) {
println!("{} {}", min, max);
}
let s = "4 3 9 10 4 3";
let parsed = s.split(" ").map(|x| x.parse::<u32>().unwrap());
if let Some((min, max)) = min_max(parsed) {
println!("{} {}", min, max);
}
}
3 10
6 20
3 10
my array is of u32, not &u32, whereas my function requires Iterator::Item to be of type &'a T. But then I don't get why it errors only on the second sample (using .iter().map()) and not on the first (just .iter()).
Because iterating over an array returns references. By using map, you are changing the type of the iterator's item from &i32 to i32. You could have also chosen to adapt the first call to return values.
You have a type mismatch problem because the .iter() call produces a "slice" iterator (Iterator with Item = &T), but the .map(|x| 2 * x) is a iterator adaptor, the call of which produces a new "value" iterator (Iterator with Item = T). These values must necessarily be stored in memory before we can get them "slice", because we can only get a reference to the value that is already stored somewhere in the memory. Therefore, we need to collect the result of the map function before we can get an iterator with references to the values it returns:
let doubled: Vec<_> = nums.iter().map(|x| 2 * x).collect();
if let Some((min, max)) = min_max(doubled.iter()) {
println!("{} {}", min, max);
}
For more details, see chapter 13.2 Iterators of The Rust Programming Language book.
I am trying to find the sum of the digits of a given number. For example, 134 will give 8.
My plan is to convert the number into a string using .to_string() and then use .chars() to iterate over the digits as characters. Then I want to convert every char in the iteration into an integer and add it to a variable. I want to get the final value of this variable.
I tried using the code below to convert a char into an integer:
fn main() {
let x = "123";
for y in x.chars() {
let z = y.parse::<i32>().unwrap();
println!("{}", z + 1);
}
}
(Playground)
But it results in this error:
error[E0599]: no method named `parse` found for type `char` in the current scope
--> src/main.rs:4:19
|
4 | let z = y.parse::<i32>().unwrap();
| ^^^^^
This code does exactly what I want to do, but first I have to convert each char into a string and then into an integer to then increment sum by z.
fn main() {
let mut sum = 0;
let x = 123;
let x = x.to_string();
for y in x.chars() {
// converting `y` to string and then to integer
let z = (y.to_string()).parse::<i32>().unwrap();
// incrementing `sum` by `z`
sum += z;
}
println!("{}", sum);
}
(Playground)
The method you need is char::to_digit. It converts char to a number it represents in the given radix.
You can also use Iterator::sum to calculate sum of a sequence conveniently:
fn main() {
const RADIX: u32 = 10;
let x = "134";
println!("{}", x.chars().map(|c| c.to_digit(RADIX).unwrap()).sum::<u32>());
}
my_char as u32 - '0' as u32
Now, there's a lot more to unpack about this answer.
It works because the ASCII (and thus UTF-8) encodings have the Arabic numerals 0-9 ordered in ascending order. You can get the scalar values and subtract them.
However, what should it do for values outside this range? What happens if you provide 'p'? It returns 64. What about '.'? This will panic. And '♥' will return 9781.
Strings are not just bags of bytes. They are UTF-8 encoded and you cannot just ignore that fact. Every char can hold any Unicode scalar value.
That's why strings are the wrong abstraction for the problem.
From an efficiency perspective, allocating a string seems inefficient. Rosetta Code has an example of using an iterator which only does numeric operations:
struct DigitIter(usize, usize);
impl Iterator for DigitIter {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.0 == 0 {
None
} else {
let ret = self.0 % self.1;
self.0 /= self.1;
Some(ret)
}
}
}
fn main() {
println!("{}", DigitIter(1234, 10).sum::<usize>());
}
If c is your character you can just write:
c as i32 - 0x30;
Test with:
let c:char = '2';
let n:i32 = c as i32 - 0x30;
println!("{}", n);
output:
2
NB: 0x30 is '0' in ASCII table, easy enough to remember!
Another way is to iterate over the characters of your string and convert and add them using fold.
fn sum_of_string(s: &str) -> u32 {
s.chars().fold(0, |acc, c| c.to_digit(10).unwrap_or(0) + acc)
}
fn main() {
let x = "123";
println!("{}", sum_of_string(x));
}