rust: integer multiplication in match [duplicate] - rust

This question already has answers here:
Why is this match pattern unreachable when using non-literal patterns?
(1 answer)
How do I match based on a dynamic variable?
(4 answers)
How can I store a pattern in a variable in Rust?
(1 answer)
Closed 22 days ago.
Hi I am learnig rust and doing the excercise rustlings/itertors3.rs
My first implementation of fn divide not behaves as I expected. Could Someone explain me why?
My first attempt was:
// Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
// Otherwise, return a suitable error.
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
let res = a.checked_div(b).ok_or(DivisionError::DivideByZero)?;
match res*b {
a => Ok(res),
other => Err(DivisionError::not_evenly_dividable(a, b))
}
}
But this gives a false positive. This works:
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
let res = a.checked_div(b).ok_or(DivisionError::DivideByZero)?;
match a%b {
0 => Ok(res),
other => Err(DivisionError::not_evenly_dividable(a, b))
}
}
Why?

Related

How to avoid try_into().unwrap() conversions with loop indices? [duplicate]

This question already has an answer here:
How do I convert between numeric types safely and idiomatically?
(1 answer)
Closed 4 months ago.
Is there a better way to use i and j for-in variables that avoids the use of std::convert::TryInto and return vec![i.try_into().unwrap(),j.try_into().unwrap()]; for dealing with the usize and i32 conversion problem between what is expected as a result and the actual value type of these variables?
The use of the module and the try_into() and unwrap() functions was because of the compiler error suggestion. But I want to know if there is another way to cast or convert numeric values.
use std::convert::TryInto;
impl Solution {
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut current = 0;
for i in 0..nums.len() - 1 {
for j in 1..nums.len(){
if j != i {
current = nums[i] + nums[j];
if current == target {
return vec![i.try_into().unwrap(),j.try_into().unwrap()];
}
}
}
}
vec![]
}
}
There is the i as i32 syntax, but that can cause silent overflow if nums.len() > i32::MAX
where i32::MAX = 2_147_483_647 https://doc.rust-lang.org/std/i32/constant.MAX.html
impl Solution {
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
nums.iter()
.enumerate()
.find_map(|(i, &x)| {
nums.iter()
.enumerate()
.find(|(j, &y)| *j != i && (x + y) == target)
.map(|(j, _)| vec![i as i32, j as i32])
})
.unwrap_or_default()
}
}

How can I get enum value by its name? [duplicate]

This question already has answers here:
Can I convert a string to enum without macros in Rust?
(3 answers)
Closed 12 months ago.
I know how to do it in Java.
It seems I need to implement TryFrom or something like that.
enum ROMAN {
I = 1,
V = 5,
X = 10,
L = 50,
C = 100,
D = 500,
M = 1000
}
I want to get value using by enums name.
println!("{:?}", ROMAN::valueOf("M")); // It should be `1000`
Either implement FromStr or TryFrom manually, or use something like enum_derive which provides these features.
Or just add a bespoke value_of method on your enum without bothering with traits.
Or do all of it, though that seems a bit much
impl Roman {
pub fn value_of(s: &str) -> Option<Self> {
Some(match s {
"I" => Self::I,
"V" => Self::V,
"X" => Self::X,
"L" => Self::L,
"C" => Self::C,
"D" => Self::D,
"M" => Self::M,
_ => return None,
})
}
}
impl FromStr for Roman {
type Err = (); // should probably provide something more useful
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::value_of(s).ok_or(())
}
}
impl TryFrom<&str> for Roman {
type Error = ();
fn try_from(s: &str) -> Result<Self, Self::Error> {
Self::value_of(s).ok_or(())
}
}
println!("{:?}", ROMAN::valueOf("M")); // It should be `1000`
It's never going to be 1000 because that's not how Rust works. You'd need to handle the error then convert the success value to its discriminant.

Array of vectors of different types in Rust [duplicate]

This question already has answers here:
How do you access enum values in Rust?
(6 answers)
Closed 1 year ago.
I would like to make an array of vectors of different types, and I realize that in Rust this isn't as straightforward as:
let array_of_vecs = [
vec![],
vec![],
vec![]
]
Instead, I took a look through the Rust Book and found this https://doc.rust-lang.org/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types.
fn main() {
enum DataType {
Int(Vec<i32>),
Float(Vec<f64>),
Text(Vec<String>)
}
let array_of_vecs = [
DataType::Int(vec![1, 3]),
DataType::Text(vec![]),
DataType::Float(vec![])
];
println!("{:?}",array_of_vecs[0][1]);
}
However, when I run this, I get the following error:
error[E0608]: cannot index into a value of type `DataType`
--> src/main.rs:15:19
|
15 | println!("{:?}",array_of_vecs[0][1]);
| ^^^^^^^^^^^^^^^^^^^
I understand that at array_of_vecs[0][1] is a DataType, but isn't it also a Vec<i32>? How do I access the Vec<i32>?
You have to destructure the vectors. While every variant of your DataType is a tuple variant with a single vector field in this case, it's possible to have whatever types you want, so the Rust compiler can't guarantee that array_of_vecs[0] is a vector. This means that you have to account for every case:
match array_of_vecs[0] {
DataType::Int(v) => println!("{:?}", v[1]),
DataType::Float(v) => println!("{:?}", v[1]),
DataType::Text(v) => println!("{:?}", v[1]),
}
You probably need to add an index trait for your enum, so that Rust knows what you're trying to do when you are accessing the enum value with [1]:
use std::ops::Index;
enum Nucleotide {
A,
C,
G,
T,
}
struct NucleotideCount {
a: usize,
c: usize,
g: usize,
t: usize,
}
impl Index<Nucleotide> for NucleotideCount {
type Output = usize;
fn index(&self, nucleotide: Nucleotide) -> &Self::Output {
match nucleotide {
Nucleotide::A => &self.a,
Nucleotide::C => &self.c,
Nucleotide::G => &self.g,
Nucleotide::T => &self.t,
}
}
}
let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12};
assert_eq!(nucleotide_count[Nucleotide::A], 14);
assert_eq!(nucleotide_count[Nucleotide::C], 9);
assert_eq!(nucleotide_count[Nucleotide::G], 10);
assert_eq!(nucleotide_count[Nucleotide::T], 12);
https://doc.rust-lang.org/std/ops/trait.Index.html

How to convert a 4 element &[u8] into i32? [duplicate]

This question already has answers here:
How can I convert a buffer of a slice of bytes (&[u8]) to an integer?
(4 answers)
Closed 1 year ago.
I have an i32 that i pass to my keyvalue database.
let a = 1234i32;
db.put(&a.to_be_bytes());
But i get it back as &[u8], how to convert it back to i32?
update: this example pretty much does what i want.
use std::convert::TryInto;
fn read_be_i32(input: &[u8]) -> i32 {
i32::from_be_bytes(input.try_into().unwrap())
}
Use i32::from_be_bytes and from this answer, TryFrom:
use std::convert::TryFrom;
fn main() {
let a = 1234i32.to_be_bytes();
let a_ref: &[u8] = &a;
let b = i32::from_be_bytes(<[u8; 4]>::try_from(a_ref).expect("Ups, I did it again..."));
println!("{}", b);
}
Playground

Returning value of enum [duplicate]

This question already has answers here:
How do you access enum values in Rust?
(6 answers)
How do I get an enum as a string?
(2 answers)
Closed 4 years ago.
I'm implementing FizzBuzz in Rust. I went from the simplest version to using an enum and I can't resolve it. I've read enums are very potent so I tried to use them to their fullest.
Here is my implementation:
use std::fmt;
fn main() {
for i in 1..100 {
println!("{}", fizzbuzz(i))
}
}
fn fizzbuzz(value: i32) -> Answer {
use crate::Answer::*;
return match (value % 3, value % 5) {
(0, 0) => FizzBuzz,
(0, _) => Fizz,
(_, 0) => Buzz,
(_, _) => Nothing(value),
};
}
enum Answer {
FizzBuzz,
Fizz,
Buzz,
Nothing(i32),
}
impl fmt::Display for Answer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::Answer::*;
match self {
FizzBuzz => write!(f, "FizzBuzz"),
Fizz => write!(f, "Fizz"),
Buzz => write!(f, "Buzz"),
Nothing() => write!(f, "number passed to NoBuzz"),
}
}
}
I have 2 problems:
how to use the name of actual enum in match self block?
In Java, I could use just FizzBuzz.name() and it would print
"FizzBuzz" - is it possible in Rust?
is it possible to print that value I passed to Nothing in fizzbuzz
function?
You can derive a printable representation for debugging purposes with #[derive(Debug)]. This would let you print it out using println!("{:?}", self)
Example:
#[derive(Debug)]
enum Answer {
FizzBuzz,
Fizz,
Buzz,
Nothing(i32),
}
match self {
Nothing(_) -> /* ... */,
other -> println!("{:?}", other),
}
However, it's much more appropriate to write a Display instance yourself. You'll have to do the translation (Fizz -> "Fizz", etc) yourself, but then it will be in a centralized location and you can pass it to formatters like you've been doing.
To get the value out of the Nothing, you simply need to pattern match on it and give it a name. Instead of
Nothing(_) => // Do something generic
consider
Nothing(n) => // Do something that involves the number n

Resources