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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use HashSet;
use ;
use crate;
use crate*;
/// [`HashSet`] builder for [`dice::collection`].
///
/// [`dice::collection`]: dice::collection()
/// Generates a [`HashSet`] that uses a default pseudorandom [`BuildHasher`] and contains elements
/// of type `T`.
///
/// The range specifies the number of tries to generate distinct elements.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Hasher
///
/// [`HashSet`] requires a [`BuildHasher`] which determines the order of elements.
/// The default is [`RandomState`] and it has no deterministic constructor.
///
/// If deterministic behavior is required, you can use [`Prng`] as [`BuildHasher`]. Otherwise,
/// you can construct [`RandomState`] yourself.
///
/// ```
/// use std::collections::hash_map::RandomState;
///
/// use dicetest::prelude::*;
/// use dicetest::{Prng, Limit};
///
/// let mut prng = Prng::from_seed(0x5EED.into());
/// let limit = Limit::default();
/// let mut fate = Fate::new(&mut prng, limit);
///
/// let elem_die = dice::u8(..);
///
/// let hasher = fate.fork_prng();
/// let deterministic_set_die = dice::hash_set(hasher, &elem_die, ..);
///
/// let hasher = RandomState::new(); // Warning: not deterministic!
/// let non_deterministic_set_die = dice::hash_set(hasher, &elem_die, ..);
/// ```
///
/// [`Prng`]: crate::Prng
/// [`RandomState`]: std::collections::hash_map::RandomState
///
/// # Examples
///
/// ```
/// use dicetest::prelude::*;
/// use dicetest::{Prng, Limit};
///
/// let mut prng = Prng::from_seed(0x5EED.into());
/// let limit = Limit::default();
/// let mut fate = Fate::new(&mut prng, limit);
///
/// let elem_die = dice::u8(..);
///
/// let hasher = fate.fork_prng();
/// let set = fate.with_limit(100.into()).roll(dice::hash_set(hasher, &elem_die, ..));
/// assert!(set.len() <= 100);
///
/// let hasher = fate.fork_prng();
/// let set = fate.roll(dice::hash_set(hasher, &elem_die, ..=73));
/// assert!(set.len() <= 73);
///
/// let hasher = fate.fork_prng();
/// let set = fate.roll(dice::hash_set(hasher, &elem_die, 17..));
/// assert!(set.len() >= 17);
///
/// let hasher = fate.fork_prng();
/// let set = fate.roll(dice::hash_set(hasher, &elem_die, 42));
/// assert!(set.len() <= 42);
/// ```
/// Similar to [`dice::hash_set`] but each element is generated using only a random part of
/// [`Limit`].
///
/// If you want to generate a [`HashSet`] that contains other collections, then you should
/// consider using this generator for the outer [`HashSet`]. That way the overall length is
/// bounded by [`Limit`] (and not the square of [`Limit`]).
///
/// [`Limit`]: crate::Limit
/// [`dice::hash_set`]: dice::hash_set()
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Examples
///
/// ```
/// use dicetest::prelude::*;
/// use dicetest::{Prng, Limit};
///
/// let mut prng = Prng::from_seed(0x5EED.into());
/// let limit = Limit::default();
/// let mut fate = Fate::new(&mut prng, limit);
///
/// let elem_die = dice::u8(..);
/// let vec_die = dice::vec(elem_die, ..);
/// let hasher = fate.fork_prng();
/// let set_of_vecs_die = dice::outer_hash_set(hasher, vec_die, ..);
///
/// let set_of_vecs = fate.roll(set_of_vecs_die);
/// assert!(set_of_vecs.iter().flatten().count() <= 100);
/// ```