inflect_rs/
inflect_rs.rs

1use std::collections::{ HashMap, HashSet };
2use regex::Regex;
3
4/// Encloses a string 's' in a non-capturing group.
5pub fn enclose(s: &str) -> String {
6    format!("(?:{})", s)
7}
8
9/// Joins the stem of each word in 'words' into a string for Regex.
10pub fn joinstem(cutpoint: Option<i32>, words: Option<Vec<String>>) -> String {
11    let words = words.unwrap_or_else(|| Vec::new());
12    let stem = words
13        .iter()
14        .map(|w| {
15            if let Some(c) = cutpoint {
16                if c < 0 { &w[..w.len() - (-c as usize)] } else { &w[..c as usize] }
17            } else {
18                w
19            }
20        })
21        .collect::<Vec<&str>>()
22        .join("|");
23    enclose(&stem)
24}
25
26/// From a list of words, returns a HashMap of HashSets of words, keyed by word length.
27pub fn bysize(words: Vec<String>) -> HashMap<usize, HashSet<String>> {
28    let mut res: HashMap<usize, HashSet<String>> = HashMap::new();
29    for word in words {
30        let len = word.len();
31        let entry = res.entry(len).or_insert_with(HashSet::new);
32        entry.insert(word.to_string());
33    }
34    res
35}
36
37pub fn make_pl_si_lists(
38    list: Vec<String>,
39    pl_ending: &str,
40    si_ending_size: Option<i32>,
41    do_joinstem: bool
42) -> (Vec<String>, HashMap<usize, HashSet<String>>, HashMap<usize, HashSet<String>>, String) {
43    let si_ending_size = si_ending_size.map(|size| -size);
44    let si_list: Vec<String> = list
45        .iter()
46        .map(|w| {
47            if let Some(size) = si_ending_size {
48                format!("{}{}", &w[..w.len() - (size as usize)], pl_ending)
49            } else {
50                format!("{}{}", w, pl_ending)
51            }
52        })
53        .collect();
54    let pl_bysize = bysize(list.clone());
55    let si_bysize = bysize(si_list.clone());
56    if do_joinstem {
57        let stem = joinstem(si_ending_size, Some(list));
58        (si_list, si_bysize, pl_bysize, stem)
59    } else {
60        (si_list, si_bysize, pl_bysize, String::new())
61    }
62}
63
64fn pl_sb_irregular_s() -> HashMap<String, String> {
65    return vec![
66        ("corpus", "corpuses|corpora"),
67        ("opus", "opuses|opera"),
68        ("genus", "genera"),
69        ("mythos", "mythoi"),
70        ("penis", "penises|penes"),
71        ("testis", "testes"),
72        ("atlas", "atlases|atlantes"),
73        ("yes", "yeses")
74    ]
75        .iter()
76        .map(|(k, v)| (k.to_string(), v.to_string()))
77        .collect();
78}
79
80fn pl_sb_irregular() -> HashMap<String, String> {
81    let mut pl_sb_irregular: HashMap<String, String> = vec![
82        ("child", "children"),
83        ("chili", "chilis|chilies"),
84        ("brother", "brothers|brethren"),
85        ("infinity", "infinities|infinity"),
86        ("loaf", "loaves"),
87        ("lore", "lores|lore"),
88        ("hoof", "hoofs|hooves"),
89        ("beef", "beefs|beeves"),
90        ("thief", "thiefs|thieves"),
91        ("money", "monies"),
92        ("mongoose", "mongooses"),
93        ("ox", "oxen"),
94        ("cow", "cows|kine"),
95        ("graffito", "graffiti"),
96        ("octopus", "octopuses|octopodes"),
97        ("genie", "genies|genii"),
98        ("ganglion", "ganglions|ganglia"),
99        ("trilby", "trilbys"),
100        ("turf", "turfs|turves"),
101        ("numen", "numina"),
102        ("atman", "atmas"),
103        ("occiput", "occiputs|occipita"),
104        ("sabretooth", "sabretooths"),
105        ("sabertooth", "sabertooths"),
106        ("lowlife", "lowlifes"),
107        ("flatfoot", "flatfoots"),
108        ("tenderfoot", "tenderfoots"),
109        ("romany", "romanies"),
110        ("jerry", "jerries"),
111        ("mary", "maries"),
112        ("talouse", "talouses"),
113        ("rom", "roma"),
114        ("carmen", "carmina")
115    ]
116        .iter()
117        .map(|(k, v)| (k.to_string(), v.to_string()))
118        .collect();
119    pl_sb_irregular.extend(pl_sb_irregular_s());
120    pl_sb_irregular
121}
122
123fn pl_sb_irregular_caps() -> HashMap<&'static str, &'static str> {
124    return vec![("Romany", "Romanies"), ("Jerry", "Jerrys"), ("Mary", "Marys"), ("Rom", "Roma")]
125        .into_iter()
126        .collect();
127}
128
129fn pl_sb_irregular_compound() -> HashMap<&'static str, &'static str> {
130    return vec![("prima donna", "prima donnas|prime donne")].into_iter().collect();
131}
132
133fn si_sb_irregular() -> HashMap<String, String> {
134    let mut si_sb_irregular: HashMap<String, String> = pl_sb_irregular()
135        .into_iter()
136        .map(|(k, v)| (v, k))
137        .collect();
138    let mut keys_to_remove = Vec::new();
139    let keys: Vec<String> = si_sb_irregular.keys().cloned().collect();
140    for k in keys.iter() {
141        if k.contains('|') {
142            keys_to_remove.push(k);
143        }
144    }
145    for k in keys_to_remove {
146        si_sb_irregular.remove(k);
147        let (k1, k2) = k.split_once('|').unwrap();
148        si_sb_irregular.insert(k1.to_string(), k.clone());
149        si_sb_irregular.insert(k2.to_string(), k.clone());
150    }
151    si_sb_irregular
152}
153
154fn si_sb_irregular_caps() -> HashMap<&'static str, &'static str> {
155    return pl_sb_irregular_caps()
156        .iter()
157        .map(|(&k, &v)| (v, k))
158        .collect();
159}
160
161fn si_sb_irregular_compound() -> HashMap<&'static str, &'static str> {
162    let mut si_sb_irregular_compound: HashMap<&str, &str> = pl_sb_irregular_compound()
163        .iter()
164        .map(|(&k, &v)| (v, k))
165        .collect();
166    let mut keys_to_remove = Vec::new();
167    for &k in si_sb_irregular_compound.keys() {
168        if k.contains('|') {
169            keys_to_remove.push(k);
170        }
171    }
172    for k in keys_to_remove {
173        si_sb_irregular_compound.remove(&k);
174        let (k1, k2) = k.split_once('|').unwrap();
175        si_sb_irregular_compound.insert(k1, k);
176        si_sb_irregular_compound.insert(k2, k);
177    }
178    si_sb_irregular_compound
179}
180
181fn pl_sb_z_zes_list() -> Vec<String> {
182    return vec!["quartz", "topaz"]
183        .iter()
184        .map(|s| s.to_string())
185        .collect();
186}
187
188fn pl_sb_z_zes_bysize() -> HashMap<usize, HashSet<String>> {
189    return bysize(pl_sb_z_zes_list());
190}
191
192fn sb_ze_zes_list() -> Vec<String> {
193    return vec!["snooze"]
194        .iter()
195        .map(|s| s.to_string())
196        .collect();
197}
198
199fn sb_ze_zes_bysize() -> HashMap<usize, HashSet<String>> {
200    return bysize(sb_ze_zes_list());
201}
202
203fn pl_sb_c_is_ides_complete() -> Vec<String> {
204    return vec!["ephemeris", "iris", "clitoris", "chrysalis", "epididymis"]
205        .iter()
206        .map(|s| s.to_string())
207        .collect();
208}
209
210fn pl_sb_c_is_ides_endings() -> Vec<String> {
211    return vec!["itis"]
212        .iter()
213        .map(|s| s.to_string())
214        .collect();
215}
216
217fn pl_sb_c_is_ides() -> String {
218    let pl_sb_c_is_ides: Vec<String> = pl_sb_c_is_ides_complete()
219        .iter()
220        .map(|s| s.to_string())
221        .chain(
222            pl_sb_c_is_ides_endings()
223                .into_iter()
224                .map(|w| format!(".*{}", w))
225        )
226        .collect();
227    return joinstem(Some(-2), Some(pl_sb_c_is_ides));
228}
229
230fn pl_sb_c_is_ides_list() -> Vec<String> {
231    let mut pl_sb_c_is_ides_complete = pl_sb_c_is_ides_complete();
232    pl_sb_c_is_ides_complete.append(&mut pl_sb_c_is_ides_endings());
233    pl_sb_c_is_ides_complete
234}
235
236fn si_sb_c_is_ides_list() -> Vec<String> {
237    return make_pl_si_lists(pl_sb_c_is_ides_list(), "ides", Some(2), false).0;
238}
239
240fn si_sb_c_is_ides_bysize() -> HashMap<usize, HashSet<String>> {
241    return make_pl_si_lists(pl_sb_c_is_ides_list(), "ides", Some(2), false).1;
242}
243
244fn pl_sb_c_is_ides_bysize() -> HashMap<usize, HashSet<String>> {
245    return make_pl_si_lists(pl_sb_c_is_ides_list(), "ides", Some(2), false).2;
246}
247
248fn pl_sb_c_a_ata_list() -> Vec<String> {
249    return vec![
250        "anathema",
251        "bema",
252        "carcinoma",
253        "charisma",
254        "diploma",
255        "dogma",
256        "drama",
257        "edema",
258        "enema",
259        "enigma",
260        "lemma",
261        "lymphoma",
262        "magma",
263        "melisma",
264        "miasma",
265        "oedema",
266        "sarcoma",
267        "schema",
268        "soma",
269        "stigma",
270        "stoma",
271        "trauma",
272        "gumma",
273        "pragma"
274    ]
275        .iter()
276        .map(|s| s.to_string())
277        .collect();
278}
279
280fn si_sb_c_a_ata_list() -> Vec<String> {
281    return make_pl_si_lists(pl_sb_c_a_ata_list(), "ata", Some(1), true).0;
282}
283
284fn si_sb_c_a_ata_bysize() -> HashMap<usize, HashSet<String>> {
285    return make_pl_si_lists(pl_sb_c_a_ata_list(), "ata", Some(1), true).1;
286}
287
288fn pl_sb_c_a_ata_bysize() -> HashMap<usize, HashSet<String>> {
289    return make_pl_si_lists(pl_sb_c_a_ata_list(), "ata", Some(1), true).2;
290}
291
292fn pl_sb_c_a_ata() -> String {
293    return make_pl_si_lists(pl_sb_c_a_ata_list(), "ata", Some(1), true).3;
294}
295
296fn pl_sb_u_a_ae_list() -> Vec<String> {
297    return vec!["alumna", "alga", "vertebra", "persona", "vita"]
298        .iter()
299        .map(|s| s.to_string())
300        .collect();
301}
302
303fn si_sb_u_a_ae_list() -> Vec<String> {
304    return make_pl_si_lists(pl_sb_u_a_ae_list(), "e", None, true).0;
305}
306
307fn si_sb_u_a_ae_bysize() -> HashMap<usize, HashSet<String>> {
308    return make_pl_si_lists(pl_sb_u_a_ae_list(), "e", None, true).1;
309}
310
311fn pl_sb_u_a_ae_bysize() -> HashMap<usize, HashSet<String>> {
312    return make_pl_si_lists(pl_sb_u_a_ae_list(), "e", None, true).2;
313}
314
315fn pl_sb_u_a_ae() -> String {
316    return make_pl_si_lists(pl_sb_u_a_ae_list(), "e", None, true).3;
317}
318
319fn pl_sb_c_a_ae_list() -> Vec<String> {
320    return vec![
321        "amoeba",
322        "antenna",
323        "formula",
324        "hyperbola",
325        "medusa",
326        "nebula",
327        "parabola",
328        "abscissa",
329        "hydra",
330        "nova",
331        "lacuna",
332        "aurora",
333        "umbra",
334        "flora",
335        "fauna"
336    ]
337        .iter()
338        .map(|s| s.to_string())
339        .collect();
340}
341
342fn si_sb_c_a_ae_list() -> Vec<String> {
343    return make_pl_si_lists(pl_sb_c_a_ae_list(), "e", None, true).0;
344}
345
346fn si_sb_c_a_ae_bysize() -> HashMap<usize, HashSet<String>> {
347    return make_pl_si_lists(pl_sb_c_a_ae_list(), "e", None, true).1;
348}
349
350fn pl_sb_c_a_ae_bysize() -> HashMap<usize, HashSet<String>> {
351    return make_pl_si_lists(pl_sb_c_a_ae_list(), "e", None, true).2;
352}
353
354fn pl_sb_c_a_ae() -> String {
355    return make_pl_si_lists(pl_sb_c_a_ae_list(), "e", None, true).3;
356}
357
358fn pl_sb_c_en_ina_list() -> Vec<String> {
359    return vec!["stamen", "foramen", "lumen"]
360        .iter()
361        .map(|s| s.to_string())
362        .collect();
363}
364
365fn si_sb_c_en_ina_list() -> Vec<String> {
366    return make_pl_si_lists(pl_sb_c_en_ina_list(), "ina", Some(2), true).0;
367}
368
369fn si_sb_c_en_ina_bysize() -> HashMap<usize, HashSet<String>> {
370    return make_pl_si_lists(pl_sb_c_en_ina_list(), "ina", Some(2), true).1;
371}
372
373fn pl_sb_c_en_ina_bysize() -> HashMap<usize, HashSet<String>> {
374    return make_pl_si_lists(pl_sb_c_en_ina_list(), "ina", Some(2), true).2;
375}
376
377fn pl_sb_c_en_ina() -> String {
378    return make_pl_si_lists(pl_sb_c_en_ina_list(), "ina", Some(2), true).3;
379}
380
381fn pl_sb_u_um_a_list() -> Vec<String> {
382    return vec![
383        "bacterium",
384        "agendum",
385        "desideratum",
386        "erratum",
387        "stratum",
388        "datum",
389        "ovum",
390        "extremum",
391        "candelabrum"
392    ]
393        .iter()
394        .map(|s| s.to_string())
395        .collect();
396}
397
398fn si_sb_u_um_a_list() -> Vec<String> {
399    return make_pl_si_lists(pl_sb_u_um_a_list(), "a", Some(2), true).0;
400}
401
402fn si_sb_u_um_a_bysize() -> HashMap<usize, HashSet<String>> {
403    return make_pl_si_lists(pl_sb_u_um_a_list(), "a", Some(2), true).1;
404}
405
406fn pl_sb_u_um_a_bysize() -> HashMap<usize, HashSet<String>> {
407    return make_pl_si_lists(pl_sb_u_um_a_list(), "a", Some(2), true).2;
408}
409
410fn pl_sb_u_um_a() -> String {
411    return make_pl_si_lists(pl_sb_u_um_a_list(), "a", Some(2), true).3;
412}
413
414fn pl_sb_c_um_a_list() -> Vec<String> {
415    return vec![
416        "maximum",
417        "minimum",
418        "momentum",
419        "optimum",
420        "quantum",
421        "cranium",
422        "curriculum",
423        "dictum",
424        "phylum",
425        "aquarium",
426        "compendium",
427        "emporium",
428        "encomium",
429        "gymnasium",
430        "honorarium",
431        "interregnum",
432        "lustrum",
433        "memorandum",
434        "millennium",
435        "rostrum",
436        "spectrum",
437        "speculum",
438        "stadium",
439        "trapezium",
440        "ultimatum",
441        "medium",
442        "vacuum",
443        "velum",
444        "consortium",
445        "arboretum"
446    ]
447        .iter()
448        .map(|s| s.to_string())
449        .collect();
450}
451
452fn si_sb_c_um_a_list() -> Vec<String> {
453    return make_pl_si_lists(pl_sb_c_um_a_list(), "a", Some(2), true).0;
454}
455
456fn si_sb_c_um_a_bysize() -> HashMap<usize, HashSet<String>> {
457    return make_pl_si_lists(pl_sb_c_um_a_list(), "a", Some(2), true).1;
458}
459
460fn pl_sb_c_um_a_bysize() -> HashMap<usize, HashSet<String>> {
461    return make_pl_si_lists(pl_sb_c_um_a_list(), "a", Some(2), true).2;
462}
463
464fn pl_sb_c_um_a() -> String {
465    return make_pl_si_lists(pl_sb_c_um_a_list(), "a", Some(2), true).3;
466}
467
468fn pl_sb_u_us_i_list() -> Vec<String> {
469    return vec![
470        "alumnus",
471        "alveolus",
472        "bacillus",
473        "bronchus",
474        "locus",
475        "nucleus",
476        "stimulus",
477        "meniscus",
478        "sarcophagus"
479    ]
480        .iter()
481        .map(|s| s.to_string())
482        .collect();
483}
484
485fn si_sb_u_us_i_list() -> Vec<String> {
486    return make_pl_si_lists(pl_sb_u_us_i_list(), "i", Some(2), true).0;
487}
488
489fn si_sb_u_us_i_bysize() -> HashMap<usize, HashSet<String>> {
490    return make_pl_si_lists(pl_sb_u_us_i_list(), "i", Some(2), true).1;
491}
492
493fn pl_sb_u_us_i_bysize() -> HashMap<usize, HashSet<String>> {
494    return make_pl_si_lists(pl_sb_u_us_i_list(), "i", Some(2), true).2;
495}
496
497fn pl_sb_u_us_i() -> String {
498    return make_pl_si_lists(pl_sb_u_us_i_list(), "i", Some(2), true).3;
499}
500
501fn pl_sb_c_us_i_list() -> Vec<String> {
502    return vec![
503        "focus",
504        "radius",
505        "genius",
506        "incubus",
507        "succubus",
508        "nimbus",
509        "fungus",
510        "nucleolus",
511        "stylus",
512        "torus",
513        "umbilicus",
514        "uterus",
515        "hippopotamus",
516        "cactus"
517    ]
518        .iter()
519        .map(|s| s.to_string())
520        .collect();
521}
522
523fn si_sb_c_us_i_list() -> Vec<String> {
524    return make_pl_si_lists(pl_sb_c_us_i_list(), "i", Some(2), true).0;
525}
526
527fn si_sb_c_us_i_bysize() -> HashMap<usize, HashSet<String>> {
528    return make_pl_si_lists(pl_sb_c_us_i_list(), "i", Some(2), true).1;
529}
530
531fn pl_sb_c_us_i_bysize() -> HashMap<usize, HashSet<String>> {
532    return make_pl_si_lists(pl_sb_c_us_i_list(), "i", Some(2), true).2;
533}
534
535fn pl_sb_c_us_i() -> String {
536    return make_pl_si_lists(pl_sb_c_us_i_list(), "i", Some(2), true).3;
537}
538
539fn pl_sb_c_us_us() -> Vec<String> {
540    return vec!["status", "apparatus", "prospectus", "sinus", "hiatus", "impetus", "plexus"]
541        .iter()
542        .map(|s| s.to_string())
543        .collect();
544}
545
546fn pl_sb_c_us_us_bysize() -> HashMap<usize, HashSet<String>> {
547    return bysize(pl_sb_c_us_us());
548}
549
550fn pl_sb_u_on_a_list() -> Vec<String> {
551    return vec![
552        "criterion",
553        "perihelion",
554        "aphelion",
555        "phenomenon",
556        "prolegomenon",
557        "noumenon",
558        "organon",
559        "asyndeton",
560        "hyperbaton"
561    ]
562        .iter()
563        .map(|s| s.to_string())
564        .collect();
565}
566
567fn si_sb_u_on_a_list() -> Vec<String> {
568    return make_pl_si_lists(pl_sb_u_on_a_list(), "a", Some(2), true).0;
569}
570
571fn si_sb_u_on_a_bysize() -> HashMap<usize, HashSet<String>> {
572    return make_pl_si_lists(pl_sb_u_on_a_list(), "a", Some(2), true).1;
573}
574
575fn pl_sb_u_on_a_bysize() -> HashMap<usize, HashSet<String>> {
576    return make_pl_si_lists(pl_sb_u_on_a_list(), "a", Some(2), true).2;
577}
578
579fn pl_sb_u_on_a() -> String {
580    return make_pl_si_lists(pl_sb_u_on_a_list(), "a", Some(2), true).3;
581}
582
583fn pl_sb_c_on_a_list() -> Vec<String> {
584    return vec!["oxymoron"]
585        .iter()
586        .map(|s| s.to_string())
587        .collect();
588}
589
590fn si_sb_c_on_a_list() -> Vec<String> {
591    return make_pl_si_lists(pl_sb_c_on_a_list(), "a", Some(2), true).0;
592}
593
594fn si_sb_c_on_a_bysize() -> HashMap<usize, HashSet<String>> {
595    return make_pl_si_lists(pl_sb_c_on_a_list(), "a", Some(2), true).1;
596}
597
598fn pl_sb_c_on_a_bysize() -> HashMap<usize, HashSet<String>> {
599    return make_pl_si_lists(pl_sb_c_on_a_list(), "a", Some(2), true).2;
600}
601
602fn pl_sb_c_on_a() -> String {
603    return make_pl_si_lists(pl_sb_c_on_a_list(), "a", Some(2), true).3;
604}
605
606fn pl_sb_c_o_i() -> Vec<String> {
607    return vec!["solo", "soprano", "basso", "alto", "contralto", "tempo", "piano", "virtuoso"]
608        .iter()
609        .map(|s| s.to_string())
610        .collect();
611}
612
613fn pl_sb_c_o_i_bysize() -> HashMap<usize, HashSet<String>> {
614    return bysize(pl_sb_c_o_i());
615}
616
617fn si_sb_c_o_i_bysize() -> HashMap<usize, HashSet<String>> {
618    return bysize(
619        pl_sb_c_o_i()
620            .iter()
621            .map(|w| format!("{}i", &w[..w.len() - 1]))
622            .collect()
623    );
624}
625
626fn pl_sb_c_o_i_stems() -> String {
627    return joinstem(Some(-1), Some(pl_sb_c_o_i()));
628}
629
630fn pl_sb_u_o_os_complete() -> Vec<String> {
631    return vec!["ado", "ISO", "NATO", "NCO", "NGO", "oto"]
632        .iter()
633        .map(|s| s.to_string())
634        .collect();
635}
636
637fn si_sb_u_o_os_complete() -> Vec<String> {
638    return pl_sb_u_o_os_complete()
639        .iter()
640        .map(|w| format!("{}s", w))
641        .collect();
642}
643
644fn pl_sb_u_o_os_endings() -> Vec<String> {
645    let mut pl_sb_u_o_os_endings: Vec<String> = vec![
646        "aficionado",
647        "aggro",
648        "albino",
649        "allegro",
650        "ammo",
651        "Antananarivo",
652        "archipelago",
653        "armadillo",
654        "auto",
655        "avocado",
656        "Bamako",
657        "Barquisimeto",
658        "bimbo",
659        "bingo",
660        "Biro",
661        "bolero",
662        "Bolzano",
663        "bongo",
664        "Boto",
665        "burro",
666        "Cairo",
667        "canto",
668        "cappuccino",
669        "casino",
670        "cello",
671        "Chicago",
672        "Chimango",
673        "cilantro",
674        "cochito",
675        "coco",
676        "Colombo",
677        "Colorado",
678        "commando",
679        "concertino",
680        "contango",
681        "credo",
682        "crescendo",
683        "cyano",
684        "demo",
685        "ditto",
686        "Draco",
687        "dynamo",
688        "embryo",
689        "Esperanto",
690        "espresso",
691        "euro",
692        "falsetto",
693        "Faro",
694        "fiasco",
695        "Filipino",
696        "flamenco",
697        "furioso",
698        "generalissimo",
699        "Gestapo",
700        "ghetto",
701        "gigolo",
702        "gizmo",
703        "Greensboro",
704        "gringo",
705        "Guaiabero",
706        "guano",
707        "gumbo",
708        "gyro",
709        "hairdo",
710        "hippo",
711        "Idaho",
712        "impetigo",
713        "inferno",
714        "info",
715        "intermezzo",
716        "intertrigo",
717        "Iquico",
718        "jumbo",
719        "junto",
720        "Kakapo",
721        "kilo",
722        "Kinkimavo",
723        "Kokako",
724        "Kosovo",
725        "Lesotho",
726        "libero",
727        "libido",
728        "libretto",
729        "lido",
730        "Lilo",
731        "limbo",
732        "limo",
733        "lineno",
734        "lingo",
735        "lino",
736        "livedo",
737        "loco",
738        "logo",
739        "lumbago",
740        "macho",
741        "macro",
742        "mafioso",
743        "magneto",
744        "magnifico",
745        "Majuro",
746        "Malabo",
747        "manifesto",
748        "Maputo",
749        "Maracaibo",
750        "medico",
751        "memo",
752        "metro",
753        "Mexico",
754        "micro",
755        "Milano",
756        "Monaco",
757        "mono",
758        "Montenegro",
759        "Morocco",
760        "Muqdisho",
761        "myo",
762        "neutrino",
763        "Ningbo",
764        "octavo",
765        "oregano",
766        "Orinoco",
767        "Orlando",
768        "Oslo",
769        "panto",
770        "Paramaribo",
771        "Pardusco",
772        "pedalo",
773        "photo",
774        "pimento",
775        "pinto",
776        "pleco",
777        "Pluto",
778        "pogo",
779        "polo",
780        "poncho",
781        "Porto-Novo",
782        "Porto",
783        "pro",
784        "psycho",
785        "pueblo",
786        "quarto",
787        "Quito",
788        "repo",
789        "rhino",
790        "risotto",
791        "rococo",
792        "rondo",
793        "Sacramento",
794        "saddo",
795        "sago",
796        "salvo",
797        "Santiago",
798        "Sapporo",
799        "Sarajevo",
800        "scherzando",
801        "scherzo",
802        "silo",
803        "sirocco",
804        "sombrero",
805        "staccato",
806        "sterno",
807        "stucco",
808        "stylo",
809        "sumo",
810        "Taiko",
811        "techno",
812        "terrazzo",
813        "testudo",
814        "timpano",
815        "tiro",
816        "tobacco",
817        "Togo",
818        "Tokyo",
819        "torero",
820        "Torino",
821        "Toronto",
822        "torso",
823        "tremolo",
824        "typo",
825        "tyro",
826        "ufo",
827        "UNESCO",
828        "vaquero",
829        "vermicello",
830        "verso",
831        "vibrato",
832        "violoncello",
833        "Virgo",
834        "weirdo",
835        "WHO",
836        "WTO",
837        "Yamoussoukro",
838        "yo-yo",
839        "zero",
840        "Zibo"
841    ]
842        .iter()
843        .map(|s| s.to_string())
844        .collect();
845    pl_sb_u_o_os_endings.extend(pl_sb_c_o_i());
846    pl_sb_u_o_os_endings
847}
848
849fn pl_sb_u_o_os_bysize() -> HashMap<usize, HashSet<String>> {
850    return bysize(pl_sb_u_o_os_endings());
851}
852
853fn si_sb_u_o_os_bysize() -> HashMap<usize, HashSet<String>> {
854    return bysize(
855        pl_sb_u_o_os_endings()
856            .iter()
857            .map(|w| format!("{}s", w))
858            .collect()
859    );
860}
861
862fn pl_sb_u_ch_chs_list() -> Vec<String> {
863    return vec!["czech", "eunuch", "stomach"]
864        .iter()
865        .map(|s| s.to_string())
866        .collect();
867}
868
869fn si_sb_u_ch_chs_list() -> Vec<String> {
870    return make_pl_si_lists(pl_sb_u_ch_chs_list(), "s", None, true).0;
871}
872
873fn si_sb_u_ch_chs_bysize() -> HashMap<usize, HashSet<String>> {
874    return make_pl_si_lists(pl_sb_u_ch_chs_list(), "s", None, true).1;
875}
876
877fn pl_sb_u_ch_chs_bysize() -> HashMap<usize, HashSet<String>> {
878    return make_pl_si_lists(pl_sb_u_ch_chs_list(), "s", None, true).2;
879}
880
881fn pl_sb_u_ch_chs() -> String {
882    return make_pl_si_lists(pl_sb_u_ch_chs_list(), "s", None, true).3;
883}
884
885fn pl_sb_u_ex_ices_list() -> Vec<String> {
886    return vec!["codex", "murex", "silex"]
887        .iter()
888        .map(|s| s.to_string())
889        .collect();
890}
891
892fn si_sb_u_ex_ices_list() -> Vec<String> {
893    return make_pl_si_lists(pl_sb_u_ex_ices_list(), "ices", Some(2), true).0;
894}
895
896fn si_sb_u_ex_ices_bysize() -> HashMap<usize, HashSet<String>> {
897    return make_pl_si_lists(pl_sb_u_ex_ices_list(), "ices", Some(2), true).1;
898}
899
900fn pl_sb_u_ex_ices_bysize() -> HashMap<usize, HashSet<String>> {
901    return make_pl_si_lists(pl_sb_u_ex_ices_list(), "ices", Some(2), true).2;
902}
903
904fn pl_sb_u_ex_ices() -> String {
905    return make_pl_si_lists(pl_sb_u_ex_ices_list(), "ices", Some(2), true).3;
906}
907
908fn pl_sb_u_ix_ices_list() -> Vec<String> {
909    return vec!["radix", "helix"]
910        .iter()
911        .map(|s| s.to_string())
912        .collect();
913}
914
915fn si_sb_u_ix_ices_list() -> Vec<String> {
916    return make_pl_si_lists(pl_sb_u_ix_ices_list(), "ices", Some(2), true).0;
917}
918
919fn si_sb_u_ix_ices_bysize() -> HashMap<usize, HashSet<String>> {
920    return make_pl_si_lists(pl_sb_u_ix_ices_list(), "ices", Some(2), true).1;
921}
922
923fn pl_sb_u_ix_ices_bysize() -> HashMap<usize, HashSet<String>> {
924    return make_pl_si_lists(pl_sb_u_ix_ices_list(), "ices", Some(2), true).2;
925}
926
927fn pl_sb_u_ix_ices() -> String {
928    return make_pl_si_lists(pl_sb_u_ix_ices_list(), "ices", Some(2), true).3;
929}
930
931fn pl_sb_c_ex_ices_list() -> Vec<String> {
932    return vec!["vortex", "vertex", "cortex", "latex", "pontifex", "apex", "index", "simplex"]
933        .iter()
934        .map(|s| s.to_string())
935        .collect();
936}
937
938fn si_sb_c_ex_ices_list() -> Vec<String> {
939    return make_pl_si_lists(pl_sb_c_ex_ices_list(), "ices", Some(2), true).0;
940}
941
942fn si_sb_c_ex_ices_bysize() -> HashMap<usize, HashSet<String>> {
943    return make_pl_si_lists(pl_sb_c_ex_ices_list(), "ices", Some(2), true).1;
944}
945
946fn pl_sb_c_ex_ices_bysize() -> HashMap<usize, HashSet<String>> {
947    return make_pl_si_lists(pl_sb_c_ex_ices_list(), "ices", Some(2), true).2;
948}
949
950fn pl_sb_c_ex_ices() -> String {
951    return make_pl_si_lists(pl_sb_c_ex_ices_list(), "ices", Some(2), true).3;
952}
953
954fn pl_sb_c_ix_ices_list() -> Vec<String> {
955    return vec!["appendix"]
956        .iter()
957        .map(|s| s.to_string())
958        .collect();
959}
960
961fn si_sb_c_ix_ices_list() -> Vec<String> {
962    return make_pl_si_lists(pl_sb_c_ix_ices_list(), "ices", Some(2), true).0;
963}
964
965fn si_sb_c_ix_ices_bysize() -> HashMap<usize, HashSet<String>> {
966    return make_pl_si_lists(pl_sb_c_ix_ices_list(), "ices", Some(2), true).1;
967}
968
969fn pl_sb_c_ix_ices_bysize() -> HashMap<usize, HashSet<String>> {
970    return make_pl_si_lists(pl_sb_c_ix_ices_list(), "ices", Some(2), true).2;
971}
972
973fn pl_sb_c_ix_ices() -> String {
974    return make_pl_si_lists(pl_sb_c_ix_ices_list(), "ices", Some(2), true).3;
975}
976
977fn pl_sb_c_i_list() -> Vec<String> {
978    return vec!["afreet", "afrit", "efreet"]
979        .iter()
980        .map(|s| s.to_string())
981        .collect();
982}
983
984fn si_sb_c_i_list() -> Vec<String> {
985    return make_pl_si_lists(pl_sb_c_i_list(), "i", None, true).0;
986}
987
988fn si_sb_c_i_bysize() -> HashMap<usize, HashSet<String>> {
989    return make_pl_si_lists(pl_sb_c_i_list(), "i", None, true).1;
990}
991
992fn pl_sb_c_i_bysize() -> HashMap<usize, HashSet<String>> {
993    return make_pl_si_lists(pl_sb_c_i_list(), "i", None, true).2;
994}
995
996fn pl_sb_c_i() -> String {
997    return make_pl_si_lists(pl_sb_c_i_list(), "i", None, true).3;
998}
999
1000fn pl_sb_c_im_list() -> Vec<String> {
1001    return vec!["goy", "seraph", "cherub"]
1002        .iter()
1003        .map(|s| s.to_string())
1004        .collect();
1005}
1006
1007fn si_sb_c_im_list() -> Vec<String> {
1008    return make_pl_si_lists(pl_sb_c_im_list(), "im", None, true).0;
1009}
1010
1011fn si_sb_c_im_bysize() -> HashMap<usize, HashSet<String>> {
1012    return make_pl_si_lists(pl_sb_c_im_list(), "im", None, true).1;
1013}
1014
1015fn pl_sb_c_im_bysize() -> HashMap<usize, HashSet<String>> {
1016    return make_pl_si_lists(pl_sb_c_im_list(), "im", None, true).2;
1017}
1018
1019fn pl_sb_c_im() -> String {
1020    return make_pl_si_lists(pl_sb_c_im_list(), "im", None, true).3;
1021}
1022
1023fn pl_sb_u_man_mans_list() -> Vec<String> {
1024    return vec![
1025        "ataman",
1026        "caiman",
1027        "cayman",
1028        "ceriman",
1029        "desman",
1030        "dolman",
1031        "farman",
1032        "harman",
1033        "hetman",
1034        "human",
1035        "leman",
1036        "ottoman",
1037        "shaman",
1038        "talisman"
1039    ]
1040        .iter()
1041        .map(|s| s.to_string())
1042        .collect();
1043}
1044
1045fn pl_sb_u_man_mans_caps_list() -> Vec<String> {
1046    return vec![
1047        "Alabaman",
1048        "Bahaman",
1049        "Burman",
1050        "|German",
1051        "Hiroshiman",
1052        "Liman",
1053        "Nakayaman",
1054        "Norman",
1055        "Oklahoman",
1056        "Panaman",
1057        "Roman",
1058        "Selman",
1059        "Sonaman",
1060        "Tacoman",
1061        "Yakiman",
1062        "Yokohaman",
1063        "Yuman"
1064    ]
1065        .iter()
1066        .map(|s| s.to_string())
1067        .collect();
1068}
1069
1070fn si_sb_u_man_mans_list() -> Vec<String> {
1071    return make_pl_si_lists(pl_sb_u_man_mans_list(), "s", None, false).0;
1072}
1073
1074fn si_sb_u_man_mans_caps_list() -> Vec<String> {
1075    return make_pl_si_lists(pl_sb_u_man_mans_caps_list(), "s", None, false).0;
1076}
1077
1078fn si_sb_u_man_mans_bysize() -> HashMap<usize, HashSet<String>> {
1079    return make_pl_si_lists(pl_sb_u_man_mans_list(), "s", None, false).1;
1080}
1081
1082fn si_sb_u_man_mans_caps_bysize() -> HashMap<usize, HashSet<String>> {
1083    return make_pl_si_lists(pl_sb_u_man_mans_caps_list(), "s", None, false).1;
1084}
1085
1086fn pl_sb_u_man_mans_bysize() -> HashMap<usize, HashSet<String>> {
1087    return make_pl_si_lists(pl_sb_u_man_mans_list(), "s", None, false).2;
1088}
1089
1090fn pl_sb_u_man_mans_caps_bysize() -> HashMap<usize, HashSet<String>> {
1091    return make_pl_si_lists(pl_sb_u_man_mans_caps_list(), "s", None, false).2;
1092}
1093
1094fn pl_sb_u_louse_lice_list() -> Vec<String> {
1095    return vec!["booklouse", "grapelouse", "louse", "woodlouse"]
1096        .iter()
1097        .map(|s| s.to_string())
1098        .collect();
1099}
1100
1101fn si_sb_u_louse_lice_list() -> Vec<String> {
1102    return make_pl_si_lists(pl_sb_u_louse_lice_list(), "lice", Some(5), false).0;
1103}
1104
1105fn si_sb_u_louse_lice_bysize() -> HashMap<usize, HashSet<String>> {
1106    return make_pl_si_lists(pl_sb_u_louse_lice_list(), "lice", Some(5), false).1;
1107}
1108
1109fn pl_sb_u_louse_lice_bysize() -> HashMap<usize, HashSet<String>> {
1110    return make_pl_si_lists(pl_sb_u_louse_lice_list(), "lice", Some(5), false).2;
1111}
1112
1113fn pl_sb_uninflected_s_complete() -> Vec<String> {
1114    return vec![
1115        "breeches",
1116        "britches",
1117        "pajamas",
1118        "pyjamas",
1119        "clippers",
1120        "gallows",
1121        "hijinks",
1122        "headquarters",
1123        "pliers",
1124        "scissors",
1125        "testes",
1126        "herpes",
1127        "pincers",
1128        "shears",
1129        "proceedings",
1130        "trousers",
1131        "cantus",
1132        "coitus",
1133        "nexus",
1134        "contretemps",
1135        "corps",
1136        "debris",
1137        "siemens",
1138        "mumps",
1139        "diabetes",
1140        "jackanapes",
1141        "series",
1142        "species",
1143        "subspecies",
1144        "rabies",
1145        "chassis",
1146        "innings",
1147        "news",
1148        "mews",
1149        "haggis"
1150    ]
1151        .iter()
1152        .map(|s| s.to_string())
1153        .collect();
1154}
1155
1156fn pl_sb_uninflected_s_endings() -> Vec<String> {
1157    return vec!["ois", "measles"]
1158        .iter()
1159        .map(|s| s.to_string())
1160        .collect();
1161}
1162
1163fn pl_sb_uninflected_s() -> Vec<String> {
1164    let mut pl_sb_uninflected_s = pl_sb_uninflected_s_complete();
1165    pl_sb_uninflected_s.extend(
1166        pl_sb_uninflected_s_endings()
1167            .iter()
1168            .map(|w| format!(".*{}", w))
1169    );
1170    pl_sb_uninflected_s
1171}
1172
1173fn pl_sb_uninflected_herd() -> Vec<String> {
1174    return vec![
1175        "wildebeest",
1176        "swine",
1177        "eland",
1178        "bison",
1179        "buffalo",
1180        "cattle",
1181        "elk",
1182        "rhinoceros",
1183        "zucchini",
1184        "caribou",
1185        "dace",
1186        "grouse",
1187        "guinea fowl",
1188        "guinea-fowl",
1189        "haddock",
1190        "hake",
1191        "halibut",
1192        "herring",
1193        "mackerel",
1194        "pickerel",
1195        "pike",
1196        "roe",
1197        "seed",
1198        "shad",
1199        "snipe",
1200        "teal",
1201        "turbot",
1202        "water fowl",
1203        "water-fowl"
1204    ]
1205        .iter()
1206        .map(|s| s.to_string())
1207        .collect();
1208}
1209
1210fn pl_sb_uninflected_complete() -> Vec<String> {
1211    return vec![
1212        "tuna",
1213        "salmon",
1214        "mackerel",
1215        "trout",
1216        "bream",
1217        "sea-bass",
1218        "sea bass",
1219        "carp",
1220        "cod",
1221        "flounder",
1222        "whiting",
1223        "moose",
1224        "graffiti",
1225        "djinn",
1226        "samuri",
1227        "offspring",
1228        "pence",
1229        "quid",
1230        "hertz"
1231    ]
1232        .iter()
1233        .map(|s| s.to_string())
1234        .chain(pl_sb_uninflected_complete())
1235        .collect();
1236}
1237
1238fn pl_sb_uninflected_caps() -> Vec<String> {
1239    return vec![
1240        "Portuguese",
1241        "Amoyese",
1242        "Borghese",
1243        "Congoese",
1244        "Faroese",
1245        "Foochowese",
1246        "Genevese",
1247        "Genoese",
1248        "Gilbertese",
1249        "Hottentotese",
1250        "Kiplingese",
1251        "Kongoese",
1252        "Lucchese",
1253        "Maltese",
1254        "Nankingese",
1255        "Niasese",
1256        "Pekingese",
1257        "Piedmontese",
1258        "Pistoiese",
1259        "Sarawakese",
1260        "Shavese",
1261        "Vermontese",
1262        "Wenchowese",
1263        "Yengeese"
1264    ]
1265        .iter()
1266        .map(|s| s.to_string())
1267        .collect();
1268}
1269
1270fn pl_sb_uninflected_endings() -> Vec<String> {
1271    return vec![
1272        "butter",
1273        "cash",
1274        "furniture",
1275        "information",
1276        "fish",
1277        "deer",
1278        "sheep",
1279        "nese",
1280        "rese",
1281        "lese",
1282        "mese",
1283        "pox",
1284        "craft"
1285    ]
1286        .iter()
1287        .map(|s| s.to_string())
1288        .chain(pl_sb_uninflected_s_endings())
1289        .collect();
1290}
1291
1292fn pl_sb_uninflected_bysize() -> HashMap<usize, HashSet<String>> {
1293    return bysize(pl_sb_uninflected_endings());
1294}
1295
1296fn pl_sb_singular_s_complete() -> Vec<String> {
1297    return vec![
1298        "acropolis",
1299        "aegis",
1300        "alias",
1301        "asbestos",
1302        "bathos",
1303        "bias",
1304        "bronchitis",
1305        "bursitis",
1306        "caddis",
1307        "cannabis",
1308        "canvas",
1309        "chaos",
1310        "cosmos",
1311        "dais",
1312        "digitalis",
1313        "epidermis",
1314        "ethos",
1315        "eyas",
1316        "gas",
1317        "glottis",
1318        "hubris",
1319        "ibis",
1320        "lens",
1321        "mantis",
1322        "marquis",
1323        "metropolis",
1324        "pathos",
1325        "pelvis",
1326        "polis",
1327        "rhinoceros",
1328        "sassafras",
1329        "trellis"
1330    ]
1331        .iter()
1332        .map(|s| s.to_string())
1333        .chain(pl_sb_c_is_ides_complete())
1334        .collect();
1335}
1336
1337fn pl_sb_singular_s_endings() -> Vec<String> {
1338    return vec!["ss", "us"]
1339        .iter()
1340        .map(|s| s.to_string())
1341        .chain(pl_sb_c_is_ides_endings())
1342        .collect();
1343}
1344
1345fn pl_sb_singular_s_bysize() -> HashMap<usize, HashSet<String>> {
1346    return bysize(pl_sb_singular_s_endings());
1347}
1348
1349fn si_sb_singular_s_complete() -> Vec<String> {
1350    return pl_sb_singular_s_complete()
1351        .iter()
1352        .map(|w| format!("{}es", w))
1353        .collect();
1354}
1355
1356fn si_sb_singular_s_endings() -> Vec<String> {
1357    return pl_sb_singular_s_endings()
1358        .iter()
1359        .map(|w| format!("{}es", w))
1360        .collect();
1361}
1362
1363fn si_sb_singular_s_bysize() -> HashMap<usize, HashSet<String>> {
1364    return bysize(si_sb_singular_s_endings());
1365}
1366
1367fn pl_sb_singular_s_es() -> Vec<String> {
1368    return vec!["[A-Z].*es"]
1369        .iter()
1370        .map(|s| s.to_string())
1371        .collect();
1372}
1373
1374fn pl_sb_singular_s() -> String {
1375    let mut concat: Vec<String> = Vec::new();
1376    concat.extend(
1377        pl_sb_singular_s_complete()
1378            .iter()
1379            .map(|w| w.to_string())
1380    );
1381    concat.extend(
1382        pl_sb_singular_s_endings()
1383            .iter()
1384            .map(|w| format!(".*{}", w))
1385    );
1386    concat.extend(
1387        pl_sb_singular_s_es()
1388            .iter()
1389            .map(|w| w.to_string())
1390    );
1391    return enclose(&concat.join("|"));
1392}
1393
1394fn si_sb_ois_oi_case() -> Vec<String> {
1395    return vec!["Bolshois", "Hanois"]
1396        .iter()
1397        .map(|s| s.to_string())
1398        .collect();
1399}
1400
1401fn si_sb_uses_use_case() -> Vec<String> {
1402    return vec!["Betelgeuses", "Duses", "Meuses", "Syracuses", "Toulouses"]
1403        .iter()
1404        .map(|s| s.to_string())
1405        .collect();
1406}
1407
1408fn si_sb_use_uses() -> Vec<String> {
1409    return vec![
1410        "abuses",
1411        "applauses",
1412        "blouses",
1413        "carouses",
1414        "causes",
1415        "chartreuses",
1416        "clauses",
1417        "contuses",
1418        "douses",
1419        "excuses",
1420        "fuses",
1421        "grouses",
1422        "hypotenuses",
1423        "masseuses",
1424        "menopauses",
1425        "misuses",
1426        "muses",
1427        "overuses",
1428        "pauses",
1429        "peruses",
1430        "profuses",
1431        "recluses",
1432        "reuses",
1433        "ruses",
1434        "souses",
1435        "spouses",
1436        "suffuses",
1437        "transfuses",
1438        "uses"
1439    ]
1440        .iter()
1441        .map(|s| s.to_string())
1442        .collect();
1443}
1444
1445fn si_sb_ies_ie_case() -> Vec<String> {
1446    return vec![
1447        "Addies",
1448        "Aggies",
1449        "Allies",
1450        "Amies",
1451        "Angies",
1452        "Annies",
1453        "Annmaries",
1454        "Archies",
1455        "Arties",
1456        "Aussies",
1457        "Barbies",
1458        "Barries",
1459        "Basies",
1460        "Bennies",
1461        "Bernies",
1462        "Berties",
1463        "Bessies",
1464        "Betties",
1465        "Billies",
1466        "Blondies",
1467        "Bobbies",
1468        "Bonnies",
1469        "Bowies",
1470        "Brandies",
1471        "Bries",
1472        "Brownies",
1473        "Callies",
1474        "Carnegies",
1475        "Carries",
1476        "Cassies",
1477        "Charlies",
1478        "Cheries",
1479        "Christies",
1480        "Connies",
1481        "Curies",
1482        "Dannies",
1483        "Debbies",
1484        "Dixies",
1485        "Dollies",
1486        "Donnies",
1487        "Drambuies",
1488        "Eddies",
1489        "Effies",
1490        "Ellies",
1491        "Elsies",
1492        "Eries",
1493        "Ernies",
1494        "Essies",
1495        "Eugenies",
1496        "Fannies",
1497        "Flossies",
1498        "Frankies",
1499        "Freddies",
1500        "Gillespies",
1501        "Goldies",
1502        "Gracies",
1503        "Guthries",
1504        "Hallies",
1505        "Hatties",
1506        "Hetties",
1507        "Hollies",
1508        "Jackies",
1509        "Jamies",
1510        "Janies",
1511        "Jannies",
1512        "Jeanies",
1513        "Jeannies",
1514        "Jennies",
1515        "Jessies",
1516        "Jimmies",
1517        "Jodies",
1518        "Johnies",
1519        "Johnnies",
1520        "Josies",
1521        "Julies",
1522        "Kalgoorlies",
1523        "Kathies",
1524        "Katies",
1525        "Kellies",
1526        "Kewpies",
1527        "Kristies",
1528        "Laramies",
1529        "Lassies",
1530        "Lauries",
1531        "Leslies",
1532        "Lessies",
1533        "Lillies",
1534        "Lizzies",
1535        "Lonnies",
1536        "Lories",
1537        "Lorries",
1538        "Lotties",
1539        "Louies",
1540        "Mackenzies",
1541        "Maggies",
1542        "Maisies",
1543        "Mamies",
1544        "Marcies",
1545        "Margies",
1546        "Maries",
1547        "Marjories",
1548        "Matties",
1549        "McKenzies",
1550        "Melanies",
1551        "Mickies",
1552        "Millies",
1553        "Minnies",
1554        "Mollies",
1555        "Mounties",
1556        "Nannies",
1557        "Natalies",
1558        "Nellies",
1559        "Netties",
1560        "Ollies",
1561        "Ozzies",
1562        "Pearlies",
1563        "Pottawatomies",
1564        "Reggies",
1565        "Richies",
1566        "Rickies",
1567        "Robbies",
1568        "Ronnies",
1569        "Rosalies",
1570        "Rosemaries",
1571        "Rosies",
1572        "Roxies",
1573        "Rushdies",
1574        "Ruthies",
1575        "Sadies",
1576        "Sallies",
1577        "Sammies",
1578        "Scotties",
1579        "Selassies",
1580        "Sherries",
1581        "Sophies",
1582        "Stacies",
1583        "Stefanies",
1584        "Stephanies",
1585        "Stevies",
1586        "Susies",
1587        "Sylvies",
1588        "Tammies",
1589        "Terries",
1590        "Tessies",
1591        "Tommies",
1592        "Tracies",
1593        "Trekkies",
1594        "Valaries",
1595        "Valeries",
1596        "Valkyries",
1597        "Vickies",
1598        "Virgies",
1599        "Willies",
1600        "Winnies",
1601        "Wylies",
1602        "Yorkies"
1603    ]
1604        .iter()
1605        .map(|s| s.to_string())
1606        .collect();
1607}
1608
1609fn si_sb_ies_ie() -> Vec<String> {
1610    return vec![
1611        "aeries",
1612        "baggies",
1613        "belies",
1614        "biggies",
1615        "birdies",
1616        "bogies",
1617        "bonnies",
1618        "boogies",
1619        "bookies",
1620        "bourgeoisies",
1621        "brownies",
1622        "budgies",
1623        "caddies",
1624        "calories",
1625        "camaraderies",
1626        "cockamamies",
1627        "collies",
1628        "cookies",
1629        "coolies",
1630        "cooties",
1631        "coteries",
1632        "crappies",
1633        "curies",
1634        "cutesies",
1635        "dogies",
1636        "eyries",
1637        "floozies",
1638        "footsies",
1639        "freebies",
1640        "genies",
1641        "goalies",
1642        "groupies",
1643        "hies",
1644        "jalousies",
1645        "junkies",
1646        "kiddies",
1647        "laddies",
1648        "lassies",
1649        "lies",
1650        "lingeries",
1651        "magpies",
1652        "menageries",
1653        "mommies",
1654        "movies",
1655        "neckties",
1656        "newbies",
1657        "nighties",
1658        "oldies",
1659        "organdies",
1660        "overlies",
1661        "pies",
1662        "pinkies",
1663        "pixies",
1664        "potpies",
1665        "prairies",
1666        "quickies",
1667        "reveries",
1668        "rookies",
1669        "rotisseries",
1670        "softies",
1671        "sorties",
1672        "species",
1673        "stymies",
1674        "sweeties",
1675        "ties",
1676        "underlies",
1677        "unties",
1678        "veggies",
1679        "vies",
1680        "yuppies",
1681        "zombies"
1682    ]
1683        .iter()
1684        .map(|s| s.to_string())
1685        .collect();
1686}
1687
1688fn si_sb_oes_oe_case() -> Vec<String> {
1689    return vec![
1690        "Chloes",
1691        "Crusoes",
1692        "Defoes",
1693        "Faeroes",
1694        "Ivanhoes",
1695        "Joes",
1696        "McEnroes",
1697        "Moes",
1698        "Monroes",
1699        "Noes",
1700        "Poes",
1701        "Roscoes",
1702        "Tahoes",
1703        "Tippecanoes",
1704        "Zoes"
1705    ]
1706        .iter()
1707        .map(|s| s.to_string())
1708        .collect();
1709}
1710
1711fn si_sb_oes_oe() -> Vec<String> {
1712    return vec![
1713        "aloes",
1714        "backhoes",
1715        "canoes",
1716        "does",
1717        "floes",
1718        "foes",
1719        "hoes",
1720        "mistletoes",
1721        "oboes",
1722        "pekoes",
1723        "roes",
1724        "sloes",
1725        "throes",
1726        "tiptoes",
1727        "toes",
1728        "woes"
1729    ]
1730        .iter()
1731        .map(|s| s.to_string())
1732        .collect();
1733}
1734
1735fn si_sb_z_zes() -> Vec<String> {
1736    return vec!["quartzes", "topazes"]
1737        .iter()
1738        .map(|s| s.to_string())
1739        .collect();
1740}
1741
1742fn si_sb_zzes_zz() -> Vec<String> {
1743    return vec!["buzzes", "fizzes", "frizzes", "razzes"]
1744        .iter()
1745        .map(|s| s.to_string())
1746        .collect();
1747}
1748
1749fn si_sb_ches_che_case() -> Vec<String> {
1750    return vec![
1751        "Andromaches",
1752        "Apaches",
1753        "Blanches",
1754        "Comanches",
1755        "Nietzsches",
1756        "Porsches",
1757        "Roches"
1758    ]
1759        .iter()
1760        .map(|s| s.to_string())
1761        .collect();
1762}
1763
1764fn si_sb_ches_che() -> Vec<String> {
1765    return vec![
1766        "aches",
1767        "avalanches",
1768        "backaches",
1769        "bellyaches",
1770        "caches",
1771        "cloches",
1772        "creches",
1773        "douches",
1774        "earaches",
1775        "fiches",
1776        "headaches",
1777        "heartaches",
1778        "microfiches",
1779        "niches",
1780        "pastiches",
1781        "psyches",
1782        "quiches",
1783        "stomachaches",
1784        "toothaches",
1785        "tranches"
1786    ]
1787        .iter()
1788        .map(|s| s.to_string())
1789        .collect();
1790}
1791
1792fn si_sb_xes_xe() -> Vec<String> {
1793    return vec!["annexes", "axes", "deluxes", "pickaxes"]
1794        .iter()
1795        .map(|s| s.to_string())
1796        .collect();
1797}
1798
1799fn si_sb_sses_sse_case() -> Vec<String> {
1800    return vec!["Hesses", "Jesses", "Larousses", "Matisses"]
1801        .iter()
1802        .map(|s| s.to_string())
1803        .collect();
1804}
1805
1806fn si_sb_sses_sse() -> Vec<String> {
1807    return vec!["bouillabaisses", "crevasses", "demitasses", "impasses", "mousses", "posses"]
1808        .iter()
1809        .map(|s| s.to_string())
1810        .collect();
1811}
1812
1813fn si_sb_ves_ve_case() -> Vec<String> {
1814    return vec!["Clives", "Palmolives"]
1815        .iter()
1816        .map(|s| s.to_string())
1817        .collect();
1818}
1819
1820fn si_sb_ves_ve() -> Vec<String> {
1821    return vec![
1822        "interweaves",
1823        "weaves",
1824        "olives",
1825        "bivalves",
1826        "dissolves",
1827        "resolves",
1828        "salves",
1829        "twelves",
1830        "valves"
1831    ]
1832        .iter()
1833        .map(|s| s.to_string())
1834        .collect();
1835}
1836
1837fn plverb_special_s() -> String {
1838    let mut concat: Vec<String> = Vec::new();
1839    concat.push(pl_sb_singular_s());
1840    concat.extend(pl_sb_uninflected_s());
1841    let pl_sb_irregular_s_keys: Vec<String> = pl_sb_irregular_s().keys().cloned().collect();
1842    concat.extend(pl_sb_irregular_s_keys);
1843    concat.extend(
1844        vec!["(.*[csx])is", "(.*)ceps", "[A-Z].*s"]
1845            .iter()
1846            .map(|s| s.to_string())
1847    );
1848    return enclose(&concat.join("|"));
1849}
1850
1851fn _pl_sb_postfix_adj_defn() -> HashMap<String, String> {
1852    let mut m = HashMap::new();
1853    m.insert("general".to_string(), enclose(r"(?!major|lieutenant|brigadier|adjutant|.*star)\S+"));
1854    m.insert("martial".to_string(), enclose("court"));
1855    m.insert("force".to_string(), enclose("pound"));
1856    m
1857}
1858
1859fn pl_sb_postfix_adj() -> Vec<String> {
1860    return _pl_sb_postfix_adj_defn()
1861        .iter()
1862        .map(|(k, v)| format!("{}(?=(?:-|\\s+){})", v, k))
1863        .collect();
1864}
1865
1866fn pl_sb_postfix_adj_stems() -> String {
1867    return format!("({})(.*)", pl_sb_postfix_adj().join("|"));
1868}
1869
1870fn si_sb_es_is() -> Vec<String> {
1871    return vec![
1872        "amanuenses",
1873        "amniocenteses",
1874        "analyses",
1875        "antitheses",
1876        "apotheoses",
1877        "arterioscleroses",
1878        "atheroscleroses",
1879        "axes",
1880        "catalyses",
1881        "catharses",
1882        "chasses",
1883        "cirrhoses",
1884        "cocces",
1885        "crises",
1886        "diagnoses",
1887        "dialyses",
1888        "diereses",
1889        "electrolyses",
1890        "emphases",
1891        "exegeses",
1892        "geneses",
1893        "halitoses",
1894        "hydrolyses",
1895        "hypnoses",
1896        "hypotheses",
1897        "hystereses",
1898        "metamorphoses",
1899        "metastases",
1900        "misdiagnoses",
1901        "mitoses",
1902        "mononucleoses",
1903        "narcoses",
1904        "necroses",
1905        "nemeses",
1906        "neuroses",
1907        "oases",
1908        "osmoses",
1909        "osteoporoses",
1910        "paralyses",
1911        "parentheses",
1912        "parthenogeneses",
1913        "periphrases",
1914        "photosyntheses",
1915        "probosces",
1916        "prognoses",
1917        "prophylaxes",
1918        "prostheses",
1919        "preces",
1920        "psoriases",
1921        "psychoanalyses",
1922        "psychokineses",
1923        "psychoses",
1924        "scleroses",
1925        "scolioses",
1926        "sepses",
1927        "silicoses",
1928        "symbioses",
1929        "synopses",
1930        "syntheses",
1931        "taxes",
1932        "telekineses",
1933        "theses",
1934        "thromboses",
1935        "tuberculoses",
1936        "urinalyses"
1937    ]
1938        .iter()
1939        .map(|s| s.to_string())
1940        .collect();
1941}
1942
1943fn pl_prep_list() -> Vec<String> {
1944    return vec![
1945        "about",
1946        "above",
1947        "across",
1948        "after",
1949        "among",
1950        "around",
1951        "at",
1952        "athwart",
1953        "before",
1954        "behind",
1955        "below",
1956        "beneath",
1957        "beside",
1958        "besides",
1959        "between",
1960        "betwixt",
1961        "beyond",
1962        "but",
1963        "by",
1964        "during",
1965        "except",
1966        "for",
1967        "from",
1968        "in",
1969        "into",
1970        "near",
1971        "of",
1972        "off",
1973        "on",
1974        "onto",
1975        "out",
1976        "over",
1977        "since",
1978        "till",
1979        "to",
1980        "under",
1981        "until",
1982        "unto",
1983        "upon",
1984        "with"
1985    ]
1986        .iter()
1987        .map(|s| s.to_string())
1988        .collect();
1989}
1990
1991fn pl_prep_list_da() -> Vec<String> {
1992    let mut concat = pl_prep_list();
1993    concat.push("de".to_string());
1994    concat.push("du".to_string());
1995    concat.push("da".to_string());
1996    return concat;
1997}
1998
1999fn pl_prep_bysize() -> HashMap<usize, HashSet<String>> {
2000    return bysize(pl_prep_list_da());
2001}
2002
2003fn pl_prep() -> String {
2004    return enclose(&pl_prep_list_da().join("|"));
2005}
2006
2007fn pl_sb_prep_dual_compound() -> String {
2008    return format!(r"(.*?)((?:-|\s+)(?:{})(?:-|\s+))a(?:-|\s+)(.*)", pl_prep());
2009}
2010
2011fn singular_pronoun_genders() -> Vec<String> {
2012    return vec![
2013        "neuter",
2014        "feminine",
2015        "masculine",
2016        "gender-neutral",
2017        "feminine or masculine",
2018        "masculine or feminine"
2019    ]
2020        .iter()
2021        .map(|s| s.to_string())
2022        .collect();
2023}
2024
2025fn pl_pron_nom() -> HashMap<String, String> {
2026    return vec![
2027        ("i", "we"),
2028        ("myself", "ourselves"),
2029        ("you", "you"),
2030        ("yourself", "yourselves"),
2031        ("she", "they"),
2032        ("herself", "themselves"),
2033        ("he", "they"),
2034        ("himself", "themselves"),
2035        ("it", "they"),
2036        ("itself", "themselves"),
2037        ("they", "they"),
2038        ("themself", "themselves"),
2039        ("mine", "ours"),
2040        ("yours", "yours"),
2041        ("hers", "theirs"),
2042        ("his", "theirs"),
2043        ("its", "theirs"),
2044        ("theirs", "theirs")
2045    ]
2046        .iter()
2047        .map(|&(k, v)| (k.to_string(), v.to_string()))
2048        .collect();
2049}
2050
2051fn pl_pron_acc() -> HashMap<String, String> {
2052    return vec![
2053        ("me", "us"),
2054        ("myself", "ourselves"),
2055        ("you", "you"),
2056        ("yourself", "yourselves"),
2057        ("her", "them"),
2058        ("herself", "themselves"),
2059        ("it", "them"),
2060        ("itself", "themselves"),
2061        ("them", "them"),
2062        ("themself", "themselves")
2063    ]
2064        .iter()
2065        .map(|&(k, v)| (k.to_string(), v.to_string()))
2066        .collect();
2067}
2068
2069fn pl_pron_acc_keys() -> String {
2070    return enclose(&pl_pron_acc().keys().cloned().collect::<Vec<String>>().join("|"));
2071}
2072
2073fn pl_pron_acc_keys_bysize() -> HashMap<usize, HashSet<String>> {
2074    return bysize(pl_pron_acc().keys().cloned().collect::<Vec<String>>());
2075}
2076
2077fn pron_tuples() -> Vec<(&'static str, &'static str, &'static str, &'static str)> {
2078    return vec![
2079        ("nom", "they", "neuter", "it"),
2080        ("nom", "they", "feminine", "she"),
2081        ("nom", "they", "masculine", "he"),
2082        ("nom", "they", "gender-neutral", "they"),
2083        ("nom", "they", "feminine or masculine", "she or he"),
2084        ("nom", "they", "masculine or feminine", "he or she"),
2085        ("nom", "themselves", "neuter", "itself"),
2086        ("nom", "themselves", "feminine", "herself"),
2087        ("nom", "themselves", "masculine", "himself"),
2088        ("nom", "themselves", "gender-neutral", "themself"),
2089        ("nom", "themselves", "feminine or masculine", "herself or himself"),
2090        ("nom", "themselves", "masculine or feminine", "himself or herself"),
2091        ("nom", "theirs", "neuter", "its"),
2092        ("nom", "theirs", "feminine", "hers"),
2093        ("nom", "theirs", "masculine", "his"),
2094        ("nom", "theirs", "gender-neutral", "theirs"),
2095        ("nom", "theirs", "feminine or masculine", "hers or his"),
2096        ("nom", "theirs", "masculine or feminine", "his or hers"),
2097        ("acc", "them", "neuter", "it"),
2098        ("acc", "them", "feminine", "her"),
2099        ("acc", "them", "masculine", "him"),
2100        ("acc", "them", "gender-neutral", "them"),
2101        ("acc", "them", "feminine or masculine", "her or him"),
2102        ("acc", "them", "masculine or feminine", "him or her"),
2103        ("acc", "themselves", "neuter", "itself"),
2104        ("acc", "themselves", "feminine", "herself"),
2105        ("acc", "themselves", "masculine", "himself"),
2106        ("acc", "themselves", "gender-neutral", "themself"),
2107        ("acc", "themselves", "feminine or masculine", "herself or himself"),
2108        ("acc", "themselves", "masculine or feminine", "himself or herself")
2109    ];
2110}
2111
2112fn si_pron() -> HashMap<String, HashMap<String, HashMap<String, String>>> {
2113    let mut si_pron: HashMap<String, HashMap<String, HashMap<String, String>>> = HashMap::new();
2114    let mut nom: HashMap<String, HashMap<String, String>> = HashMap::new();
2115    for (k, v) in pl_pron_nom() {
2116        let mut entry = HashMap::new();
2117        entry.insert(k.to_string(), v.to_string());
2118        nom.insert(k.to_string(), entry);
2119    }
2120    //nom.insert("we".to_string(), "I".to_string());
2121    let mut acc: HashMap<String, HashMap<String, String>> = HashMap::new();
2122    for (k, v) in pl_pron_acc() {
2123        let mut entry = HashMap::new();
2124        entry.insert(k.to_string(), v.to_string());
2125        acc.insert(k.to_string(), entry);
2126    }
2127    si_pron.insert("nom".to_string(), nom);
2128    si_pron.insert("acc".to_string(), acc);
2129
2130    for data in pron_tuples() {
2131        let (this_case, this_plur, this_gend, this_sing) = data;
2132        let case = si_pron.entry(this_case.to_string()).or_insert_with(HashMap::new);
2133        let plur = case.entry(this_plur.to_string()).or_insert_with(HashMap::new);
2134        plur.insert(this_gend.to_string(), this_sing.to_string());
2135    }
2136
2137    si_pron
2138}
2139
2140pub fn get_si_pron(thecase: &str, word: &str, gender: Option<&str>) -> String {
2141    match si_pron().get(thecase) {
2142        Some(case) =>
2143            match case.get(word) {
2144                Some(sing) =>
2145                    match sing.get(gender.unwrap_or("N/A")) {
2146                        Some(specific) => specific.clone(),
2147                        None => sing.clone().values().next().unwrap().clone(),
2148                    }
2149                None => panic!("No such case for word: {}", word),
2150            }
2151        None => panic!("No such case: {}", thecase),
2152    }
2153}
2154
2155fn plverb_irregular_pres() -> HashMap<String, String> {
2156    return vec![
2157        ("am", "are"),
2158        ("are", "are"),
2159        ("is", "are"),
2160        ("was", "were"),
2161        ("were", "were"),
2162        ("have", "have"),
2163        ("has", "have"),
2164        ("do", "do"),
2165        ("does", "do")
2166    ]
2167        .iter()
2168        .map(|&(k, v)| (k.to_string(), v.to_string()))
2169        .collect();
2170}
2171
2172fn plverb_ambiguous_pres() -> HashMap<String, String> {
2173    return vec![
2174        ("act", "act"),
2175        ("acts", "act"),
2176        ("blame", "blame"),
2177        ("blames", "blame"),
2178        ("can", "can"),
2179        ("must", "must"),
2180        ("fly", "fly"),
2181        ("flies", "fly"),
2182        ("copy", "copy"),
2183        ("copies", "copy"),
2184        ("drink", "drink"),
2185        ("drinks", "drink"),
2186        ("fight", "fight"),
2187        ("fights", "fight"),
2188        ("fire", "fire"),
2189        ("fires", "fire"),
2190        ("like", "like"),
2191        ("likes", "like"),
2192        ("look", "look"),
2193        ("looks", "look"),
2194        ("make", "make"),
2195        ("makes", "make"),
2196        ("reach", "reach"),
2197        ("reaches", "reach"),
2198        ("run", "run"),
2199        ("runs", "run"),
2200        ("sink", "sink"),
2201        ("sinks", "sink"),
2202        ("sleep", "sleep"),
2203        ("sleeps", "sleep"),
2204        ("view", "view"),
2205        ("views", "view")
2206    ]
2207        .iter()
2208        .map(|&(k, v)| (k.to_string(), v.to_string()))
2209        .collect();
2210}
2211
2212fn plverb_ambiguous_pres_keys() -> Regex {
2213    let pattern = format!(
2214        r"^({})((\s.*)?)$",
2215        enclose(&plverb_ambiguous_pres().keys().cloned().collect::<Vec<String>>().join("|"))
2216    );
2217    return Regex::new(&pattern).expect("Failed to compile regex");
2218}
2219
2220fn plverb_irregular_non_pres() -> Vec<String> {
2221    return vec![
2222        "did",
2223        "had",
2224        "ate",
2225        "made",
2226        "put",
2227        "spent",
2228        "fought",
2229        "sank",
2230        "gave",
2231        "sought",
2232        "shall",
2233        "could",
2234        "ought",
2235        "should"
2236    ]
2237        .iter()
2238        .map(|s| s.to_string())
2239        .collect();
2240}
2241
2242fn plverb_ambiguous_non_pres() -> Regex {
2243    let pattern = format!(r"^((?:thought|saw|bent|will|might|cut))((\s.*)?)$");
2244    return Regex::new(&pattern).expect("Failed to compile regex");
2245}
2246
2247fn pl_v_oes_oe() -> Vec<String> {
2248    return vec!["canoes", "floes", "oboes", "roes", "throes", "woes"]
2249        .iter()
2250        .map(|s| s.to_string())
2251        .collect();
2252}
2253
2254fn pl_v_oes_oe_endings_size4() -> Vec<String> {
2255    return vec!["hoes", "toes"]
2256        .iter()
2257        .map(|s| s.to_string())
2258        .collect();
2259}
2260
2261fn pl_v_oes_oe_endings_size5() -> Vec<String> {
2262    return vec!["shoes"]
2263        .iter()
2264        .map(|s| s.to_string())
2265        .collect();
2266}
2267
2268fn pl_count_zero() -> Vec<String> {
2269    return vec!["0", "no", "zero", "nil"]
2270        .iter()
2271        .map(|s| s.to_string())
2272        .collect();
2273}
2274
2275fn pl_count_one() -> Vec<String> {
2276    return vec!["1", "a", "an", "one", "each", "every", "this", "that"]
2277        .iter()
2278        .map(|s| s.to_string())
2279        .collect();
2280}
2281
2282fn pl_adj_special() -> HashMap<String, String> {
2283    return vec![("a", "some"), ("an", "some"), ("this", "these"), ("that", "those")]
2284        .iter()
2285        .map(|&(k, v)| (k.to_string(), v.to_string()))
2286        .collect();
2287}
2288
2289fn pl_adj_special_keys() -> Regex {
2290    let pattern = format!(
2291        r"^({})$",
2292        enclose(&pl_adj_special().keys().cloned().collect::<Vec<String>>().join("|"))
2293    );
2294    return Regex::new(&pattern).expect("Failed to compile regex");
2295}
2296
2297fn pl_adj_poss() -> HashMap<String, String> {
2298    return vec![
2299        ("my", "our"),
2300        ("your", "your"),
2301        ("its", "their"),
2302        ("her", "their"),
2303        ("his", "their"),
2304        ("their", "their")
2305    ]
2306        .iter()
2307        .map(|&(k, v)| (k.to_string(), v.to_string()))
2308        .collect();
2309}
2310
2311fn pl_adj_poss_keys() -> Regex {
2312    let pattern = format!(
2313        r"^({})$",
2314        enclose(&pl_adj_poss().keys().cloned().collect::<Vec<String>>().join("|"))
2315    );
2316    return Regex::new(&pattern).expect("Failed to compile regex");
2317}
2318
2319fn a_abbrev() -> Regex {
2320    return Regex::new(
2321        r"^(?:FJO|[HLMNS]Y\.|RY[EO]|SQU|(?:F[LR]?|[HL]|MN?|N|RH?|S[CHKLMNPTVW]?|X(?:YL)?) [AEIOU])[FHLMNRSX][A-Z]"
2322    ).expect("Failed to compile regex");
2323}
2324
2325fn a_y_cons() -> Regex {
2326    return Regex::new(r"^(y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt))").expect(
2327        "Failed to compile regex"
2328    );
2329}
2330
2331fn a_explicit_a() -> Regex {
2332    return Regex::new(r"^((?:unabomber|unanimous|US))").expect("Failed to compile regex");
2333}
2334
2335fn a_explicit_an() -> Regex {
2336    return Regex::new(r"^((?:euler|hour(?!i)|heir|honest|hono[ur]|mpeg))").expect(
2337        "Failed to compile regex"
2338    );
2339}
2340
2341fn a_ordinal_a() -> Regex {
2342    return Regex::new(r"^([aefhilmnorsx]-?th)").expect("Failed to compile regex");
2343}
2344
2345fn a_ordinal_an() -> Regex {
2346    return Regex::new(r"^([bcdgjkpqtuvwyz]-?th)").expect("Failed to compile regex");
2347}
2348
2349fn nth() -> HashMap<u32, String> {
2350    return vec![
2351        (0, "th"),
2352        (1, "st"),
2353        (2, "nd"),
2354        (3, "rd"),
2355        (4, "th"),
2356        (5, "th"),
2357        (6, "th"),
2358        (7, "th"),
2359        (8, "th"),
2360        (9, "th"),
2361        (11, "th"),
2362        (12, "th"),
2363        (13, "th")
2364    ]
2365        .iter()
2366        .map(|&(k, v)| (k, v.to_string()))
2367        .collect();
2368}
2369
2370fn nth_suff() -> HashSet<String> {
2371    return nth().values().cloned().collect();
2372}
2373
2374fn ordinal() -> HashMap<String, String> {
2375    return vec![
2376        ("ty", "tieth"),
2377        ("one", "first"),
2378        ("two", "second"),
2379        ("three", "third"),
2380        ("five", "fifth"),
2381        ("eight", "eighth"),
2382        ("nine", "ninth"),
2383        ("twelve", "twelfth")
2384    ]
2385        .iter()
2386        .map(|&(k, v)| (k.to_string(), v.to_string()))
2387        .collect();
2388}
2389
2390pub fn ordinal_suff() -> Regex {
2391    let pattern = format!("({})", ordinal().keys().cloned().collect::<Vec<String>>().join("|"));
2392    return Regex::new(&format!("{}\\z", pattern)).expect("Failed to compile regex");
2393}
2394
2395fn unit() -> Vec<String> {
2396    return vec!["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
2397        .iter()
2398        .map(|s| s.to_string())
2399        .collect();
2400}
2401
2402fn teen() -> Vec<String> {
2403    return vec![
2404        "ten",
2405        "eleven",
2406        "twelve",
2407        "thirteen",
2408        "fourteen",
2409        "fifteen",
2410        "sixteen",
2411        "seventeen",
2412        "eighteen",
2413        "nineteen"
2414    ]
2415        .iter()
2416        .map(|s| s.to_string())
2417        .collect();
2418}
2419
2420fn ten() -> Vec<String> {
2421    return vec![
2422        "",
2423        "",
2424        "twenty",
2425        "thirty",
2426        "forty",
2427        "fifty",
2428        "sixty",
2429        "seventy",
2430        "eighty",
2431        "ninety"
2432    ]
2433        .iter()
2434        .map(|s| s.to_string())
2435        .collect();
2436}
2437
2438fn mill() -> Vec<String> {
2439    return vec![
2440        " ",
2441        " thousand",
2442        " million",
2443        " billion",
2444        " trillion",
2445        " quadrillion",
2446        " quintillion",
2447        " sextillion",
2448        " septillion",
2449        " octillion",
2450        " nonillion",
2451        " decillion"
2452    ]
2453        .iter()
2454        .map(|s| s.to_string())
2455        .collect();
2456}
2457
2458// fn def_classical()