Skip to content

Instantly share code, notes, and snippets.

@fallwith
Last active December 28, 2020 07:39
Show Gist options
  • Save fallwith/c48431f520904b7656298c47dcc6882c to your computer and use it in GitHub Desktop.
Save fallwith/c48431f520904b7656298c47dcc6882c to your computer and use it in GitHub Desktop.
A Rust attempt at a Ruby challenge
use chrono::{DateTime, Local};
use std::collections::HashMap;
use std::env;
use std::process;
use std::time::SystemTime;
const VERSION: &str = "0.1.0";
// a Rust attempt at the following Ruby coding challenge:
// https://gist.github.com/fallwith/00aa5f7a0d5c192e91fa6468e7434048
fn main() {
let start_time = SystemTime::now();
let args: Vec<String> = env::args().collect();
let input = process_cli_args(&args);
let mut processor = PeanutsProcessor {
// 2.
names: input.split('|').map(String::from).collect(),
};
// 3.
processor.add_name(String::from("Franklin"));
processor.add_name(String::from("Sally"));
// 4.
processor.remove_last_name();
// 5.
let l_count = processor.starts_with_count(String::from("L"));
// 6.
let over_4_count = processor.over_n_count(4);
// 7.
let substring_matches_included_list = processor.names.clone();
let unwanted_substring = String::from("ie");
processor.remove_having_substring(unwanted_substring.clone());
let substring_matches_removed_list = processor.names.clone();
// 8
processor.sort_names();
// 9.
let seen_counts = processor.seen_counts();
// 10.
processor.dedup_names();
// 11.
let labeled_list = processor.labeled_list();
println!("{}", labeled_list);
// 12.
let semicoloned_peanuts = processor.delimit_names(String::from(";"));
// 13.
let datetime: DateTime<Local> = start_time.into();
println!();
println!(
"Program started at {}",
datetime.format("%m/%d/%y at %I:%M %p")
);
println!("Program version = {}", VERSION);
println!("Original delimited string: '{}'", input);
println!("'L' name count is {}", l_count);
println!("Over 4 characters name count is {}", over_4_count);
println!("Unwanted substring = '{}'", unwanted_substring);
println!(
"List before removing substring matches: '{}'",
substring_matches_included_list.join("|")
);
println!(
"List after removing substring matches: '{}'",
substring_matches_removed_list.join("|")
);
println!("Number of times each name appears:");
for (name, count) in seen_counts {
println!("{} => {}", name, count);
}
println!(
"Sorted, substring filtered, de-duped list with English word labels:\n{}",
labeled_list
);
println!("New delimited string: {}", semicoloned_peanuts);
match start_time.elapsed() {
Ok(elapsed) => {
println!(
"Elapsed time: {:.3} secs",
(elapsed.as_millis() as f64) / 1000.0
);
}
Err(e) => {
println!("Failed to determine elapsed time! - {:?}", e);
}
}
}
// 16.
pub fn process_cli_args(args: &[String]) -> String {
for arg in args {
if arg == "-h" || arg == "--help" {
println!(
"Usage: {}\n\n\tor:\n\n{} Name1 Name2 Name3",
args[0], args[0]
);
process::exit(0);
} else if arg == "-v" || arg == "--version" {
println!("Version: {}", VERSION);
process::exit(0);
} else if arg.starts_with('-') {
panic!("Unexpected argument '{}'", arg)
}
}
match args.len() {
// 1.
1 => String::from("Charlie|Snoopy|Linus|Lucy|Linus|Pigpen|Snoopy|Linus|Woodstock|Frieda"),
// 14.
2..=3 => {
panic!("Too few names - please provide 4 to 10 names or none for the default list")
}
4..=11 => args[1..].join("|"),
_ => panic!("Too many names - please provide 4 to 10 names or none for the default list"),
}
}
// 15. sorta, no classes in Rust
struct PeanutsProcessor {
names: Vec<String>,
}
impl PeanutsProcessor {
fn add_name(&mut self, name: String) {
self.names.push(name);
}
fn remove_last_name(&mut self) {
self.names.pop();
}
fn starts_with_count(&mut self, initial: String) -> u32 {
let mut count: u32 = 0;
for name in &self.names {
if name.starts_with(&initial) {
count += 1;
}
}
count
}
fn over_n_count(&mut self, threshold: usize) -> u32 {
let mut count: u32 = 0;
for name in &self.names {
if name.chars().count() > threshold {
count += 1;
}
}
count
}
fn remove_having_substring(&mut self, substring: String) {
&self.names.retain(|name| !name.contains(&substring));
}
fn sort_names(&mut self) {
self.names.sort();
}
fn seen_counts(&mut self) -> HashMap<String, u32> {
let mut counts: HashMap<String, u32> = HashMap::new();
for name in &self.names {
let count = counts.entry(name.to_string()).or_insert(0);
*count += 1;
}
counts
}
fn dedup_names(&mut self) {
self.names.dedup();
}
fn labeled_list(&mut self) -> String {
let english_number_words: HashMap<usize, &str> = [
(1, "One"),
(2, "Two"),
(3, "Three"),
(4, "Four"),
(5, "Five"),
(6, "Six"),
(7, "Seven"),
(8, "Eight"),
(9, "Nine"),
(10, "Ten"),
(11, "Eleven"), // input max is 10, 2 get added, and 1 gets removed
]
.iter()
.cloned()
.collect();
let mut list: String = String::new();
for (idx, name) in self.names.iter().enumerate() {
let formatted = format!("Item {}:\t{}\n", english_number_words[&(idx + 1)], name);
list = format!("{}{}", list, formatted);
}
list.pop();
list
}
fn delimit_names(&mut self, delimiter: String) -> String {
self.names.join(&delimiter)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment