use std::boxed::Box;
use std::collections::HashSet;
use std::error::Error;
use std::fmt::Display;
use std::convert::From;
use unrar::error as unrar_err;
pub mod data_size;
pub mod graph;
const NORMALIZE_MAP: &[(&[&str], &str)] = &[
(&[" —"], " -"),
(&["−", "–", "—"], "-"),
(&["\u{2009}"], " ")
];
pub type SolveResult = Result<String, SolveError>;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum NumberToFind {
Min,
Max,
}
#[derive(Debug)]
pub struct SolveError(pub Box<dyn Error>);
impl Display for SolveError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Cannot solve the problem! Reason: {}", self.0)
}
}
impl PartialEq for SolveError {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
impl From<unrar_err::UnrarError> for SolveError {
fn from(value: unrar_err::UnrarError) -> Self {
let when = match value.when {
unrar_err::When::Open => "opening archive",
unrar_err::When::Read => "reading archive",
unrar_err::When::Process => "processing archive",
};
SolveError(format!("When {}: {}", when, value).into())
}
}
impl Error for SolveError {}
impl Eq for SolveError {}
pub trait Validated {
fn valid(&self) -> Result<(), String>;
}
pub fn normalize_text(text: &str) -> String {
let mut text = text.to_string();
for (patterns, replacer) in NORMALIZE_MAP {
patterns.iter().for_each(|p| text = text.replace(p, replacer));
}
text
}
pub(crate) fn has_unique_chars(string: &str) -> bool {
let set: HashSet<char> = HashSet::from_iter(string.chars());
set.len() == string.chars().count()
}
pub(crate) fn get_repeating_chars(string: &str) -> Vec<char> {
let mut string_set: HashSet<char> = HashSet::from_iter(string.chars());
let repeating_chars: HashSet<char> = HashSet::from_iter(string.chars()
.filter(|ch| !string_set.remove(ch)));
let mut v = Vec::from_iter(repeating_chars.iter().map(|c| c.to_owned()));
v.sort();
v
}
pub(crate) fn combinations<C, I, U>(len: usize, items: U) -> Vec<C>
where
C: Default + Extend<I> + Clone,
I: Clone,
U: IntoIterator<Item = I> + Clone,
{
let mut v = vec![];
if len == 1 {
for item in items {
let mut container = C::default();
container.extend([item]);
v.push(container);
}
} else {
for combination in combinations::<C, I, U>(len - 1, items.clone()) {
for item in items.clone() {
let mut new_combination = combination.clone();
new_combination.extend([item]);
v.push(new_combination);
}
}
}
v
}