use std::error::Error; use std::fmt::Display; use std::fs::File; use std::io::{BufReader, prelude::*}; #[derive(Debug)] pub struct Crossword { data: Vec>, width: usize, height: usize, } pub struct WordPuller<'a> { x: usize, y: usize, direction: (isize, isize), crossword: &'a Crossword, } impl<'a> WordPuller<'a> { pub fn take(&self, num_of_letters: usize) -> String { let mut word = String::new(); for i in 0..num_of_letters { let x = self.x as isize + (i as isize * self.direction.0); let y = self.y as isize + (i as isize * self.direction.1); word.push(self.crossword.data[x as usize][y as usize]); } word } } impl Crossword { pub fn new(file: File) -> Result> { let mut input_buffer = BufReader::new(file); let mut data: Vec> = Vec::new(); let mut first_line = String::new(); input_buffer.read_line(&mut first_line)?; let first_line = first_line.trim_end().to_owned(); let width = first_line.len(); for line in input_buffer.lines() { let line = line?; if line.len() != width { println!("{}", line); Err("Line length of input are not consistent")?; } data.push(line.chars().collect()); } let height = data.len(); Ok(Crossword { data, width, height, }) } pub fn width(&self) -> usize { self.width } pub fn height(&self) -> usize { self.height } pub fn n(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (-1, 0), crossword: self, } } pub fn ne(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (-1, 1), crossword: self, } } pub fn e(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (0, 1), crossword: self, } } pub fn se(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (1, 1), crossword: self, } } pub fn s(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (1, 0), crossword: self, } } pub fn sw(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (1, -1), crossword: self, } } pub fn w(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (0, -1), crossword: self, } } pub fn nw(&self, x: usize, y: usize) -> WordPuller { WordPuller { x, y, direction: (-1, -1), crossword: self, } } } impl Display for Crossword { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for row in &self.data { let row = String::from_iter(row.iter()); writeln!(f, "{}", row)?; } Ok(()) } }