Compare commits

...

9 commits

Author SHA1 Message Date
Kacper Poneta b02b1dc296
Merge 59e8f70e55 into b01fddef8b 2024-08-20 04:26:11 +01:00
mo8it b01fddef8b Show progress of dev check 2024-08-19 23:52:22 +02:00
mo8it 78a8553f1c "Continue at" quits the list 2024-08-19 23:29:17 +02:00
mo8it b70c1abd7c Update deps 2024-08-19 23:28:53 +02:00
mo8it 59e8f70e55 Format code 2024-07-12 18:31:23 +02:00
mo8it 4c8365fe88 Update dev/Cargo.toml 2024-07-12 18:25:01 +02:00
Kacper Poneta 52af0674c1 changed the task to make it more appropriate 2024-07-12 18:14:40 +02:00
Kacper Poneta 938b90e5f2 very small solution update 2024-07-11 22:55:48 +02:00
Kacper Poneta 55cc8584bd added exercise 2024-07-11 22:53:38 +02:00
7 changed files with 153 additions and 10 deletions

8
Cargo.lock generated
View file

@ -368,9 +368,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.156"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "libredox"
@ -746,9 +746,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.74"
version = "2.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7"
checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9"
dependencies = [
"proc-macro2",
"quote",

View file

@ -116,6 +116,8 @@ bin = [
{ name = "generics1_sol", path = "../solutions/14_generics/generics1.rs" },
{ name = "generics2", path = "../exercises/14_generics/generics2.rs" },
{ name = "generics2_sol", path = "../solutions/14_generics/generics2.rs" },
{ name = "generics3", path = "../exercises/14_generics/generics3.rs" },
{ name = "generics3_sol", path = "../solutions/14_generics/generics3.rs" },
{ name = "traits1", path = "../exercises/15_traits/traits1.rs" },
{ name = "traits1_sol", path = "../solutions/15_traits/traits1.rs" },
{ name = "traits2", path = "../exercises/15_traits/traits2.rs" },

View file

@ -0,0 +1,54 @@
// generics3.rs
// Execute `rustlings hint generics3` or use the `hint` watch subcommand for a hint.
// This function should take an array of `Option` elements and returns array of not None elements
// TODO fix this function signature
fn into_dispose_nulls(list: Vec<Option<&str>>) -> Vec<&str> {
list.into_iter().flatten().collect()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_str_on_list() {
let names_list = vec![Some("maria"), Some("jacob"), None, Some("kacper"), None];
let only_values = into_dispose_nulls(names_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_numbers_on_list() {
let numbers_list = vec![Some(1), Some(2), None, Some(3)];
let only_values = into_dispose_nulls(numbers_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_custom_type_on_list() {
#[allow(dead_code)]
struct Rectangle {
width: i32,
height: i32,
}
impl Rectangle {
fn new(width: i32, height: i32) -> Self {
Self { width, height }
}
}
let custom_list = vec![
Some(Rectangle::new(1, 2)),
None,
None,
Some(Rectangle::new(3, 4)),
];
let only_values = into_dispose_nulls(custom_list);
assert_eq!(only_values.len(), 2);
}
}

View file

@ -744,6 +744,17 @@ hint = """
Related section in The Book:
https://doc.rust-lang.org/book/ch10-01-syntax.html#in-method-definitions"""
[[exercises]]
name = "generics3"
dir = "14_generics"
hint = """
Vectors in Rust use generics to create dynamically-sized arrays of any type.
The `into_dispose_nulls` function takes a vector as an argument, but only accepts vectors that store the &str type.
To allow the function to accept vectors that store any type, you can leverage your knowledge about generics.
If you're unsure how to proceed, please refer to the Rust Book at:
https://doc.rust-lang.org/book/ch10-01-syntax.html#in-function-definitions.
"""
# TRAITS
[[exercises]]

View file

@ -0,0 +1,53 @@
// generics3.rs
// Execute `rustlings hint generics3` or use the `hint` watch subcommand for a hint.
// Here we added generic type `T` to function signature
// Now this function can be used with vector of any
fn into_dispose_nulls<T>(list: Vec<Option<T>>) -> Vec<T> {
list.into_iter().flatten().collect()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_str_on_list() {
let names_list = vec![Some("maria"), Some("jacob"), None, Some("kacper"), None];
let only_values = into_dispose_nulls(names_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_numbers_on_list() {
let numbers_list = vec![Some(1), Some(2), None, Some(3)];
let only_values = into_dispose_nulls(numbers_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_custom_type_on_list() {
struct Rectangle {
width: i32,
height: i32,
}
impl Rectangle {
fn new(width: i32, height: i32) -> Self {
Self { width, height }
}
}
let custom_list = vec![
Some(Rectangle::new(1, 2)),
None,
None,
Some(Rectangle::new(3, 4)),
];
let only_values = into_dispose_nulls(custom_list);
assert_eq!(only_values.len(), 2);
}
}

View file

@ -161,9 +161,9 @@ fn check_unexpected_files(dir: &str, allowed_rust_files: &HashSet<PathBuf>) -> R
}
fn check_exercises_unsolved(info_file: &InfoFile, cmd_runner: &CmdRunner) -> Result<()> {
println!(
"Running all exercises to check that they aren't already solved. This may take a while…\n",
);
let mut stdout = io::stdout().lock();
stdout.write_all(b"Running all exercises to check that they aren't already solved...\n")?;
thread::scope(|s| {
let handles = info_file
.exercises
@ -180,6 +180,11 @@ fn check_exercises_unsolved(info_file: &InfoFile, cmd_runner: &CmdRunner) -> Res
})
.collect::<Vec<_>>();
let n_handles = handles.len();
write!(stdout, "Progress: 0/{n_handles}")?;
stdout.flush()?;
let mut handle_num = 1;
for (exercise_name, handle) in handles {
let Ok(result) = handle.join() else {
bail!("Panic while trying to run the exericse {exercise_name}");
@ -192,7 +197,12 @@ fn check_exercises_unsolved(info_file: &InfoFile, cmd_runner: &CmdRunner) -> Res
Ok(false) => (),
Err(e) => return Err(e),
}
write!(stdout, "\rProgress: {handle_num}/{n_handles}")?;
stdout.flush()?;
handle_num += 1;
}
stdout.write_all(b"\n")?;
Ok(())
})
@ -225,7 +235,9 @@ fn check_solutions(
info_file: &InfoFile,
cmd_runner: &CmdRunner,
) -> Result<()> {
println!("Running all solutions. This may take a while…\n");
let mut stdout = io::stdout().lock();
stdout.write_all(b"Running all solutions...\n")?;
thread::scope(|s| {
let handles = info_file
.exercises
@ -261,6 +273,11 @@ fn check_solutions(
.arg("always")
.stdin(Stdio::null());
let n_handles = handles.len();
write!(stdout, "Progress: 0/{n_handles}")?;
stdout.flush()?;
let mut handle_num = 1;
for (exercise_info, handle) in info_file.exercises.iter().zip(handles) {
let Ok(check_result) = handle.join() else {
bail!(
@ -282,7 +299,8 @@ fn check_solutions(
}
SolutionCheck::MissingOptional => (),
SolutionCheck::RunFailure { output } => {
io::stderr().lock().write_all(&output)?;
stdout.write_all(b"\n\n")?;
stdout.write_all(&output)?;
bail!(
"Running the solution of the exercise {} failed with the error above",
exercise_info.name,
@ -290,7 +308,12 @@ fn check_solutions(
}
SolutionCheck::Err(e) => return Err(e),
}
write!(stdout, "\rProgress: {handle_num}/{n_handles}")?;
stdout.flush()?;
handle_num += 1;
}
stdout.write_all(b"\n")?;
let handle = s.spawn(move || check_unexpected_files("solutions", &sol_paths));

View file

@ -75,7 +75,7 @@ fn handle_list(app_state: &mut AppState, stdout: &mut StdoutLock) -> Result<()>
}
KeyCode::Char('c') => {
ui_state.selected_to_current_exercise()?;
ui_state = ui_state.with_updated_rows();
break;
}
_ => (),
}