Hi I wrote a function that maps a vector to the interval [0,1]:
fn vec2interval(v: &Vec<f32>) -> Vec<f32> {
let total: f32 = v.iter().sum();
let mut interval: Vec<f32> = vec![0f32; v.len()];
interval[0] = v[0] / total;
for i in 1..v.len() {
interval[i] = interval[i-1] + v[i] / total;
}
return interval;
}
Is there any way to do the same with iterator? I wrote the following but it's slower and needs a for loop:
fn vec2interval(v: &Vec<f32>) -> Vec<f32> {
let total: f32 = v.iter().sum();
let mut interval: Vec<f32> = v
.iter()
.map(|x| x / total)
.collect::<Vec<f32>>();
for i in 1..v.len() {
interval[i] = interval[i-1] + interval[i];
}
return interval;
}
scan can do all of the job:
fn vec2interval(v: &Vec<f32>) -> Vec<f32> {
let total: f32 = v.iter().sum();
v.iter()
.scan(0.0, |acc, x| {
*acc += x / total;
Some(*acc)
})
.collect()
}
Also, slice (&[u8]) better be used instead of Vec<_> as a parameter.
Related
I'm attempting to implement SHA3-512 the way it is done by NIST in FIPS PUB 202:
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf.
It works whenever I plug in the test vector's bit values + "01"(look for HERE in code), and for the blank value test case.
Example working test vector:
https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_Msg5.pdf
For some reason, whenever string values such as "abc" are plugged in, the hash function fails to work. Despite the conversion from string to binary string being fine, I believe the issue is with the padding function but I cant see where I messed up.
/* Keccak */
struct Keccak<'a> {
b: usize,
d: usize,
r: usize,
l: usize,
w: usize,
delim: &'a str,
}
impl Keccak<'_> {
pub fn new(digest: usize, bits: usize, delim: &str) -> Keccak {
Keccak {
b: bits,
d: digest,
r: (bits - digest * 2),
w: bits / 25,
l: (((bits / 25) as f32).log2()) as usize,
delim,
}
}
pub fn hash(&mut self, msg: &mut String) {
self.sponge(msg);
}
// SPONGE the provided string of binary m
fn sponge(&mut self, msg: &mut String) {
// Pad the message using pad10*1
// HERE: let mut msg = &mut String::from("01");
let len = msg.len() as isize;
self.pad101(msg, self.r as isize, len);
// Let n be size of P
let n = msg.len() / self.r;
// Create vector s of size b/8, each value is a byte
let mut s: Vec<String> = vec!["0".repeat(8); self.b / 8];
// Xor s and p for every p in P
let c = self.b - self.r;
for i in 0..n {
// let p be the message of len(r) + 0^c of size b
let p = format!("{}{}", &msg[i * self.r..(i + 1) * self.r], "0".repeat(c));
// Xor s and p in byte sized intervals, then do a round of keccakf
s = self.keccackf(
&(0..p.len())
.step_by(8)
.map(|x| {
format!(
"{:08?}",
p[x..x + 8].parse::<u32>().unwrap() ^ s[x / 8].parse::<u32>().unwrap()
)
})
.collect::<Vec<String>>()
.join(""),
);
let mut z = String::new();
while z.len() <= self.d {
let mut str = s.join("");
str.truncate(self.r);
z += &str;
s = self.keccackf(&(s.join("")));
}
z.truncate(self.d);
self.from_bin_string(&z);
}
}
// Convert string m to state array
fn to_state(&self, msg: &str) -> Vec<Vec<Vec<u8>>> {
let mut s: Vec<Vec<Vec<u8>>> = Vec::new();
for x in 0..5 {
let mut row = Vec::new();
for y in 0..5 {
let mut column = Vec::new();
for z in 0..self.w {
let i = self.w * (5 * y + x) + z;
column.push(msg[i..i + 1].parse::<u8>().unwrap());
}
row.push(column)
}
s.push(row);
}
s
}
// Convert state array to vector of string
fn from_state(&self, state: Vec<Vec<Vec<u8>>>) -> Vec<String> {
let mut result: Vec<String> = Vec::new();
let mut temp = String::new();
for i in 0..5 {
for j in 0..5 {
for w in 0..self.w {
temp += &format!("{}", state[j][i][w]);
if (temp.len() == 8) {
result.push(temp.clone());
temp = String::new();
}
}
}
}
result
}
fn theta(&self, state: &mut Vec<Vec<Vec<u8>>>) {
// C NIST
fn c(x: usize, z: usize, state: &Vec<Vec<Vec<u8>>>) -> u8 {
state[x][0][z] ^ state[x][1][z] ^ state[x][2][z] ^ state[x][3][z] ^ state[x][4][z]
}
// D NIST
fn d(x: usize, z: usize, state: &Vec<Vec<Vec<u8>>>, w: isize) -> u8 {
c(((x as isize) - 1).rem_euclid(5) as usize, z, state)
^ c(
(x + 1).rem_euclid(5),
((z as isize) - 1).rem_euclid(w) as usize,
state,
)
}
// Let s be a'
let mut s = vec![vec![vec![0; self.w]; 5]; 5];
// Save xor'd values into a'
for x in 0..5 {
for y in 0..5 {
for z in 0..self.w {
s[x][y][z] = state[x][y][z] ^ d(x, z, &state, self.w as isize);
}
}
}
s.clone_into(state);
}
fn rho(&self, state: &mut Vec<Vec<Vec<u8>>>) {
// Let s be a'
let mut s = vec![vec![vec![0; self.w]; 5]; 5];
// Set all z values of a' = a
state[0][0].clone_into(&mut s[0][0]);
// Let coords represent (x, y)
let mut coords = [1, 0];
for t in 0..24 {
for z in 0..self.w {
s[coords[0]][coords[1]][z] = state[coords[0]][coords[1]]
[((z as isize) - (t + 1) * (t + 2) / 2).rem_euclid(self.w as isize) as usize];
}
coords = [coords[1], (2 * coords[0] + 3 * coords[1]).rem_euclid(5)];
}
s.clone_into(state);
}
fn pi(&self, state: &mut Vec<Vec<Vec<u8>>>) {
let mut s: Vec<Vec<Vec<u8>>> = Vec::new();
for x in 0..5 {
let mut row = Vec::new();
for y in 0..5 {
let mut column = Vec::new();
for z in 0..self.w {
column.push(state[((x as usize) + 3 * y).rem_euclid(5)][x][z]);
}
row.push(column)
}
s.push(row);
}
s.clone_into(state)
}
fn chi(&self, state: &mut Vec<Vec<Vec<u8>>>) {
let mut s: Vec<Vec<Vec<u8>>> = Vec::new();
for x in 0..5 {
let mut row = Vec::new();
for y in 0..5 {
let mut column = Vec::new();
for z in 0..self.w {
column.push(
state[x][y][z]
^ ((state[(x + 1).rem_euclid(5)][y][z] ^ 1)
* state[(x + 2).rem_euclid(5)][y][z]),
);
}
row.push(column)
}
s.push(row);
}
s.clone_into(state)
}
fn rc(&self, t: usize) -> u8 {
if t.rem_euclid(255) == 0 {
return 1;
}
let mut r = std::collections::VecDeque::new();
r.extend(
"10000000"
.chars()
.map(|x| x.to_string().parse::<u8>().unwrap()),
);
for _ in 0..t.rem_euclid(255) {
r.push_front(0);
r[0] ^= r[8];
r[4] ^= r[8];
r[5] ^= r[8];
r[6] ^= r[8];
r.truncate(8);
}
return r[0];
}
fn iota(&self, state: &mut Vec<Vec<Vec<u8>>>, round: usize) {
let mut r: Vec<u8> = vec![0; self.w];
for j in 0..=self.l {
r[((2 as isize).pow(j as u32) - 1) as usize] = self.rc(j + 7 * round);
}
for z in 0..self.w {
state[0][0][z] ^= r[z];
}
}
fn keccackf(&self, msg: &str) -> Vec<String> {
let mut state = self.to_state(msg);
// Go through all the rounds
for r in 0..(12 + 2 * self.l) {
self.theta(&mut state);
self.rho(&mut state);
self.pi(&mut state);
self.chi(&mut state);
self.iota(&mut state, r);
}
let res = self.from_state(state);
res
}
// Pad10*1
fn pad101(&mut self, msg: &mut String, x: isize, m: isize) {
let j = (-m - 2).rem_euclid(x);
msg.push_str("1");
msg.push_str(&"0".repeat(j as usize));
msg.push('1');
}
// For nist test vectors
fn from_bin_string(&self, str: &str) {
let z = (0..str.len())
.step_by(8)
.map(|i| (&str[i..i + 8]).chars().rev().collect::<String>())
.collect::<Vec<String>>();
for i in 0..z.len() {
print!("{:02x}", u32::from_str_radix(&z[i], 2).unwrap());
}
}
}
/* Sha3 */
pub struct SHA3<'a> {
kec: Option<Keccak<'a>>,
}
impl SHA3<'_> {
// Creates new hash variable with default hash function, currently SHA512
pub fn new() -> SHA3<'static> {
SHA3 { kec: None }
}
// Sha512
fn SHA512(&mut self, mut msg: String) {
match self.kec.as_mut() {
// Provided kec hash msg
Some(kec) => kec.hash(&mut msg),
// Otherwise create new kec and call function again
None => {
// Creating new keccack struct, l & w & state are defined in NIST
self.kec = Some(Keccak::new(512, 1600, "0110"));
self.SHA512(msg)
}
}
}
// Return hashed vector
pub fn hash(&mut self, m: &str) {
self.SHA512(self.to_bin_string(m) + "01");
}
// Return hexdigest output
pub fn hexdigest(&self, m: &str) {}
// Convert string slice to binary string
fn to_bin_string(&self, str: &str) -> String {
String::from(str)
.as_bytes()
.into_iter()
.map(|x| format!("{:08b}", x))
.collect::<Vec<String>>()
.join("")
}
}
How can I correct this behavior ?
P.S Now I am trying to implement a search for the number of page_faults when using the FIFO algorithm
fn page_fault(capacity: i32, n: i32, pages: &[i32]) -> i32 {
let mut s: HashSet<i32> = HashSet::new();
let mut indexes: VecDeque<i32> = VecDeque::new();
let mut page_faults: i32 = 0;
for i in 0..n {
if (s.len() as i32) < capacity {
if s.contains(&pages[(i) as usize]) {
s.insert(pages[(i) as usize]);
page_faults += 1;
indexes.insert(i as usize, pages[(i) as usize])
}
}
else {
if s.contains(&pages[(i) as usize]) {
let val = indexes.front();
indexes.pop_front();
s.remove(&val.unwrap());
s.insert(pages[(i) as usize]);
indexes.push_back(pages[(i) as usize]);
page_faults += 1;
}
}
}
return page_faults;
}
Terminal:
let val = indexes.front();
--------------- immutable borrow occurs here
indexes.pop_front();
^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
s.remove(&val.unwrap());
--- immutable borrow later used here
Calling indexes.front() seems redundant to me. You can simply use the result of indexes.pop_front() and assign it to a variable. So you can replace these two lines:
let val = indexes.front();
indexes.pop_front();
With this line:
let val = indexes.pop_front();
When calling indexes.front you are keeping a reference to it (&self), it can be easily solved by unwraping inmediatly and dereferencing it so the i32 is copied. Then the reference is freed.
use std::collections::VecDeque;
use std::collections::HashSet;
fn page_fault(capacity: i32, n: i32, pages: &[i32]) -> i32 {
let mut s: HashSet<i32> = HashSet::new();
let mut indexes: VecDeque<i32> = VecDeque::new();
let mut page_faults: i32 = 0;
for i in 0..n {
if (s.len() as i32) < capacity {
if s.contains(&pages[(i) as usize]) {
s.insert(pages[(i) as usize]);
page_faults += 1;
indexes.insert(i as usize, pages[(i) as usize])
}
}
else {
if s.contains(&pages[(i) as usize]) {
let val = *indexes.front().unwrap();
indexes.pop_front();
s.remove(&val);
s.insert(pages[(i) as usize]);
indexes.push_back(pages[(i) as usize]);
page_faults += 1;
}
}
}
return page_faults;
}
Playground
I have implemented a simple command-line calculator in Rust. The add function acts as normal but the subtract, multiply, and divide functions don't work. The rest of the code is on GitHub: https://github.com/henryboisdequin/rust-calculator.
calc.rs
impl Calc {
pub fn add(arr: Vec<i64>) -> f64 {
let mut total: f64 = 0.0;
for num in arr {
total += num as f64;
}
total
}
pub fn sub(arr: Vec<i64>) -> f64 {
let mut total: f64 = 0.0;
for num in arr {
total -= num as f64;
}
total
}
pub fn mul(arr: Vec<i64>) -> f64 {
let mut total: f64 = 0.0;
for num in arr {
total *= num as f64;
}
total
}
pub fn div(arr: Vec<i64>) -> f64 {
let mut total: f64 = 0.0;
for num in arr {
total /= num as f64;
}
total
}
}
Instead of having your functions take Vec<i64>, I would instead suggest &[i64], or even &[f64] to avoid the as f64. This wouldn't really break your existing code, as you can just borrow a Vec<i64>, to have it auto dereference into &[i64].
You can simplify add() by using sum(), and mul() by using product().
pub fn add(arr: &[i64]) -> f64 {
arr.iter().map(|&x| x as f64).sum()
}
pub fn mul(arr: &[i64]) -> f64 {
arr.iter().map(|&x| x as f64).product()
}
You can similarly simplify sub() and div() with next() and then fold().
pub fn sub(arr: &[i64]) -> f64 {
let mut it = arr.iter().map(|&x| x as f64);
it.next()
.map(|x| it.fold(x, |acc, x| acc - x))
.unwrap_or(0.0)
}
pub fn div(arr: &[i64]) -> f64 {
let mut it = arr.iter().map(|&x| x as f64);
it.next()
.map(|x| it.fold(x, |acc, x| acc / x))
.unwrap_or(0.0)
}
You can even simplify them further, by using fold_first(). However that is currently experimental and nightly only. Instead you can use fold1() from the itertools crate, or reduce() from the reduce crate.
// itertools = "0.10"
use itertools::Itertools;
pub fn sub(arr: &[i64]) -> f64 {
arr.iter().map(|&x| x as f64).fold1(|a, b| a - b).unwrap_or(0.0)
}
pub fn div(arr: &[i64]) -> f64 {
arr.iter().map(|&x| x as f64).fold1(|a, b| a / b).unwrap_or(0.0)
}
You can even replace the closures with Sub::sub and Div::div.
// itertools = "0.10"
use itertools::Itertools;
use std::ops::{Div, Sub};
pub fn sub(arr: &[i64]) -> f64 {
arr.iter().map(|&x| x as f64).fold1(Sub::sub).unwrap_or(0.0)
}
pub fn div(arr: &[i64]) -> f64 {
arr.iter().map(|&x| x as f64).fold1(Div::div).unwrap_or(0.0)
}
Siguza helped me fix this problem by specifying that my addition function only works because addition is commutative but the other operations are failing because they are not.
Here is the right code:
pub struct Calc;
impl Calc {
pub fn add(arr: Vec<i64>) -> f64 {
let mut total: f64 = 0.0;
for num in arr {
total += num as f64;
}
total
}
pub fn sub(arr: Vec<i64>) -> f64 {
let mut total: f64 = arr[0] as f64;
let mut counter = 0;
while counter != arr.len() - 1 {
total -= arr[counter + 1] as f64;
counter += 1;
}
total
}
pub fn mul(arr: Vec<i64>) -> f64 {
let mut total: f64 = arr[0] as f64;
let mut counter = 0;
while counter != arr.len() - 1 {
total *= arr[counter + 1] as f64;
counter += 1;
}
total
}
pub fn div(arr: Vec<i64>) -> f64 {
let mut total: f64 = arr[0] as f64;
let mut counter = 0;
while counter != arr.len() - 1 {
total /= arr[counter + 1] as f64;
counter += 1;
}
total
}
}
For the operations excluding 0, instead of assigning the total to 0.0, I assigned the total to the first element of the given array and -/*// the total with the rest of the elements in the array.
This is what I wrote for LeetCode: Add Two Numbers
//2. Add Two Numbers
// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>,
}
impl ListNode {
#[inline]
fn new(val: i32) -> Self {
ListNode { next: None, val }
}
}
struct Solution;
impl Solution {
pub fn list_to_num(ls: &Option<Box<ListNode>>) -> i64 {
let mut vec = vec![];
let mut head = ls;
while let Some(node) = head {
vec.push(node.val);
head = &node.next;
}
vec.reverse();
let mut num = 0i64;
for x in vec {
num *= 10;
num += x as i64;
}
num
}
pub fn num_to_list(num: i64) -> Option<Box<ListNode>> {
let num_str = num.to_string();
let vec = num_str
.chars()
.map(|x| x.to_digit(10).unwrap() as i32)
.collect::<Vec<_>>();
let mut res = None;
for x in vec {
let mut one = ListNode::new(x);
one.next = res;
res = Some(Box::new(one));
}
res
}
pub fn add_two_numbers(
l1: Option<Box<ListNode>>,
l2: Option<Box<ListNode>>,
) -> Option<Box<ListNode>> {
let mut vec = vec![] as Vec<i32>;
let mut step = 0;
let mut left = l1;
let mut right = l2;
loop {
match (left, right) {
(None, None) => {
if step != 0 {
vec.push(step);
}
break;
}
(Some(leftN), None) => {
let curr = leftN.val + step;
if curr >= 10 {
vec.push(curr - 10);
step = 1
} else {
vec.push(curr);
step = 0
}
left = leftN.next
}
(None, Some(rightN)) => {
let curr = rightN.val + step;
if curr >= 10 {
vec.push(curr - 10);
step = 1
} else {
vec.push(curr);
step = 0
}
right = rightN.next
}
(Some(leftN), Some(rightN)) => {
let curr = leftN.val + rightN.val + step;
if curr >= 10 {
vec.push(curr - 10);
step = 1
} else {
vec.push(curr);
step = 0
}
right = rightN.next;
left = leftN.next
}
}
}
vec.reverse();
let mut res = None;
for x in vec {
let mut next = ListNode::new(x);
next.next = res;
res = Some(Box::new(next));
}
res
}
}
fn main() {
let list1 = Solution::num_to_list(9);
let list2 = Solution::num_to_list(991);
println!("list1 {:?}", list1);
println!("list2 {:?}", list2);
let res = Solution::add_two_numbers(list1, list2);
println!("summed {:#?}", res);
}
I get a compile error
error[E0382]: use of moved value: `left`
--> src/main.rs:66:20
|
63 | let mut left = l1;
| -------- move occurs because `left` has type `std::option::Option<std::boxed::Box<ListNode>>`, which does not implement the `Copy` trait
...
66 | match (left, right) {
| ^^^^ value moved here, in previous iteration of loop
error[E0382]: use of moved value: `right`
--> src/main.rs:66:26
|
64 | let mut right = l2;
| --------- move occurs because `right` has type `std::option::Option<std::boxed::Box<ListNode>>`, which does not implement the `Copy` trait
65 | loop {
66 | match (left, right) {
| ^^^^^ value moved here, in previous iteration of loop
I think each iteration is independent, and if the value is borrowed by a previous iteration, it should be returned in "this" iteration.
If I replace match (left, right) { with match (left.clone(), right.clone()) {, the code compiles, but it might consume more memory than necessary. What is the better way to make it compile and be memory economical?
You're not borrowing the nodes, you're moving them.
In order to use references, you should replace
let mut left = l1;
let mut right = l2;
with
let mut left = &l1;
let mut right = &l2;
and then later
right = rightN.next;
with
right = &rightN.next;
etc.
playground
I am new to Rust. My code is given below:
use std::*;
fn DFS(A: i32, grid: &mut [[i32; 500]; 500], visited: &mut [i32; 500]) -> (usize, usize) {
let mut s = Vec::new();
s.push(A);
visited[A as usize] = 1;
let mut flag;
let mut max_height = 0;
let mut ans_vertex: usize = A as usize;
let mut x;
'outer: while let Some(top) = s.pop() {
s.push(top);
x = top as usize;
flag = 0;
'inner: for i in 1..500 {
if visited[grid[x][i] as usize] == 0 && grid[x][i] != 0 {
flag = 1;
s.push(grid[x][i]);
visited[grid[x][i] as usize] = 1;
break 'outer;
}
}
if s.len() > max_height {
max_height = s.len();
ans_vertex = s.pop() as usize;
}
if flag != 0 {
s.pop();
}
}
println!("{}, {}", ans_vertex, max_height);
return (ans_vertex, max_height);
}
fn fc(grid: &mut [[i32; 500]; 500]) {
for i in 1..500 {
for j in 1..500 {
grid[i][j] = 0;
}
}
grid[1][2] = 1;
grid[2][1] = 1;
grid[2][3] = 1;
grid[3][2] = 1;
grid[3][4] = 1;
grid[4][3] = 1;
}
fn main() {
let mut visited: [i32; 500] = [0; 500];
let mut grid: [[i32; 500]; 500] = [[0; 500]; 500];
fc(&mut grid);
let B = DFS(1, &mut grid, &mut visited);
println!("{}", B.0);
}
I already tried changing usize to u32 and other types, but I'm not getting any results. When I run rustc newdia.rs, it shows:
newdia.rs:26:17: 26:33 error: non-scalar cast: `core::option::Option<i32>` as `usize`
newdia.rs:26 ans_vertex = s.pop() as usize;
^~~~~~~~~~~~~~~~
error: aborting due to previous error
Vec::pop() returns an Option<T> because if the Vec is empty, there's no value present to pop. If you're sure your Vec contains atleast 1 value before you call Vec::pop(), you can use Option::unwrap(), which will convert your Option<i32> to i32 (and panic if Vec::pop returned None because the Vec was empty).
ans_vertex = s.pop().unwrap() as usize;
You can also choose to handle the cases differently using match or if let:
if let Some(popped) = s.pop() {
// Successfully popped `popped`. `popped` here is an i32.
} else {
// `s` was empty.
}