Skip to content

Instantly share code, notes, and snippets.

@Diti Diti/ascii-art.rs
Created Apr 13, 2019

Embed
What would you like to do?
use std::error::Error;
use std::io::{prelude::*, stdin};
type AsciiArtResult<T> = Result<T, Box<Error>>;
#[derive(Debug, Default, PartialEq)]
struct AsciiArtData {
alphabet_rows: Vec<String>,
letter_width: u8,
letter_height: u8,
sentence: String,
}
impl AsciiArtData {
fn from(reader: impl BufRead) -> AsciiArtResult<Self> {
let mut input_lines = reader.lines().map(|l| l.unwrap());
let w: u8 = input_lines
.next()
.expect("Cannot read letter width")
.trim()
.parse()
.expect("Cannot parse letter width");
let h: u8 = input_lines
.next()
.expect("Cannot read letter height")
.trim()
.parse()
.expect("Cannot parse letter height");
let txt: String = input_lines
.next()
.expect("Cannot read sentence")
.trim_end()
.to_uppercase()
.parse()
.expect("Cannot parse sentence");
let rows: Vec<String> = input_lines
.take(h as usize)
.map(|x| x.trim_end().to_owned())
.collect::<Vec<String>>();
Ok(Self {
letter_width: w,
letter_height: h,
sentence: txt,
alphabet_rows: rows,
})
}
fn process(self) -> String {
let mut text_out = String::new();
for row in self.alphabet_rows {
// FIXME: For some reason, first character of first row is already consumed
for c in self.sentence.chars() {
let letter_width = self.letter_width as usize;
let idx_start = if c.is_ascii_uppercase() {
(c as usize - 'A' as usize)
} else {
26
} * letter_width;
let substring = unsafe { row.get_unchecked(idx_start..(idx_start + letter_width)) };
text_out.push_str(substring);
}
text_out.push('\n')
}
text_out
}
}
// Try with "E", "MANHATTAN", "ManhAtTan", "M@NH@TT@N"
#[test]
fn letters_4x5_with_only_f() {
let input = b"4\n5\nE
# ## ## ## ### ### ## # # ### ## # # # # # ### # ## # ## ## ### # # # # # # # # # # ### ### \n\
# # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # # # # # # # \n\
### ## # # # ## ## # # ### # # ## # ### # # # # ## # # ## # # # # # # ### # # # ## \n\
# # # # # # # # # # # # # # # # # # # # # # # # # # ## # # # # # # # # ### # # # # \n\
# # ## ## ## ### # ## # # ### # # # ### # # # # # # # # # ## # ### # # # # # # ### # ";
let expected = "### \n\
# \n\
## \n\
# \n\
### \n";
let actual = AsciiArtData::from(&input[..]).unwrap().process();
println!("{}", actual);
assert_eq!(expected, actual);
}
#[test]
fn letters_4x5_with_uppercase_manhattan() {
let input = b"4\n5\nMANHATTAN
# ## ## ## ### ### ## # # ### ## # # # # # ### # ## # ## ## ### # # # # # # # # # # ### ### \n\
# # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # # # # # # # \n\
### ## # # # ## ## # # ### # # ## # ### # # # # ## # # ## # # # # # # ### # # # ## \n\
# # # # # # # # # # # # # # # # # # # # # # # # # # ## # # # # # # # # ### # # # # \n\
# # ## ## ## ### # ## # # ### # # # ### # # # # # # # # # ## # ### # # # # # # ### # ";
let expected = "# # # ### # # # ### ### # ### \n\
### # # # # # # # # # # # # # # \n\
### ### # # ### ### # # ### # # \n\
# # # # # # # # # # # # # # # # \n\
# # # # # # # # # # # # # # # # \n";
let actual = AsciiArtData::from(&input[..]).unwrap().process();
println!("{}", actual);
assert_eq!(expected, actual);
}
fn main() {
let stdin = stdin();
match AsciiArtData::from(stdin.lock()) {
Ok(data) => println!("{}", data.process()),
Err(err) => {
eprintln!("Input error: {}", err);
std::process::exit(1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.