Implemented problem 10

This commit is contained in:
Egor 2024-04-16 15:46:07 +03:00
parent 5da5a2ca0a
commit e77be12ebe

View file

@ -0,0 +1,101 @@
fn main() {
let matcher = RegexMatcher::new(String::from(".*"));
println!("{}", matcher.match_str(String::from("abaaaddddcccd")));
println!();
println!("{}", matcher.match_str(String::from("abcd")));
}
// TODO: improve runtime
pub fn is_match(s: String, p: String) -> bool { RegexMatcher::new(p).match_str(s) }
#[derive(Debug, Clone)]
enum Pattern {
ZeroOrMore(char),
SameAs(String),
AnyChar,
ZeroOrMoreAny
}
struct RegexMatcher {
patterns: Vec<Pattern>
}
impl RegexMatcher {
fn new(p: String) -> RegexMatcher {
let mut patterns: Vec<Pattern> = Vec::new();
let mut buf: String = String::new();
let mut is_zero_or_more = false;
for c in p.chars().rev() {
match c {
'*' => {
is_zero_or_more = true;
}
'.' => {
if !buf.is_empty() {
patterns.push(Pattern::SameAs(buf.clone()));
buf.clear();
}
if is_zero_or_more {
patterns.push(Pattern::ZeroOrMoreAny);
is_zero_or_more = false;
} else {
patterns.push(Pattern::AnyChar);
}
}
_ => {
if is_zero_or_more {
if !buf.is_empty() {
patterns.push(Pattern::SameAs(buf.clone()));
buf.clear();
}
patterns.push(Pattern::ZeroOrMore(c));
is_zero_or_more = false;
} else {
buf.insert(0, c);
}
}
}
}
if !buf.is_empty() { patterns.push(Pattern::SameAs(buf)); }
patterns.reverse();
return Self { patterns };
}
fn match_str(&self, s: String) -> bool { Self::match_patterns(&s, &self.patterns) }
fn match_patterns(s: &str, patterns: &[Pattern]) -> bool {
if patterns.is_empty() { return s.is_empty(); }
return match &patterns[0] {
Pattern::SameAs(str) => {
if str.len() > s.len() || str != &s[0..str.len()] { return false; }
Self::match_patterns(&s[str.len()..], &patterns[1..])
}
Pattern::AnyChar => {
if s.len() < 1 { return false; }
Self::match_patterns(&s[1..], &patterns[1..])
}
Pattern::ZeroOrMore(char) => {
if s.is_empty() { return Self::match_patterns(&s, &patterns[1..]); }
let mut max_length = 0usize;
for c in s.chars() {
if c != *char { break; }
max_length += 1;
}
for length in (0..=max_length).rev() {
let result = Self::match_patterns(&s[length..], &patterns[1..]);
if result { return result; }
}
false
}
Pattern::ZeroOrMoreAny => {
if s.is_empty() { return Self::match_patterns(&s, &patterns[1..]); }
for length in (0..=s.len()).rev() {
let result = Self::match_patterns(&s[length..], &patterns[1..]);
if result { return result; }
}
false
}
}
}
}