From 75c63ff17d6dbfe158ebe2447c96eb1aa237566c Mon Sep 17 00:00:00 2001 From: AnthonyMichaelTDM <68485672+AnthonyMichaelTDM@users.noreply.github.com> Date: Mon, 18 Apr 2022 12:13:06 -0700 Subject: [PATCH 1/5] 32_diamond --- 32_Diamond/rust/Cargo.toml | 8 ++ 32_Diamond/rust/README.md | 3 + 32_Diamond/rust/src/lib.rs | 169 ++++++++++++++++++++++++++++++++++++ 32_Diamond/rust/src/main.rs | 40 +++++++++ 4 files changed, 220 insertions(+) create mode 100644 32_Diamond/rust/Cargo.toml create mode 100644 32_Diamond/rust/README.md create mode 100644 32_Diamond/rust/src/lib.rs create mode 100644 32_Diamond/rust/src/main.rs diff --git a/32_Diamond/rust/Cargo.toml b/32_Diamond/rust/Cargo.toml new file mode 100644 index 00000000..1ec69633 --- /dev/null +++ b/32_Diamond/rust/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/32_Diamond/rust/README.md b/32_Diamond/rust/README.md new file mode 100644 index 00000000..f84e546c --- /dev/null +++ b/32_Diamond/rust/README.md @@ -0,0 +1,3 @@ +Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) + +Conversion to [Rust](https://www.rust-lang.org/) by Anthony Rubick [AnthonyMichaelTDM](https://github.com/AnthonyMichaelTDM) \ No newline at end of file diff --git a/32_Diamond/rust/src/lib.rs b/32_Diamond/rust/src/lib.rs new file mode 100644 index 00000000..0d820562 --- /dev/null +++ b/32_Diamond/rust/src/lib.rs @@ -0,0 +1,169 @@ +/* + lib.rs contains all the logic of the program +*/ + +use std::{error::Error, fmt::Display, str::FromStr, io::{self, Write}}; + +const LINE_WIDTH:usize = 60; +const EDGE: &str = "C"; +const EDGE_WIDTH: usize = 2; +const FILL: &str = "!"; + +/// handles setup for the game +pub struct Config { + diamond_size: usize, +} +impl Config { + /// creates and returns a new Config from user input + pub fn new() -> Result> { + //DATA + let mut config: Config = Config { diamond_size: 0 }; + + //get data from user input + + //get num players + println!("FOR A PRETTY DIAMOND PATTERN,"); + //input looop + config.diamond_size = loop { + match get_number_from_input("TYPE IN AN ODD NUMBER BETWEEN 5 AND 21 ", 5, 21) { + Ok(num) => break num, + Err(e) => { + eprintln!("{}",e); + continue; + }, + } + }; + + //return new config + return Ok(config); + } +} + +/// run the program +pub fn run(config: &Config) -> Result<(), Box> { + //DATA + let diamonds = LINE_WIDTH / config.diamond_size; + let mut line: String; + + //print out diamond + for i in 1..diamonds { + let mut x = 1; + let mut y = config.diamond_size.clone(); + for n in x..y { + line = String::new(); + + //add (diamond size - n) / 2 spaces + line += &n_spaces( (config.diamond_size - n) / 2); + + for m in 1..diamonds { + let mut c = 1; + + for a in 1..n { + if c > EDGE_WIDTH { + line += FILL; + } else { + line += EDGE; + c = c + 1; + } + } + + //53 + } + + + + + //print line + println!("{}", line); + } + } + + + //return to main + Ok(()) +} + +/// returns n spaces in a string +fn n_spaces(n:usize) -> String { + let mut output = String::new(); + + for _i in 0..n { + output += " "; + } + + output +} + + +/// gets a string from user input +fn get_string_from_user_input(prompt: &str) -> Result> { + //DATA + let mut raw_input = String::new(); + + //print prompt + print!("{}", prompt); + //make sure it's printed before getting input + io::stdout().flush().unwrap(); + + //read user input from standard input, and store it to raw_input, then return it or an error as needed + raw_input.clear(); //clear input + match io::stdin().read_line(&mut raw_input) { + Ok(_num_bytes_read) => return Ok(String::from(raw_input.trim())), + Err(err) => return Err(format!("ERROR: CANNOT READ INPUT!: {}", err).into()), + } +} + +/// generic function to get a number from the passed string (user input) +/// pass a min lower than the max to have minimun and maximun bounds +/// pass a min higher than the max to only have a minumum bound +/// pass a min equal to the max to only have a maximun bound +/// +/// Errors: +/// no number on user input +fn get_number_from_input(prompt: &str, min:T, max:T) -> Result> { + //DATA + let raw_input: String; + let processed_input: String; + + + //input looop + raw_input = loop { + match get_string_from_user_input(prompt) { + Ok(input) => break input, + Err(e) => { + eprintln!("{}",e); + continue; + }, + } + }; + + //filter out num-numeric characters from user input + processed_input = raw_input.chars().filter(|c| c.is_numeric()).collect(); + + //from input, try to read a number + match processed_input.trim().parse() { + Ok(i) => { + //what bounds must the input fall into + if min < max { //have a min and max bound: [min,max] + if i >= min && i <= max {//is input valid, within bounds + return Ok(i); //exit the loop with the value i, returning it + } else { //print error message specific to this case + return Err(format!("ONLY BETWEEN {} AND {}, PLEASE!", min, max).into()); + } + } else if min > max { //only a min bound: [min, infinity) + if i >= min { + return Ok(i); + } else { + return Err(format!("NO LESS THAN {}, PLEASE!", min).into()); + } + } else { //only a max bound: (-infinity, max] + if i <= max { + return Ok(i); + } else { + return Err(format!("NO MORE THAN {}, PLEASE!", max).into()); + } + } + }, + Err(_e) => return Err(format!("Error: couldn't find a valid number in {}",raw_input).into()), + } +} \ No newline at end of file diff --git a/32_Diamond/rust/src/main.rs b/32_Diamond/rust/src/main.rs new file mode 100644 index 00000000..8aab7350 --- /dev/null +++ b/32_Diamond/rust/src/main.rs @@ -0,0 +1,40 @@ +use std::process; //allows for some better error handling + +mod lib; +use lib::Config; + +/// main function +/// responsibilities: +/// - Calling the command line logic with the argument values +/// - Setting up any other configuration +/// - Calling a run function in lib.rs +/// - Handling the error if run returns an error +fn main() { + //greet user + welcome(); + + // set up other configuration + let config = Config::new().unwrap_or_else(|err| { + eprintln!("Problem configuring program: {}", err); + process::exit(1); + }); + + // run the program + if let Err(e) = lib::run(&config) { + eprintln!("Application Error: {}", e); //use the eprintln! macro to output to standard error + process::exit(1); //exit the program with an error code + } + + //end of program + println!("THANKS FOR PLAYING!"); +} + +/// welcome message +fn welcome() { + print!(" + DIAMOND + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + "); +} From bfbc4b743f9ab680cb358899b2aaed8d1924bb72 Mon Sep 17 00:00:00 2001 From: AnthonyMichaelTDM <68485672+AnthonyMichaelTDM@users.noreply.github.com> Date: Mon, 18 Apr 2022 13:24:41 -0700 Subject: [PATCH 2/5] progress on 32_diamond next step: inset newline character every LINE_WIDTH characters --- 32_Diamond/rust/src/lib.rs | 106 +++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/32_Diamond/rust/src/lib.rs b/32_Diamond/rust/src/lib.rs index 0d820562..b86adb2e 100644 --- a/32_Diamond/rust/src/lib.rs +++ b/32_Diamond/rust/src/lib.rs @@ -4,14 +4,14 @@ use std::{error::Error, fmt::Display, str::FromStr, io::{self, Write}}; -const LINE_WIDTH:usize = 60; +const LINE_WIDTH: isize = 60; const EDGE: &str = "C"; -const EDGE_WIDTH: usize = 2; +const EDGE_WIDTH: isize = 2; const FILL: &str = "!"; /// handles setup for the game pub struct Config { - diamond_size: usize, + diamond_size: isize, } impl Config { /// creates and returns a new Config from user input @@ -26,7 +26,11 @@ impl Config { //input looop config.diamond_size = loop { match get_number_from_input("TYPE IN AN ODD NUMBER BETWEEN 5 AND 21 ", 5, 21) { - Ok(num) => break num, + Ok(num) => { + //ensure num is odd + if num%2 == 0 {continue;} + else {break num;} + }, Err(e) => { eprintln!("{}",e); continue; @@ -43,48 +47,72 @@ impl Config { pub fn run(config: &Config) -> Result<(), Box> { //DATA let diamonds = LINE_WIDTH / config.diamond_size; - let mut line: String; - - //print out diamond - for i in 1..diamonds { - let mut x = 1; - let mut y = config.diamond_size.clone(); - for n in x..y { - line = String::new(); - - //add (diamond size - n) / 2 spaces - line += &n_spaces( (config.diamond_size - n) / 2); - - for m in 1..diamonds { - let mut c = 1; - - for a in 1..n { - if c > EDGE_WIDTH { - line += FILL; - } else { - line += EDGE; - c = c + 1; - } - } - - //53 - } - - - - - //print line - println!("{}", line); - } - } + //print out diamonds + print_diamonds(config.diamond_size, diamonds); //return to main Ok(()) } +/// prints a diamond +fn print_diamonds(width:isize, count:isize) { + //DATA + let mut line: String = String::new(); +/* +8 FOR L=1 TO width + 10 X=1:Y=count:Z=2 + 20 FOR N=X TO Y STEP Z + 25 PRINT TAB((count-N)/2); + 28 FOR M=1 TO width + 29 C=1 + 30 FOR A=1 TO N + 32 IF C>LEN(A$) THEN PRINT "!";:GOTO 50 + 34 PRINT MID$(A$,C,1); + 36 C=C+1 + 50 NEXT A + 53 IF M=width THEN 60 + 55 PRINT TAB(count*M+(count-N)/2); + 56 NEXT M + 60 PRINT + 70 NEXT N (n+=Z) + 83 IF X<>1 THEN 95 + 85 X=count-2:Y=1:Z=-2 + 90 GOTO 20 +95 NEXT L +99 END +*/ + let mut x = 1; + let mut y = count; + let mut step = 2; + let mut l =1; + while l < width { + let mut n = x; + while n <= y { + line+= &n_spaces( (count-n) / 2); + for m in 1..width { + for c in 1..n { + line += if c > EDGE_WIDTH {FILL} else {EDGE}; + } + + line += &n_spaces(count*m+(count-n)/2); + } + n += step; + } + if x != 1 {l+=1;continue;} + x = count - 2; + y = 1; + step = -2; + } + //separate line by LINE_WIDTH or whatever + println!("{}", line); + + +} + + /// returns n spaces in a string -fn n_spaces(n:usize) -> String { +fn n_spaces(n:isize) -> String { let mut output = String::new(); for _i in 0..n { From f8fa6fec782f12955bb9983abec87eff166e60a3 Mon Sep 17 00:00:00 2001 From: AnthonyMichaelTDM <68485672+AnthonyMichaelTDM@users.noreply.github.com> Date: Mon, 18 Apr 2022 13:28:25 -0700 Subject: [PATCH 3/5] still not working hmmm --- 32_Diamond/rust/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/32_Diamond/rust/src/lib.rs b/32_Diamond/rust/src/lib.rs index b86adb2e..17aa2e0c 100644 --- a/32_Diamond/rust/src/lib.rs +++ b/32_Diamond/rust/src/lib.rs @@ -105,7 +105,12 @@ fn print_diamonds(width:isize, count:isize) { step = -2; } //separate line by LINE_WIDTH or whatever - println!("{}", line); + while line.len() >= LINE_WIDTH as usize { + let line_parts = line.split_at(LINE_WIDTH as usize); + println!("{}",line_parts.0); + + line = String::from(line_parts.1); + } } From 733513c1568e381a68bfe2d4f6596de21966f070 Mon Sep 17 00:00:00 2001 From: AnthonyMichaelTDM <68485672+AnthonyMichaelTDM@users.noreply.github.com> Date: Fri, 22 Apr 2022 13:02:52 -0700 Subject: [PATCH 4/5] finished 32_diamond --- 32_Diamond/rust/src/lib.rs | 108 +++++++++++++++---------------------- 1 file changed, 43 insertions(+), 65 deletions(-) diff --git a/32_Diamond/rust/src/lib.rs b/32_Diamond/rust/src/lib.rs index 17aa2e0c..428cd9e9 100644 --- a/32_Diamond/rust/src/lib.rs +++ b/32_Diamond/rust/src/lib.rs @@ -4,11 +4,6 @@ use std::{error::Error, fmt::Display, str::FromStr, io::{self, Write}}; -const LINE_WIDTH: isize = 60; -const EDGE: &str = "C"; -const EDGE_WIDTH: isize = 2; -const FILL: &str = "!"; - /// handles setup for the game pub struct Config { diamond_size: isize, @@ -46,82 +41,65 @@ impl Config { /// run the program pub fn run(config: &Config) -> Result<(), Box> { //DATA - let diamonds = LINE_WIDTH / config.diamond_size; + let line_width: isize = 60; + let padding: char = 'C'; + let pixel_width: isize = 2; + let filling: char = '!'; + let border: char = '#'; + + //print top border + println!("{}", n_chars(line_width+2, border)); //print out diamonds - print_diamonds(config.diamond_size, diamonds); + for row in 0..(line_width/pixel_width) { + print_diamond_line(config.diamond_size, row, line_width, pixel_width, padding, filling, border); + } + + //print bottom border + println!("{}", n_chars(line_width+2, border)); //return to main Ok(()) } -/// prints a diamond -fn print_diamonds(width:isize, count:isize) { +/// prints the next line of diamonds +fn print_diamond_line(diamond_width: isize,row: isize, line_width:isize, pixel_width:isize, padding:char, filling:char, border:char) { //DATA - let mut line: String = String::new(); -/* -8 FOR L=1 TO width - 10 X=1:Y=count:Z=2 - 20 FOR N=X TO Y STEP Z - 25 PRINT TAB((count-N)/2); - 28 FOR M=1 TO width - 29 C=1 - 30 FOR A=1 TO N - 32 IF C>LEN(A$) THEN PRINT "!";:GOTO 50 - 34 PRINT MID$(A$,C,1); - 36 C=C+1 - 50 NEXT A - 53 IF M=width THEN 60 - 55 PRINT TAB(count*M+(count-N)/2); - 56 NEXT M - 60 PRINT - 70 NEXT N (n+=Z) - 83 IF X<>1 THEN 95 - 85 X=count-2:Y=1:Z=-2 - 90 GOTO 20 -95 NEXT L -99 END -*/ - let mut x = 1; - let mut y = count; - let mut step = 2; - let mut l =1; - while l < width { - let mut n = x; - while n <= y { - line+= &n_spaces( (count-n) / 2); - for m in 1..width { - for c in 1..n { - line += if c > EDGE_WIDTH {FILL} else {EDGE}; - } - - line += &n_spaces(count*m+(count-n)/2); - } - n += step; - } - if x != 1 {l+=1;continue;} - x = count - 2; - y = 1; - step = -2; - } - //separate line by LINE_WIDTH or whatever - while line.len() >= LINE_WIDTH as usize { - let line_parts = line.split_at(LINE_WIDTH as usize); - println!("{}",line_parts.0); + let diamonds_per_row = (line_width/pixel_width) / diamond_width; + //let row = row % (diamonds_per_row - 1); + let padding_amount; //total amount of padding before and after the filling of each diamond in this row + let filling_amount; //amount of "diamond" in each diamond in this row - line = String::from(line_parts.1); + //calculate padding + padding_amount = (2 * ( (row%(diamond_width-1)) - (diamond_width/2))).abs(); + //calculate filling + filling_amount = -padding_amount + diamond_width; + + //print border before every row + print!("{}", border); + + //for every diamond in this row: + for _diamond in 0..diamonds_per_row { + //print leading padding + print!("{}", n_chars( pixel_width * padding_amount/2, padding ) ); + //print filling + print!("{}", n_chars( pixel_width * filling_amount , filling ) ); + //print trailing padding + print!("{}", n_chars( pixel_width * padding_amount/2, padding ) ); } - + //print border after every row + print!("{}", border); + //new line + println!(""); } - -/// returns n spaces in a string -fn n_spaces(n:isize) -> String { +/// returns n of the passed character, put into a string +fn n_chars(n:isize, character: char) -> String { let mut output = String::new(); for _i in 0..n { - output += " "; + output.push(character); } output From 69e9c1438e70e1a76955306bdcc09d1c16e2f1da Mon Sep 17 00:00:00 2001 From: AnthonyMichaelTDM <68485672+AnthonyMichaelTDM@users.noreply.github.com> Date: Fri, 22 Apr 2022 13:27:06 -0700 Subject: [PATCH 5/5] bit of modification to match description of readme --- 32_Diamond/rust/src/lib.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/32_Diamond/rust/src/lib.rs b/32_Diamond/rust/src/lib.rs index 428cd9e9..3d2692c6 100644 --- a/32_Diamond/rust/src/lib.rs +++ b/32_Diamond/rust/src/lib.rs @@ -20,7 +20,7 @@ impl Config { println!("FOR A PRETTY DIAMOND PATTERN,"); //input looop config.diamond_size = loop { - match get_number_from_input("TYPE IN AN ODD NUMBER BETWEEN 5 AND 21 ", 5, 21) { + match get_number_from_input("TYPE IN AN ODD NUMBER BETWEEN 5 AND 31 ", 5, 31) { Ok(num) => { //ensure num is odd if num%2 == 0 {continue;} @@ -43,20 +43,22 @@ pub fn run(config: &Config) -> Result<(), Box> { //DATA let line_width: isize = 60; let padding: char = 'C'; - let pixel_width: isize = 2; + let pixel_width: isize = 1; let filling: char = '!'; let border: char = '#'; + let width_of_full_diamonds_in_line = (line_width/config.diamond_size) * config.diamond_size; + //print top border - println!("{}", n_chars(line_width+2, border)); + println!("{}", n_chars(width_of_full_diamonds_in_line+2, border)); //print out diamonds - for row in 0..(line_width/pixel_width) { + for row in 0..width_of_full_diamonds_in_line { print_diamond_line(config.diamond_size, row, line_width, pixel_width, padding, filling, border); } //print bottom border - println!("{}", n_chars(line_width+2, border)); + println!("{}", n_chars(width_of_full_diamonds_in_line+2, border)); //return to main Ok(())