malachite_base/strings/
exhaustive.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::chars::exhaustive::{ExhaustiveChars, exhaustive_chars};
10use crate::num::exhaustive::PrimitiveIntIncreasingRange;
11use crate::strings::{StringsFromCharVecs, strings_from_char_vecs};
12use crate::vecs::exhaustive::{
13    ExhaustiveFixedLengthVecs1Input, ExhaustiveVecs, LexFixedLengthVecsFromSingle, ShortlexVecs,
14    exhaustive_vecs, exhaustive_vecs_fixed_length_from_single, lex_vecs_fixed_length_from_single,
15    shortlex_vecs,
16};
17
18/// Generates all [`String`]s of a given length with [`char`]s from a single iterator, in
19/// lexicographic order.
20///
21/// The order is lexicographic with respect to the order of the element iterator.
22///
23/// `cs` must be finite.
24///
25/// The output length is $\ell^n$, where $\ell$ is `cs.count()` and $n$ is `len`.
26///
27/// If `len` is 0, the output consists of one empty [`String`].
28///
29/// If `cs` is empty, the output is also empty, unless `len` is 0.
30///
31/// # Examples
32/// ```
33/// use itertools::Itertools;
34/// use malachite_base::strings::exhaustive::lex_fixed_length_strings_using_chars;
35///
36/// let ss = lex_fixed_length_strings_using_chars(2, ['c', 'a', 't'].iter().cloned()).collect_vec();
37/// assert_eq!(
38///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
39///     &["cc", "ca", "ct", "ac", "aa", "at", "tc", "ta", "tt"]
40/// );
41/// ```
42#[inline]
43pub fn lex_fixed_length_strings_using_chars<I: Iterator<Item = char>>(
44    len: u64,
45    cs: I,
46) -> StringsFromCharVecs<LexFixedLengthVecsFromSingle<I>> {
47    strings_from_char_vecs(lex_vecs_fixed_length_from_single(len, cs))
48}
49
50/// Generates all [`String`]s of a given length in lexicographic order.
51///
52/// The order is lexicographic with respect to the order of [`exhaustive_chars`], which is not the
53/// default lexicographic order for [`char`]s. (For example, the first characters are not control
54/// characters, but lowercase Latin letters.) If you want the default [`char`] order, use
55/// `lex_fixed_length_strings_using_chars(len, chars_increasing())`.
56///
57/// The output length is $1112064^n$, where $n$ is `len`.
58///
59/// If `len` is 0, the output consists of one empty [`String`].
60///
61/// # Complexity per iteration
62/// $T(i, n) = O(n)$
63///
64/// $M(i, n) = O(n)$
65///
66/// where $T$ is time, $M$ is additional memory, and $n$ is `len`.
67///
68/// # Examples
69/// ```
70/// use itertools::Itertools;
71/// use malachite_base::strings::exhaustive::lex_fixed_length_strings;
72///
73/// let ss = lex_fixed_length_strings(2).take(20).collect_vec();
74/// assert_eq!(
75///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
76///     &[
77///         "aa", "ab", "ac", "ad", "ae", "af", "ag", "ah", "ai", "aj", "ak", "al", "am", "an",
78///         "ao", "ap", "aq", "ar", "as", "at"
79///     ]
80/// );
81/// ```
82#[inline]
83pub fn lex_fixed_length_strings(
84    len: u64,
85) -> StringsFromCharVecs<LexFixedLengthVecsFromSingle<ExhaustiveChars>> {
86    lex_fixed_length_strings_using_chars(len, exhaustive_chars())
87}
88
89/// Generates all `String`s of a given length with [`char`]s from a single iterator.
90///
91/// If `cs` is finite, the output length is $\ell^n$, where $\ell$ is `cs.count()` and $n$ is `len`.
92/// If `cs` is infinite, the output is also infinite.
93///
94/// If `len` is 0, the output consists of one empty [`String`].
95///
96/// If `cs` is empty, the output is also empty, unless `len` is 0.
97///
98/// # Examples
99/// ```
100/// use itertools::Itertools;
101/// use malachite_base::strings::exhaustive::exhaustive_fixed_length_strings_using_chars;
102///
103/// let ss = exhaustive_fixed_length_strings_using_chars(2, ['c', 'a', 't'].iter().cloned())
104///     .collect_vec();
105/// assert_eq!(
106///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
107///     &["cc", "ca", "ac", "aa", "ct", "at", "tc", "ta", "tt"]
108/// );
109/// ```
110#[inline]
111pub fn exhaustive_fixed_length_strings_using_chars<I: Iterator<Item = char>>(
112    len: u64,
113    cs: I,
114) -> StringsFromCharVecs<ExhaustiveFixedLengthVecs1Input<I>> {
115    strings_from_char_vecs(exhaustive_vecs_fixed_length_from_single(len, cs))
116}
117
118/// Generates all [`String`]s of a given length.
119///
120/// The output length is $1112064^n$, where $n$ is `len`.
121///
122/// If `len` is 0, the output consists of one empty [`String`].
123///
124/// # Examples
125/// ```
126/// use itertools::Itertools;
127/// use malachite_base::strings::exhaustive::exhaustive_fixed_length_strings;
128///
129/// let ss = exhaustive_fixed_length_strings(2).take(20).collect_vec();
130/// assert_eq!(
131///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
132///     &[
133///         "aa", "ab", "ba", "bb", "ac", "ad", "bc", "bd", "ca", "cb", "da", "db", "cc", "cd",
134///         "dc", "dd", "ae", "af", "be", "bf"
135///     ]
136/// );
137/// ```
138#[inline]
139pub fn exhaustive_fixed_length_strings(
140    len: u64,
141) -> StringsFromCharVecs<ExhaustiveFixedLengthVecs1Input<ExhaustiveChars>> {
142    exhaustive_fixed_length_strings_using_chars(len, exhaustive_chars())
143}
144
145/// Generates [`String`]s with [`char`]s from a specified iterator, in shortlex order.
146///
147/// Shortlex order means that the [`String`]s are output from shortest to longest, and [`String`]s
148/// of the same length are output in lexicographic order with respect to the ordering of the
149/// [`char`]s specified by the input iterator.
150///
151/// `cs` must be finite; if it's infinite, only [`String`]s of length 0 and 1 are ever produced.
152///
153/// If `cs` is empty, the output length is 1; otherwise, the output is infinite.
154///
155/// The lengths of the output [`String`]s grow logarithmically.
156///
157/// # Complexity per iteration
158/// $T(i) = O(\log i)$
159///
160/// $M(i) = O(\log i)$
161///
162/// where $T$ is time and $M$ is additional memory.
163///
164/// # Examples
165/// ```
166/// use itertools::Itertools;
167/// use malachite_base::strings::exhaustive::shortlex_strings_using_chars;
168///
169/// let ss = shortlex_strings_using_chars('x'..='z')
170///     .take(20)
171///     .collect_vec();
172/// assert_eq!(
173///     ss.iter().map(String::as_str).collect_vec().as_slice(),
174///     &[
175///         "", "x", "y", "z", "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz", "xxx", "xxy",
176///         "xxz", "xyx", "xyy", "xyz", "xzx"
177///     ]
178/// );
179/// ```
180#[inline]
181pub fn shortlex_strings_using_chars<I: Clone + Iterator<Item = char>>(
182    cs: I,
183) -> StringsFromCharVecs<ShortlexVecs<char, PrimitiveIntIncreasingRange<u64>, I>> {
184    strings_from_char_vecs(shortlex_vecs(cs))
185}
186
187/// Generates [`String`]s in shortlex order.
188///
189/// Shortlex order means that the [`String`]s are output from shortest to longest, and [`String`]s
190/// of the same length are output in lexicographic order with respect to the order of
191/// [`exhaustive_chars`], which is not the default lexicographic order for [`char`]s. (For example,
192/// the first characters are not control characters, but lowercase Latin letters.) If you want the
193/// default [`char`] order, use `shortlex_strings_using_chars(chars_increasing())`.
194///
195/// The output is infinite.
196///
197/// The lengths of the output [`String`]s grow logarithmically.
198///
199/// # Complexity per iteration
200/// $T(i) = O(\log i)$
201///
202/// $M(i) = O(\log i)$
203///
204/// where $T$ is time and $M$ is additional memory.
205///
206/// # Examples
207/// ```
208/// use itertools::Itertools;
209/// use malachite_base::strings::exhaustive::shortlex_strings;
210///
211/// let ss = shortlex_strings().take(20).collect_vec();
212/// assert_eq!(
213///     ss.iter().map(String::as_str).collect_vec().as_slice(),
214///     &[
215///         "", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
216///         "q", "r", "s"
217///     ]
218/// );
219/// ```
220#[inline]
221pub fn shortlex_strings()
222-> StringsFromCharVecs<ShortlexVecs<char, PrimitiveIntIncreasingRange<u64>, ExhaustiveChars>> {
223    shortlex_strings_using_chars(exhaustive_chars())
224}
225
226/// Generates all [`String`]s with [`char`]s from a specified iterator.
227///
228/// If `cs` is empty, the output length is 1; otherwise, the output is infinite.
229///
230/// The lengths of the output [`String`]s grow logarithmically.
231///
232/// # Complexity per iteration
233/// $T(i) = O(\log i)$
234///
235/// $M(i) = O(\log i)$
236///
237/// where $T$ is time and $M$ is additional memory.
238///
239/// # Examples
240/// ```
241/// use itertools::Itertools;
242/// use malachite_base::strings::exhaustive::exhaustive_strings_using_chars;
243///
244/// let ss = exhaustive_strings_using_chars('x'..='z')
245///     .take(20)
246///     .collect_vec();
247/// assert_eq!(
248///     ss.iter().map(String::as_str).collect_vec().as_slice(),
249///     &[
250///         "", "x", "y", "xxx", "z", "xx", "xy", "xxxxx", "yx", "xxy", "yy", "xxxx", "xz", "xyx",
251///         "yz", "xxxxxx", "zx", "xyy", "zy", "xxxy"
252///     ]
253/// );
254/// ```
255#[inline]
256pub fn exhaustive_strings_using_chars<I: Clone + Iterator<Item = char>>(
257    cs: I,
258) -> StringsFromCharVecs<ExhaustiveVecs<char, PrimitiveIntIncreasingRange<u64>, I>> {
259    strings_from_char_vecs(exhaustive_vecs(cs))
260}
261
262/// Generates all [`String`]s.
263///
264/// The lengths of the output [`String`]s grow logarithmically.
265///
266/// # Complexity per iteration
267/// $T(i) = O(\log i)$
268///
269/// $M(i) = O(\log i)$
270///
271/// where $T$ is time and $M$ is additional memory.
272///
273/// # Examples
274/// ```
275/// use itertools::Itertools;
276/// use malachite_base::strings::exhaustive::exhaustive_strings;
277///
278/// let ss = exhaustive_strings().take(20).collect_vec();
279/// assert_eq!(
280///     ss.iter().map(String::as_str).collect_vec().as_slice(),
281///     &[
282///         "", "a", "b", "aaa", "c", "aa", "d", "aaaa", "e", "ab", "f", "aab", "g", "ba", "h",
283///         "aaaaa", "i", "bb", "j", "aba"
284///     ]
285/// );
286/// ```
287#[inline]
288pub fn exhaustive_strings()
289-> StringsFromCharVecs<ExhaustiveVecs<char, PrimitiveIntIncreasingRange<u64>, ExhaustiveChars>> {
290    exhaustive_strings_using_chars(exhaustive_chars())
291}