Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CON-3264 Fix rust piscine's quest-02 #145

Merged
merged 18 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Test Image specific config

FROM rust:1.78-slim-bookworm
FROM rust:1.83-slim-bookworm

RUN apt-get update
RUN apt-get -y install pkg-config libssl-dev moreutils
Expand Down
29 changes: 9 additions & 20 deletions solutions/armstrong_number/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
pub fn is_armstrong_number(nb: u32) -> Option<u32> {
let nb_digits = nb_digits(nb);
let mut new_num = nb;
let mut armstrong: u32 = 0;
let digits = nb.checked_ilog10().unwrap_or_default() + 1;

while new_num != 0 {
let digit = new_num % 10;
match armstrong.checked_add(digit.pow(nb_digits)) {
Some(nb) => armstrong = nb,
None => return None,
}
let armstrong = (0..digits)
.scan(nb, |state, _| {
let val = (*state % 10).pow(digits);

new_num /= 10;
}
(armstrong == nb).then_some(nb)
}
*state /= 10;

fn nb_digits(mut nb: u32) -> u32 {
let mut nb_digits = 0;
Some(val)
})
.sum::<u32>();

while nb != 0 {
nb_digits += 1;
nb /= 10;
}
nb_digits
(armstrong == nb).then_some(nb)
}
1 change: 1 addition & 0 deletions solutions/arrange_it/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
itertools = "0.13.0"
65 changes: 14 additions & 51 deletions solutions/arrange_it/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,17 @@
/*
## arrange_it

### Instructions

Create a function called `arrange_phrase` that takes a string literal as a phrase and returns it organized
Each word will have a number that indicates the position of that word

### Example

```rust
fn main() {
println!("{:?}", initials("is2 Thi1s T4est 3a"));
// output: This is a Test
}
```

> This exercise will test the **heap allocation** of your function!
> So try your best to allocate the minimum data on the heap!

### Notions

- https://doc.rust-lang.org/1.22.0/book/first-edition/the-stack-and-the-heap.html
- https://doc.rust-lang.org/std/primitive.str.html#method.split

*/
use itertools::Itertools;

pub fn arrange_phrase(phrase: &str) -> String {
let nbrs: Vec<&str> = phrase.matches(char::is_numeric).collect();
let a = &phrase.replace(char::is_numeric, "");
let mut m: Vec<&str> = a.split_whitespace().collect();

for (i, ele) in nbrs.iter().enumerate() {
let strs: Vec<&str> = a.split_whitespace().collect();
m[ele.parse::<usize>().unwrap() - 1] = strs[i];
}
m.join(" ")
let indexes = phrase
.matches(|c: char| c.is_ascii_digit())
.map(|c| c.parse::<u32>().unwrap());

let stripped = phrase.replace(|c: char| c.is_ascii_digit(), "");

stripped
.split_ascii_whitespace()
.zip(indexes)
.sorted_unstable_by_key(|&(_, i)| i)
.map(|(w, _)| w)
.collect::<Vec<_>>()
.join(" ")
}

// // example of function that works but does not pass the heap test
// pub fn arrange_phrase(phrase: &str) -> String {
// let mut vec = vec![0; 1024];
// vec.push(213);
// let words_nbr = phrase.matches(" ").count() + 1;
// let mut result_vec: Vec<String> = vec!["".to_string(); words_nbr];
// for word in phrase.split_whitespace().into_iter() {
// for i in 1..words_nbr + 1 {
// if word.contains(&i.to_string()) {
// result_vec[i - 1] = word.split(&i.to_string()).collect::<String>();
// }
// }
// }
// result_vec.join(" ")
// }
92 changes: 1 addition & 91 deletions solutions/borrow/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,93 +1,3 @@
/*
## borrow

### Instructions

Complete the signature and the body of the `str_len` function so it
receives a string or a string literal and returns its length (of type usize)
without taking ownership of the value (i.e, borrowing the value)

### Example

```rust
fn main() {
let s = "hello";
let s1 = "camelCase".to_string();

println!("\tstr_len(\"{}\") = {}", s, str_len(s));
println!("\tstr_len(\"{}\") = {}", s1, str_len(&s1));
}
```
*/

// fn main() {
// let s = "hello";
// let s1 = "camelCase".to_string();

// println!("\tstr_len(\"{}\") = {}", s, str_len(s));
// println!("\tstr_len(\"{}\") = {}", s1, str_len(&s1));
// }

pub fn str_len(s: &str) -> usize {
// Write you're code here
s.len()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
// maybe not the best way to make the test, but I wanted to use
// lifetimes
fn str_len_test() {
struct TstLit<'a> {
str: &'a str,
l: usize,
}

struct TstString {
str: String,
l: usize,
}

let tsts = vec![
TstLit { str: "hello", l: 5 },
TstLit { str: "how", l: 3 },
TstLit {
str: "are you",
l: 7,
},
TstLit {
str: "change",
l: 6,
},
];
let o_tsts = vec![
TstString {
str: "hello".to_string(),
l: 5,
},
TstString {
str: "how".to_string(),
l: 3,
},
TstString {
str: "are you".to_string(),
l: 7,
},
TstString {
str: "change".to_string(),
l: 6,
},
];

for t in tsts.iter() {
assert_eq!(t.l, str_len(t.str));
}

for t in o_tsts.iter() {
assert_eq!(t.l, str_len(&t.str));
}
}
s.chars().count()
}
19 changes: 7 additions & 12 deletions solutions/borrow_me_the_reference/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,12 @@ pub fn delete_and_backspace(s: &mut String) {
}
}

pub fn do_operations(v: &mut Vec<String>) {
for (i, equation) in v.clone().iter().enumerate() {
let numbers: Vec<&str> = equation.split(|c| c == '+' || c == '-').collect();
let left_number = numbers[0].parse::<i32>().unwrap();
let right_number = numbers[1].parse::<i32>().unwrap();
pub fn do_operations(v: &mut [String]) {
v.iter_mut().for_each(|equation| {
let (l, r) = equation.split_once(['+', '-']).unwrap();
let (l, r) = (l.parse::<i32>().unwrap(), r.parse::<i32>().unwrap());

let result = if equation.contains('+') {
left_number + right_number
} else {
left_number - right_number
};
v[i] = result.to_string();
}
let result = if equation.contains('+') { l + r } else { l - r };
*equation = result.to_string();
});
}
133 changes: 9 additions & 124 deletions solutions/copy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,132 +1,17 @@
/*
## copy

### Instructions

Your objective is to fix the program so that all functions work.

- `nbr_function`, returns a tuple with the original value, the exponential and logarithm of that value
- `str_function`, returns a tuple with the original value and the exponential of that value as a string
- `vec_function`, returns a tuple with the original value and the logarithm of each value

The objective is to now how ownership works with different types.

### Example

```rust
fn main() {
let a = String::from("1 2 4 5 6");
let b = vec![1, 2, 4, 5];
let c: u32 = 0;

println!("{:?}", nbr_function(c));
// output: (12, 162754.79141900392, 2.4849066497880004)
println!("{:?}", vec_function(b));
// output: ([1, 2, 4], [0.0, 0.6931471805599453, 1.3862943611198906])
println!("{:?}", str_function(a));
// output: ("1 2 4", "2.718281828459045 7.38905609893065 54.598150033144236")
}
```

### Notions

- https://doc.rust-lang.org/rust-by-example/scope/move.html
*/

pub fn nbr_function(c: i32) -> (i32, f64, f64) {
(c, exponential(c), logarithm(c))
}

pub fn logarithm(n: i32) -> f64 {
(n.abs() as f64).ln()
}
pub fn exponential(n: i32) -> f64 {
(n as f64).exp()
(c, (c as f64).exp(), (c as f64).abs().ln())
}

pub fn str_function(a: String) -> (String, String) {
(a.clone(), exp(a).join(" "))
}
pub fn exp(s: String) -> Vec<String> {
let mut v: Vec<String> = Vec::new();
for token in s.split_whitespace() {
v.push(exponential(token.parse::<i32>().unwrap()).to_string());
}
v
let transform = a
.split_ascii_whitespace()
.map(|n| n.parse::<f64>().unwrap().exp().to_string())
.collect::<Vec<_>>()
.join(" ");
(a, transform)
}

pub fn vec_function(b: Vec<i32>) -> (Vec<i32>, Vec<f64>) {
(b.clone(), b.iter().map(|v| logarithm(*v)).collect())
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn ownership_nbr_test() {
assert_eq!(
nbr_function(12),
(12, 162754.79141900392, 2.4849066497880004)
);
assert_eq!(nbr_function(1), (1, 2.718281828459045, 0.0));
assert_eq!(nbr_function(0), (0, 1.0, std::f64::NEG_INFINITY));
}

#[test]
fn negative_nbr_test() {
assert_eq!(
nbr_function(-12),
(-12, 0.00000614421235332821, 2.4849066497880004)
);
assert_eq!(nbr_function(-1), (-1, 0.36787944117144233, 0.0));
assert_eq!(nbr_function(0), (0, 1.0, std::f64::NEG_INFINITY));
}

#[test]
fn ownership_vec_test() {
assert_eq!(
vec_function(vec![1, 2, 4]),
(
vec![1, 2, 4],
vec![0.0, 0.6931471805599453, 1.3862943611198906]
)
);

assert_eq!(
vec_function(vec![0, 1]),
(vec![0, 1], vec![std::f64::NEG_INFINITY, 0.0])
);

assert_eq!(
vec_function(vec![1, 2, 4, 5]),
(
vec![1, 2, 4, 5],
vec![
0.0,
0.6931471805599453,
1.3862943611198906,
1.6094379124341003
]
)
);
}

#[test]
fn ownership_str_test() {
assert_eq!(
str_function(String::from("1 2 4")),
(
"1 2 4".to_string(),
"2.718281828459045 7.38905609893065 54.598150033144236".to_string()
)
);
assert_eq!(
str_function(String::from("1 0")),
(("1 0".to_string(), "2.718281828459045 1".to_string()))
);
assert_eq!(str_function(
String::from("1 2 4 5 6")),
(("1 2 4 5 6".to_string(), "2.718281828459045 7.38905609893065 54.598150033144236 148.4131591025766 403.4287934927351".to_string())));
}
let transform = b.iter().copied().map(|n| (n as f64).abs().ln()).collect();
(b, transform)
}
Loading
Loading