2025-05-27 22:26:05 -05:00
|
|
|
use std::error::Error;
|
|
|
|
|
use std::fmt::Display;
|
|
|
|
|
use std::fs::File;
|
|
|
|
|
use std::io::{BufReader, prelude::*};
|
2025-05-28 17:01:56 -05:00
|
|
|
|
2025-05-27 22:26:05 -05:00
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Crossword {
|
|
|
|
|
data: Vec<Vec<char>>,
|
|
|
|
|
width: usize,
|
|
|
|
|
height: usize,
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-28 17:01:56 -05:00
|
|
|
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 {
|
2025-05-28 17:03:20 -05:00
|
|
|
let x = self.x as isize + (i as isize * self.direction.0);
|
|
|
|
|
let y = self.y as isize + (i as isize * self.direction.1);
|
2025-05-28 17:01:56 -05:00
|
|
|
word.push(self.crossword.data[x as usize][y as usize]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
word
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-27 22:26:05 -05:00
|
|
|
impl Crossword {
|
|
|
|
|
pub fn new(file: File) -> Result<Crossword, Box<dyn Error>> {
|
|
|
|
|
let mut input_buffer = BufReader::new(file);
|
|
|
|
|
|
|
|
|
|
let mut data: Vec<Vec<char>> = 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
|
|
|
|
|
}
|
2025-05-28 17:01:56 -05:00
|
|
|
|
2025-05-28 17:03:20 -05:00
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-27 22:26:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(())
|
|
|
|
|
}
|
|
|
|
|
}
|