1use std::collections::HashMap;
2use std::collections::LinkedList;
3
4pub fn run<'a>(from: &str, seqs_hash: HashMap<&'a str, &'a str>) -> String {
7 let mut all_matches: LinkedList<Matcher> = LinkedList::new();
8 let seqs = hash_to_vec_ordered_longest_shortest(seqs_hash);
9 let mut to_str = String::from("");
10 let mut memory = StringCache::new();
11
12 for (c_index, c) in from.char_indices() {
13 if let Some(matches) = build_matches(c_index, c, &seqs) {
15 for matcher in matches {
16 all_matches.push_back(matcher);
17 }
18 };
19
20 if !all_matches.is_empty() {
22 for matcher in &mut all_matches {
24 matcher.run(c);
25 }
26 all_matches = all_matches
27 .into_iter()
28 .filter(|matcher| match matcher.status {
29 Status::Failed => false,
30 Status::Running => true,
31 Status::Complete => true,
32 })
33 .collect();
34
35 if !all_matches.is_empty() {
36 memory.push(c);
37
38 println!("MEM PUSH: {}", c);
39 }
40
41 loop {
43 let front_op = if !all_matches.is_empty() {
45 let front: &Matcher = all_matches.front().unwrap();
46 match front.status {
47 Status::Complete => Some(all_matches.pop_front().unwrap()),
48 _ => None,
49 }
50 } else {
51 None
52 };
53 if let Some(front) = front_op {
54 all_matches = all_matches
56 .into_iter()
57 .filter(|matcher| {
58 if matcher.start_i >= front.get_clear_to_i() {
59 return true;
60 }
61 false
62 })
63 .collect();
64
65 if front.start_i > memory.get_index() {
66 let str_offset = front.start_i - memory.get_index();
67 let prev_str = memory.drain_chars(str_offset);
68 println!("MEM DRAIN PUSH: {}", prev_str);
69 to_str.push_str(&prev_str);
70 }
71
72 memory.set_index(front.end_i + 1); println!("MEM INDEX: {}", memory.start_i);
75 memory.drain_chars(front.from_seq_count);
76 to_str.push_str(front.to_seq);
77 println!("REP PUSH: {}", front.to_seq);
78 } else {
79 break;
80 }
81 }
82
83 if all_matches.is_empty() {
85 to_str.push_str(&memory.drain_all());
86 memory.set_index(c_index + 1);
87 println!("MEM INDEX: {}", memory.start_i);
88 }
89 } else {
90 memory.set_index(c_index + 1);
91 println!("MEM INDEX: {}", memory.start_i);
92 println!("MEM PUSH C: {}", c);
93 to_str.push(c);
94 }
95 println!("CHAR: {}, LOOP COUNT {}", c, c_index);
96 }
97
98 to_str
99}
100use std::ops::Add;
101
102struct StringCache {
103 s: String,
104 start_i: usize,
105}
106impl StringCache {
107 fn new() -> Self {
108 StringCache {
109 s: "".to_string(),
110 start_i: 0,
111 }
112 }
113
114 fn drain_chars(&mut self, count: usize) -> String {
115 println!("Current String: {}", self.s);
116 println!("Drain_Chars (COUNT): {}", count);
117
118 let mut ret_s: String = "".to_string();
119 let mut chars_rem: Vec<char> = self.s.clone().chars().collect();
120 let chars: Vec<char> = chars_rem.drain(..count).collect();
121
122 self.s.clear();
123 for c in chars_rem {
124 self.s.push(c);
125 }
126
127 for c in chars {
128 ret_s.push(c);
129 }
130 ret_s
131 }
132
133 fn drain_all(&mut self) -> String {
134 let ret_s = self.s.clone();
135 self.s.clear();
136 return ret_s;
137 }
138
139 fn push(&mut self, c: char) {
140 self.s.push(c);
141 }
142
143 fn clear(&mut self) {
144 self.s.clear();
145 }
146
147 fn inc_index(&mut self) {
148 self.start_i += 1;
149 }
150
151 fn inc_index_by(&mut self, num: usize) {
152 self.start_i += num;
153 }
154
155 fn set_index(&mut self, index: usize) {
156 self.start_i = index;
157 }
158
159 fn get_index(&self) -> usize {
160 return self.start_i;
161 }
162
163 fn count(&self) -> usize {
164 self.s.chars().count()
165 }
166}
167
168fn hash_to_vec_ordered_longest_shortest<'a>(
169 seqs_hash: HashMap<&'a str, &'a str>,
170) -> Vec<(&'a str, &'a str)> {
171 let mut seqs_vec: Vec<(&str, &str)> = vec![];
172 for key in seqs_hash.keys() {
173 seqs_vec.push((key, seqs_hash.get(key).unwrap()));
174 }
175 seqs_vec.sort_by(|a, b| b.0.chars().count().cmp(&a.0.chars().count()));
176
177 seqs_vec
178}
179
180enum Status {
181 Complete,
182 Running,
183 Failed,
184}
185fn build_matches<'a>(
186 start_index: usize,
187 initial_char: char,
188 seqs: &'a Vec<(&'a str, &'a str)>,
189) -> Option<Vec<Matcher>> {
190 let mut matchers: Vec<Matcher> = vec![];
191 for (from, to) in seqs {
192 if let Some(c) = from.chars().next() {
193 if c == initial_char {
194 matchers.push(Matcher::new(from, to, start_index));
195 }
196 }
197 }
198
199 if matchers.is_empty() {
200 return None;
201 }
202 return Some(matchers);
203}
204
205struct Matcher<'a> {
206 status: Status,
207 from_seq: Vec<char>,
208 to_seq: &'a str,
209 from_seq_count: usize,
210 start_i: usize,
211 end_i: usize,
212 counter: usize,
213}
214impl<'a> Matcher<'a> {
215 fn new(from_seq: &'a str, to_seq: &'a str, start_i: usize) -> Self {
216 let from_seq_count = from_seq.chars().count();
217 let from_seq: Vec<char> = from_seq.chars().collect();
218 Self {
219 status: Status::Running,
220 from_seq: from_seq,
221 to_seq: &to_seq,
222 from_seq_count: from_seq_count,
223 start_i: start_i,
224 end_i: start_i + from_seq_count - 1,
225 counter: 0,
226 }
227 }
228
229 fn run(&mut self, c: char) -> Status {
230 match self.status {
231 Status::Running => self.next(c),
232 Status::Complete => Status::Complete,
233 Status::Failed => Status::Failed, }
235 }
236
237 fn next(&mut self, c: char) -> Status {
241 if self.from_seq[self.counter] == c {
242 self.counter += 1;
243
244 if self.counter == self.from_seq.len() {
245 self.status = Status::Complete;
246 return Status::Complete;
247 }
248 return Status::Running;
249 } else {
250 self.status = Status::Failed;
251 return Status::Failed;
252 }
253 }
254
255 pub fn get_clear_to_i(&self) -> usize {
256 return self.start_i + self.from_seq_count;
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use std::collections::HashMap;
263
264 use crate::*;
265 #[test]
266 fn drain_chars() {
267 let mut sc = StringCache::new();
268 sc.s = String::from("hippo");
269 println!("Before drain: {}", sc.s);
270 let ret_s = sc.drain_chars(5);
271 println!("After drain: {}", sc.s);
272
273 assert_eq!(ret_s, "hippo");
274 }
276
277 #[test]
278 fn drain_all() {
279 let mut sc = StringCache::new();
280 sc.s = String::from("my word");
281 let ret_s = sc.drain_all();
282
283 assert_eq!(ret_s, "my word");
284 assert_eq!("".to_string(), sc.s);
285 }
286
287 #[test]
288 fn highest_complexity() {
289 let mut replacement_seqs: HashMap<&str, &str> = HashMap::new();
290 replacement_seqs.insert("a", "x");
291 replacement_seqs.insert("bbbb c dddd eX", "!NO REPLACE");
292 replacement_seqs.insert("c", "l");
293 replacement_seqs.insert("c dddd", "y");
294 replacement_seqs.insert("c dddd eeX", "!NO REPLACE");
295 replacement_seqs.insert("gg ", "z ");
296 replacement_seqs.insert("g", "r");
297 replacement_seqs.insert("hh", "END");
298 pr(&replacement_seqs);
299
300 let from_s = "a bbbb cc dddd eee f gggggg hh";
301 let expect_s = "x bbbb ly eee f rrrrz END";
302 let new_s = run(from_s, replacement_seqs);
303 println!("Orig: {}", from_s);
304 println!("New String: {:?}", new_s);
305
306 assert_eq!(expect_s, new_s);
307 }
308
309 #[test]
310 fn longest_collapse_three_shorters() {
311 let mut replacement_seqs: HashMap<&str, &str> = HashMap::new();
312 replacement_seqs.insert("wow is my fox", "mmmmmmmmm");
313 replacement_seqs.insert("wow", "aaaa");
314 replacement_seqs.insert("is", "bb");
315 replacement_seqs.insert("my", "cc");
316 pr(&replacement_seqs);
317
318 let from_s = "wow is my foo";
319 let expect_s = "aaaa bb cc foo";
320 let new_s = run(from_s, replacement_seqs);
321 println!("Orig: {}", from_s);
322 println!("New String: {:?}", new_s);
323
324 assert_eq!(expect_s, new_s);
325 }
326
327 #[test]
328 fn longest_collapse_two_shorters() {
329 let mut replacement_seqs: HashMap<&str, &str> = HashMap::new();
330 replacement_seqs.insert("wow is my fox", "mmmmmmmmm");
331 replacement_seqs.insert("is", "bb");
332 replacement_seqs.insert("my", "cc");
333 pr(&replacement_seqs);
334
335 let from_s = "wow is my foo";
336 let expect_s = "wow bb cc foo";
337 let new_s = run(from_s, replacement_seqs);
338 println!("Orig: {}", from_s);
339 println!("New String: {:?}", new_s);
340
341 assert_eq!(expect_s, new_s);
342 }
343
344 #[test]
345 fn longest_collapse_replace_shorter() {
346 let mut replacement_seqs: HashMap<&str, &str> = HashMap::new();
347 replacement_seqs.insert("present", "future");
348 replacement_seqs.insert("present txxxxx", "past");
349 pr(&replacement_seqs);
350
351 let from_s = "a present tense foo";
352 let expect_s = "a future tense foo";
353 let new_s = run(from_s, replacement_seqs);
354 println!("Orig: {}", from_s);
355 println!("New String: {:?}", new_s);
356
357 assert_eq!(expect_s, new_s);
358 }
359
360 #[test]
361 fn longest_replace() {
362 let mut replacement_seqs: HashMap<&str, &str> = HashMap::new();
363 replacement_seqs.insert("present", "future");
364 replacement_seqs.insert("present tense", "past");
365 pr(&replacement_seqs);
366
367 let from_s = "a present tense foo";
368 let expect_s = "a past foo";
369 let new_s = run(from_s, replacement_seqs);
370 println!("Orig: {}", from_s);
371 println!("New String: {:?}", new_s);
372
373 assert_eq!(expect_s, new_s);
374 }
375
376 #[test]
377 fn multiple_seperate_replace() {
378 let mut replacement_seqs: HashMap<&str, &str> = HashMap::new();
379 replacement_seqs.insert("a", "it was");
380 replacement_seqs.insert("present", "past");
381 pr(&replacement_seqs);
382
383 let from_s = "a present tense foo";
384 let expect_s = "it was past tense foo";
385 let new_s = run(from_s, replacement_seqs);
386 println!("Orig: {}", from_s);
387 println!("New String: {:?}", new_s);
388
389 assert_eq!(expect_s, new_s);
390 }
391
392 #[test]
393 fn single_replace() {
394 let mut replacement_seqs: HashMap<&str, &str> = HashMap::new();
395 replacement_seqs.insert("a", "the");
396 pr(&replacement_seqs);
397
398 let from_s = "a present tense foo";
399 let expect_s = "the present tense foo";
400 let new_s = run(from_s, replacement_seqs);
401 println!("Orig: {}", from_s);
402 println!("New String: {:?}", new_s);
403
404 assert_eq!(expect_s, new_s);
405 }
406
407 #[test]
408 fn hashmap_stays_in_order() {
409 let mut map: HashMap<&str, &str> = HashMap::new();
410 map.insert("ham", "cheese");
411 map.insert("foo", "boo");
412 assert!(map.get("ham").unwrap() == &"cheese");
413 assert!(map.keys().len() == 2);
414 }
415
416 fn pr(map: &HashMap<&str, &str>) {
417 println!("Replacements: {:?}", map);
418 }
419
420 #[test]
422 fn matcher_works() {
423 let from_match = "foo";
424 let to_match = "bar";
425 let mut sentance = "this is foo bar".chars();
426 let mut matched_str = String::from("");
427 let mut matcher: Option<Matcher> = Option::None;
428
429 let mut count = 0;
430 while let Some(c) = sentance.next() {
431 if c == 'f' {
432 matcher = Option::Some(Matcher::new(from_match, to_match, count));
433 }
434
435 let status = match matcher.as_mut() {
436 Some(m) => m.run(c),
437 None => Status::Failed,
438 };
439
440 match status {
441 Status::Running => matched_str = format!("{}{}", matched_str, c),
442 Status::Complete => {
443 matched_str = format!("{}{}", matched_str, c);
444 matcher = Option::None;
445 }
446 Status::Failed => matcher = Option::None,
447 }
448 println!("to match: {}", from_match);
449 println!("matched: {}", matched_str);
450
451 count += 1;
452 }
453
454 assert!(matched_str == from_match);
455 }
456
457 #[test]
458 pub fn hashmap_to_vector_sort_longest() {
459 let mut seqs_hash: HashMap<&str, &str> = HashMap::new();
460 seqs_hash.insert("a super duper long foo", "a super duper long bar");
461 seqs_hash.insert("fooest", "barest");
462 seqs_hash.insert("foo", "bar");
463 seqs_hash.insert("fooer", "barer");
464 seqs_hash.insert("a very long foo", "a very long foo");
465
466 let mut seqs_vec: Vec<(&str, &str)> = vec![];
467 for key in seqs_hash.keys() {
468 seqs_vec.push((key, seqs_hash.get(key).unwrap()));
469 }
470 seqs_vec.sort_by(|a, b| b.0.len().cmp(&a.0.len()));
471 println! {"{:?}", seqs_vec};
472
473 assert!(seqs_vec[0].0 == "a super duper long foo");
474 assert!(seqs_vec[1].0 == "a very long foo");
475 assert!(seqs_vec[2].0 == "fooest");
476 assert!(seqs_vec[3].0 == "fooer");
477 assert!(seqs_vec[4].0 == "foo");
478 }
479}