main.rs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. use std::env;
  2. use std::fs::File;
  3. use std::io::BufRead;
  4. use std::io::BufReader;
  5. use std::io::Error;
  6. use std::iter::Iterator;
  7. use regex::Regex;
  8. use unidecode::unidecode;
  9. use std::collections::HashSet;
  10. #[derive(Default)]
  11. struct Dictionary{
  12. words: Vec<String>,
  13. iter_position: usize,
  14. }
  15. impl Dictionary {
  16. fn load_from_iterable(&mut self, lines: impl Iterator<Item = Result<String, Error>>) {
  17. let mut it = lines;
  18. // aux_set is used only to deduplicate
  19. // so we're still using a normal Vec, and perform deduplication at load time
  20. let mut aux_set = HashSet::new();
  21. for line in it.by_ref() {
  22. let line = line.unwrap();
  23. let word = line_to_word(line);
  24. if !aux_set.contains(&word) {
  25. //println!("Inserisco: {}", word);
  26. aux_set.insert(word.clone());
  27. self.words.push(word);
  28. }
  29. }
  30. }
  31. }
  32. impl Iterator for Dictionary{
  33. type Item = String;
  34. fn next(&mut self) -> Option<Self::Item> {
  35. if self.words.len() >= self.iter_position {
  36. None
  37. } else {
  38. let v = self.words[self.iter_position].clone();
  39. self.iter_position += 1;
  40. Some(v)
  41. }
  42. }
  43. }
  44. fn line_to_word(l: String) -> String {
  45. let l = unidecode(&l);
  46. let l = l.to_lowercase();
  47. let l = l.replace("'", "");
  48. l
  49. }
  50. // filtri {{{
  51. // i filtri dovrebbero essere creati da una struct Config{} creata parsando gli argomenti
  52. fn matches_regexp(regexp: &str) -> (impl std::ops::FnMut(&&String) -> bool) {
  53. // filtro
  54. let re = Regex::new(regexp).unwrap();
  55. move |w| re.is_match(w.as_str())
  56. }
  57. fn sort_word(word: &str) -> Result<String, impl std::error::Error> {
  58. // funzione ausiliaria, utile per la is_anagram e cose simili
  59. // ritorna una COPIA
  60. // esempio: house -> ehosu
  61. let mut w_bytes = word.to_string().clone().into_bytes();
  62. w_bytes.sort();
  63. String::from_utf8(w_bytes)
  64. }
  65. fn is_anagram(word: &str) -> (impl std::ops::FnMut(&&String) -> bool) {
  66. // filtro
  67. let sorted_word = sort_word(line_to_word(word.to_string()).as_str()).unwrap();
  68. move |w| {
  69. sorted_word == sort_word(w.as_str()).unwrap()
  70. }
  71. }
  72. // filtri }}}
  73. fn main() {
  74. let args: Vec<String> = env::args().collect();
  75. let fname = &args[1];
  76. let pattern = &args[2];
  77. let f = File::open(fname).unwrap();
  78. let buf = BufReader::new(&f);
  79. let mut d = Dictionary::default();
  80. d.load_from_iterable(buf.lines());
  81. //let filter = matches_regexp(pattern);
  82. let filter = is_anagram(pattern);
  83. for w in d.words.iter().filter(filter) {
  84. println!("{}", w)
  85. }
  86. }