Skip to main content

malachite_base/strings/
random.rs

1// Copyright © 2026 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::random::{RandomCharRange, random_chars};
10use crate::num::random::geometric::GeometricRandomNaturalValues;
11use crate::random::Seed;
12use crate::strings::StringsFromCharVecs;
13use crate::vecs::random::{
14    RandomFixedLengthVecsFromSingle, RandomVecs, random_vecs, random_vecs_fixed_length_from_single,
15};
16
17/// Randomly generates [`String`]s of a given length using [`char`]s from a single iterator.
18///
19/// The probability of a particular length-$n$ [`String`] being generated is the product of the
20/// probabilities of each of its `char`s.
21///
22/// If `len` is 0, the output consists of the empty [`String`], repeated.
23///
24/// `cs` must be infinite.
25///
26/// # Expected complexity per iteration
27/// $T(i) = O(\ell + T^\prime(i))$
28///
29/// $M(i) = O(\ell + M^\prime(i))$
30///
31/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
32/// $M^\prime$ are the time and memory functions of `cs`, and $\ell$ is `len`.
33///
34/// # Examples
35/// ```
36/// use itertools::Itertools;
37/// use malachite_base::chars::random::random_char_inclusive_range;
38/// use malachite_base::random::EXAMPLE_SEED;
39/// use malachite_base::strings::random::random_fixed_length_strings_using_chars;
40///
41/// let ss = random_fixed_length_strings_using_chars(
42///     2,
43///     random_char_inclusive_range(EXAMPLE_SEED, 'a', 'c'),
44/// )
45/// .take(10)
46/// .collect_vec();
47/// assert_eq!(
48///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
49///     &["ba", "bc", "bb", "ab", "ac", "ba", "bc", "ca", "ba", "cc"]
50/// );
51/// ```
52#[inline]
53pub const fn random_fixed_length_strings_using_chars<I: Iterator<Item = char>>(
54    len: u64,
55    cs: I,
56) -> StringsFromCharVecs<RandomFixedLengthVecsFromSingle<I>> {
57    StringsFromCharVecs {
58        css: random_vecs_fixed_length_from_single(len, cs),
59    }
60}
61
62/// Randomly generates [`String`]s of a given length.
63///
64/// The probability of a particular length-$n$ [`String`] being generated is $1112064^{-\ell}$,
65/// where $\ell$ is `len`.
66///
67/// If `len` is 0, the output consists of the empty [`String`], repeated.
68///
69/// # Expected complexity per iteration
70/// $T(n) = O(n)$
71///
72/// $M(n) = O(n)$
73///
74/// where $T$ is time, $M$ is additional memory, and $n$ is `len`.
75///
76/// # Examples
77/// ```
78/// use itertools::Itertools;
79/// use malachite_base::random::EXAMPLE_SEED;
80/// use malachite_base::strings::random::random_fixed_length_strings;
81///
82/// let ss = random_fixed_length_strings(EXAMPLE_SEED, 2)
83///     .take(10)
84///     .collect_vec();
85/// assert_eq!(
86///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
87///     &[
88///         "\u{5f771}\u{87234}",
89///         "\u{bcd36}\u{9e195}",
90///         "\u{5da07}\u{36553}",
91///         "\u{45028}\u{1cdfd}",
92///         "\u{d8530}\u{c7f2e}",
93///         "\u{ba4bc}\u{ff677}",
94///         "\u{a12e2}\u{d775c}",
95///         "\u{f827b}\u{bdf7a}",
96///         "簅\u{15aca}",
97///         "\u{4e5e2}\u{bb286}"
98///     ]
99/// );
100/// ```
101#[inline]
102pub fn random_fixed_length_strings(
103    seed: Seed,
104    len: u64,
105) -> StringsFromCharVecs<RandomFixedLengthVecsFromSingle<RandomCharRange>> {
106    random_fixed_length_strings_using_chars(len, random_chars(seed))
107}
108
109/// Generates random [`String`]s using [`char`]s from an iterator.
110///
111/// The lengths of the [`String`]s are sampled from a geometric distribution with a specified mean
112/// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0.
113///
114/// $$
115/// P((c_0, c_1, \ldots, c_{n-1})) = \frac{m^n}{(m+1)^{n+1}}\prod_{i=0}^{n-1}P(c_i).
116/// $$
117///
118/// The iterators produced by `cs_gen` must be infinite.
119///
120/// # Expected complexity per iteration
121/// $T(i) = O(m + T^\prime(i))$
122///
123/// $M(i) = O(m + M^\prime(i))$
124///
125/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
126/// $M^\prime$ are the time and memory functions of `cs`, and $m$ is `mean_length_numerator /
127/// mean_length_denominator`.
128///
129/// # Panics
130/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being
131/// reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
132///
133/// # Examples
134/// ```
135/// use itertools::Itertools;
136/// use malachite_base::chars::random::random_char_inclusive_range;
137/// use malachite_base::random::EXAMPLE_SEED;
138/// use malachite_base::strings::random::random_strings_using_chars;
139///
140/// let ss = random_strings_using_chars(
141///     EXAMPLE_SEED,
142///     &|seed| random_char_inclusive_range(seed, 'x', 'z'),
143///     4,
144///     1,
145/// )
146/// .take(10)
147/// .collect_vec();
148/// assert_eq!(
149///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
150///     &["", "yyyyzxxxzxzxzx", "zzzy", "xzzx", "y", "", "zyzxz", "zy", "zyyx", ""]
151/// );
152/// ```
153#[inline]
154pub fn random_strings_using_chars<I: Iterator<Item = char>>(
155    seed: Seed,
156    cs_gen: &dyn Fn(Seed) -> I,
157    mean_length_numerator: u64,
158    mean_length_denominator: u64,
159) -> StringsFromCharVecs<RandomVecs<char, GeometricRandomNaturalValues<u64>, I>> {
160    StringsFromCharVecs {
161        css: random_vecs(seed, cs_gen, mean_length_numerator, mean_length_denominator),
162    }
163}
164
165/// Generates random [`String`]s.
166///
167/// The lengths of the [`String`]s are sampled from a geometric distribution with a specified mean
168/// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0.
169///
170/// $$
171/// P((c_0, c_1, \ldots, c_{n-1})) = \frac{m^n}{1112064^n(m+1)^{n+1}}
172/// $$
173///
174/// # Expected complexity per iteration
175/// $T(m) = O(m)$
176///
177/// $M(m) = O(m)$
178///
179/// where $T$ is time, $M$ is additional memory, and $m$ is `mean_length_numerator /
180/// mean_length_denominator`.
181///
182/// # Panics
183/// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being
184/// reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
185///
186/// # Examples
187/// ```
188/// use itertools::Itertools;
189/// use malachite_base::random::EXAMPLE_SEED;
190/// use malachite_base::strings::random::random_strings;
191///
192/// let ss = random_strings(EXAMPLE_SEED, 4, 1).take(10).collect_vec();
193/// assert_eq!(
194///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
195///     &[
196///         "",
197///         "\u{81355}\u{a331d}\u{b707b}\u{1354b}\u{b16ac}𣙘\u{67377}\u{4aaa4}\u{a6d6e}\u{45616}\
198///         \u{7725f}\u{41e2d}\u{d6b59}\u{de165}",
199///         "\u{c2d29}\u{695af}\u{98fd7}\u{10ca51}",
200///         "\u{bec46}\u{c0bec}\u{cb677}\u{71318}",
201///         "\u{755e1}",
202///         "",
203///         "𫮜\u{a2f84}柂\u{f5560}\u{6737b}",
204///         "\u{8442e}\u{a6883}",
205///         "\u{49cf2}\u{32d2b}\u{1e6e5}\u{1084bd}",
206///         ""
207///     ]
208/// );
209/// ```
210#[inline]
211pub fn random_strings(
212    seed: Seed,
213    mean_length_numerator: u64,
214    mean_length_denominator: u64,
215) -> StringsFromCharVecs<RandomVecs<char, GeometricRandomNaturalValues<u64>, RandomCharRange>> {
216    random_strings_using_chars(
217        seed,
218        &random_chars,
219        mean_length_numerator,
220        mean_length_denominator,
221    )
222}