1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use bools::random::{weighted_random_bools, WeightedRandomBools};
use random::Seed;
/// Generates random [`Option`]s except `None`, with values from a given random iterator.
///
/// This `struct` is created by [`random_somes`]; see its documentation for more.
#[derive(Clone, Debug)]
pub struct RandomSomes<I: Iterator> {
xs: I,
}
impl<I: Iterator> Iterator for RandomSomes<I> {
type Item = Option<I::Item>;
#[inline]
fn next(&mut self) -> Option<Option<I::Item>> {
Some(self.xs.next())
}
}
/// Generates random [`Option`]s except `None`, with values from a given random iterator.
///
/// The values have the same distribution as the values generated by the given iterator: If $Q(x)$
/// is the probability of $x$ being generated by `xs`, then
///
/// $P(\operatorname{Some}(x)) = Q(x)$.
///
/// `xs` must be infinite.
///
/// The output length is infinite.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::num::random::random_primitive_ints;
/// use malachite_base::options::random::random_somes;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_base::strings::ToDebugString;
///
/// assert_eq!(
/// prefix_to_string(
/// random_somes(random_primitive_ints::<u8>(EXAMPLE_SEED)).map(|x| x.to_debug_string()),
/// 5
/// ),
/// "[Some(113), Some(239), Some(69), Some(108), Some(228), ...]",
/// )
/// ```
pub const fn random_somes<I: Iterator>(xs: I) -> RandomSomes<I> {
RandomSomes { xs }
}
/// Generates random [`Option`]s with values from a given random iterator.
///
/// We don't use [`WithSpecialValue`](crate::iterators::WithSpecialValue) here because that
/// requires `I::Item` to be cloneable. The "special value" in this case, `None`, can be produced
/// on demand without any cloning.
///
/// This `struct` is created by [`random_options`]; see its documentation for more.
#[derive(Clone, Debug)]
pub struct RandomOptions<I: Iterator> {
bs: WeightedRandomBools,
xs: I,
}
impl<I: Iterator> Iterator for RandomOptions<I> {
type Item = Option<I::Item>;
#[inline]
fn next(&mut self) -> Option<Option<I::Item>> {
Some(if self.bs.next().unwrap() {
self.xs.next()
} else {
None
})
}
}
/// Generates random [`Option`]s with values from a given random iterator.
///
/// The probability of generating `None` is specified by $p$ =
/// `none_p_numerator / none_p_denominator`. If a `Some` is generated, its values have the same
/// distribution as the values generated by the given iterator.
///
/// If $Q(x)$ is the probability of $x$ being generated by `xs`, then
///
/// $P(\text{None}) = p$
///
/// $P(\operatorname{Some}(x)) = (1-p)Q(x)$
///
/// `xs` must be infinite.
///
/// The output length is infinite.
///
/// # Panics
/// Panics if `none_p_denominator` is 0 or `none_p_numerator > none_p_denominator`.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::num::random::random_primitive_ints;
/// use malachite_base::options::random::random_options;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_base::strings::ToDebugString;
///
/// assert_eq!(
/// prefix_to_string(
/// random_options(EXAMPLE_SEED, 1, 2, &random_primitive_ints::<u8>)
/// .map(|x| x.to_debug_string()),
/// 10
/// ),
/// "[Some(85), Some(11), Some(136), None, Some(200), None, Some(235), Some(134), Some(203), \
/// None, ...]"
/// )
/// ```
pub fn random_options<I: Iterator>(
seed: Seed,
none_p_numerator: u64,
none_p_denominator: u64,
xs_gen: &dyn Fn(Seed) -> I,
) -> RandomOptions<I> {
RandomOptions {
bs: weighted_random_bools(
seed.fork("bs"),
none_p_denominator - none_p_numerator,
none_p_denominator,
),
xs: xs_gen(seed.fork("xs")),
}
}