I have setup the docker container to run the model evaluation.
Write a self-contained Rust program that prints a JSON output of how often each word appears in a text file located in /tmp/file.txt. So if the file contains "This is is is, an example" then the program should print to stdout. {"This": 1, "is": 2, "is,": 1, "an": 1, "example": 1} Don't import any crates that would require a Cargo.toml file. I'll just compile it with `rustc yourfile.rs` and it should work. The program should be run by calling /path/to/rust_word_count with no arguments. Make it run in parallel on 4 cores at the same time, each job taking ~1/4 of the file. Print out 4 differnt json dicts, one per line. I'll do the merging.
Write a self-contained Rust program that prints a JSON output of how often each word appears in a text file located in /tmp/file.txt. So if the file contains "This is is is, an example" then the program should print to stdout. {"This": 1, "is": 2, "is,": 1, "an": 1, "example": 1} Don't import any crates that would require a Cargo.toml file. I'll just compile it with `rustc yourfile.rs` and it should work. The program should be run by calling /path/to/rust_word_count with no arguments. Make it run in parallel on 4 cores at the same time, each job taking ~1/4 of the file. Print out 4 differnt json dicts, one per line. I'll do the merging.
Here's the Rust program that meets your requirements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::sync::Mutex; fn main() -> std::io::Result<()> { let path = "/tmp/file.txt"; let mut content = String::new(); File::open(path)?.read_to_string(&mut content)?; let words: Vec<&str> = content.split_whitespace().collect(); let total_words = words.len(); let num_chunks = 4; let quot = total_words / num_chunks; let rem = total_words % num_chunks; let mut chunks = Vec::new(); let mut start = 0; for i in 0..num_chunks { let chunk_size = quot + if i < rem { 1 } else { 0 }; let end = (start + chunk_size).min(total_words); chunks.push(&words[start..end]); start = end; } let stdout = Mutex::new(std::io::stdout()); std::thread::scope(|s| { for chunk in chunks { s.spawn(|| { let mut counts = HashMap::new(); for &word in chunk { *counts.entry(word.to_string()).or_insert(0) += 1; } let json = format_counts(&counts); let mut stdout = stdout.lock().unwrap(); println!("{}", json); }); } }); Ok(()) } fn format_counts(counts: &HashMap<String, u32>) -> String { let mut entries: Vec<String> = counts .iter() .map(|(word, count)| { let escaped = word .chars() .map(|c| match c { '"' => "\\\"".to_string(), '\\' => "\\\\".to_string(), _ => c.to_string(), }) .collect::<String>(); format!("\"{}\": {}", escaped, count) }) .collect(); entries.sort(); // For deterministic output order format!("{{{}}}", entries.join(", ")) } |
1 2 | rustc rust_word_count.rs
./rust_word_count
|
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::sync::Mutex; fn main() -> std::io::Result<()> { let path = "/tmp/file.txt"; let mut content = String::new(); File::open(path)?.read_to_string(&mut content)?; let words: Vec<&str> = content.split_whitespace().collect(); let total_words = words.len(); let num_chunks = 4; let quot = total_words / num_chunks; let rem = total_words % num_chunks; let mut chunks = Vec::new(); let mut start = 0; for i in 0..num_chunks { let chunk_size = quot + if i < rem { 1 } else { 0 }; let end = (start + chunk_size).min(total_words); chunks.push(&words[start..end]); start = end; } let stdout = Mutex::new(std::io::stdout()); std::thread::scope(|s| { for chunk in chunks { s.spawn(|| { let mut counts = HashMap::new(); for &word in chunk { *counts.entry(word.to_string()).or_insert(0) += 1; } let json = format_counts(&counts); let mut stdout = stdout.lock().unwrap(); println!("{}", json); }); } }); Ok(()) } fn format_counts(counts: &HashMap<String, u32>) -> String { let mut entries: Vec<String> = counts .iter() .map(|(word, count)| { let escaped = word .chars() .map(|c| match c { '"' => "\\\"".to_string(), '\\' => "\\\\".to_string(), _ => c.to_string(), }) .collect::<String>(); format!("\"{}\": {}", escaped, count) }) .collect(); entries.sort(); format!("{{{}}}", entries.join(", ")); } |
Below is some student's code. I asked them to parallelize some code. Do not judge if it is correct, I have test cases for that. Logic errors are okay. So are synatx errors. Just tell me if they tried to parallelize it. use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::sync::Mutex; fn main() -> std::io::Result<()> { let path = "/tmp/file.txt"; let mut content = String::new(); File::open(path)?.read_to_string(&mut content)?; let words: Vec<&str> = content.split_whitespace().collect(); let total_words = words.len(); let num_chunks = 4; let quot = total_words / num_chunks; let rem = total_words % num_chunks; let mut chunks = Vec::new(); let mut start = 0; for i in 0..num_chunks { let chunk_size = quot + if i < rem { 1 } else { 0 }; let end = (start + chunk_size).min(total_words); chunks.push(&words[start..end]); start = end; } let stdout = Mutex::new(std::io::stdout()); std::thread::scope(|s| { for chunk in chunks { s.spawn(|| { let mut counts = HashMap::new(); for &word in chunk { *counts.entry(word.to_string()).or_insert(0) += 1; } let json = format_counts(&counts); let mut stdout = stdout.lock().unwrap(); println!("{}", json); }); } }); Ok(()) } fn format_counts(counts: &HashMap<String, u32>) -> String { let mut entries: Vec<String> = counts .iter() .map(|(word, count)| { let escaped = word .chars() .map(|c| match c { '"' => "\\\"".to_string(), '\\' => "\\\\".to_string(), _ => c.to_string(), }) .collect::<String>(); format!("\"{}\": {}", escaped, count) }) .collect(); entries.sort(); format!("{{{}}}", entries.join(", ")); } Answer either 'The student passes' or 'The student fails'.
The student passes.
Testing if the previous output contains the string student passes
: True
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::sync::Mutex; fn main() -> std::io::Result<()> { let path = "/tmp/file.txt"; let mut content = String::new(); File::open(path)?.read_to_string(&mut content)?; let words: Vec<&str> = content.split_whitespace().collect(); let total_words = words.len(); let num_chunks = 4; let quot = total_words / num_chunks; let rem = total_words % num_chunks; let mut chunks = Vec::new(); let mut start = 0; for i in 0..num_chunks { let chunk_size = quot + if i < rem { 1 } else { 0 }; let end = (start + chunk_size).min(total_words); chunks.push(&words[start..end]); start = end; } let stdout = Mutex::new(std::io::stdout()); std::thread::scope(|s| { for chunk in chunks { s.spawn(|| { let mut counts = HashMap::new(); for &word in chunk { *counts.entry(word.to_string()).or_insert(0) += 1; } let json = format_counts(&counts); let mut stdout = stdout.lock().unwrap(); println!("{}", json); }); } }); Ok(()) } fn format_counts(counts: &HashMap<String, u32>) -> String { let mut entries: Vec<String> = counts .iter() .map(|(word, count)| { let escaped = word .chars() .map(|c| match c { '"' => "\\\"".to_string(), '\\' => "\\\\".to_string(), _ => c.to_string(), }) .collect::<String>(); format!("\"{}\": {}", escaped, count) }) .collect(); entries.sort(); format!("{{{}}}", entries.join(", ")); } |
error[E0308]: mismatched types
--> main.rs:46:52
|
46 | fn format_counts(counts: &HashMap<String, u32>) -> String {
| ------------- ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
...
62 | format!("{{{}}}", entries.join(", "));
| - help: remove this semicolon to return this value
warning: unused variable: `stdout`
--> main.rs:37:25
|
37 | let mut stdout = stdout.lock().unwrap();
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_stdout`
|
= note: `#[warn(unused_variables)]` on by default
warning: variable does not need to be mutable
--> main.rs:37:21
|
37 | let mut stdout = stdout.lock().unwrap();
| ----^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0373]: closure may outlive the current function, but it borrows `chunk`, which is owned by the current function
--> main.rs:31:21
|
29 | std::thread::scope(|s| {
| - has type `&'1 Scope<'1, '_>`
30 | for chunk in chunks {
31 | s.spawn(|| {
| ^^ may outlive borrowed value `chunk`
32 | let mut counts = HashMap::new();
33 | for &word in chunk {
| ----- `chunk` is borrowed here
|
note: function requires argument type to outlive `'1`
--> main.rs:31:13
|
31 | / s.spawn(|| {
32 | | let mut counts = HashMap::new();
33 | | for &word in chunk {
34 | | *counts.entry(word.to_string()).or_insert(0) += 1;
... |
38 | | println!("{}", json);
39 | | });
| |______________^
help: to force the closure to take ownership of `chunk` (and any other referenced variables), use the `move` keyword
|
31 | s.spawn(move || {
| ++++
error: aborting due to 2 previous errors; 2 warnings emitted
Some errors have detailed explanations: E0308, E0373.
For more information about an error, try `rustc --explain E0308`.
main.sh: line 2: ./a.out: No such file or directory
Resulting in output: []
Testing if the previous output equals the string [('Darkness,', 1), ('Heaven,', 1), ('Light,', 1), ('age', 2), ('all', 2), ('before', 2), ('belief,', 1), ('best', 1), ('despair,', 1), ('direct', 2), ('epoch', 2), ('everything', 1), ('foolishness,', 1), ('going', 2), ('had', 2), ('hope,', 1), ('incredulity,', 1), ('it', 10), ('nothing', 1), ('of', 10), ('other', 1), ('season', 2), ('spring', 1), ('the', 11), ('times,', 2), ('to', 1), ('us,', 2), ('was', 10), ('way', 1), ('we', 4), ('were', 2), ('winter', 1), ('wisdom,', 1), ('worst', 1)]
: False