Skip to content

Commit 7f5d079

Browse files
author
electricessence
committed
Updated random functions
1 parent 6a65052 commit 7f5d079

3 files changed

Lines changed: 190 additions & 71 deletions

File tree

Open.Numeric.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Part of the "Open" set of libraries.</Description>
1616
<PackageProjectUrl>https://github.com/electricessence/Open.Numeric/</PackageProjectUrl>
1717
<RepositoryType>git</RepositoryType>
1818
<PackageTags>dotnet, dotnetcore, cs, numbers, double, float, precision, extensions</PackageTags>
19-
<Version>1.0.2</Version>
19+
<Version>1.0.5</Version>
2020
</PropertyGroup>
2121

2222
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

Random.cs

Lines changed: 150 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,76 +19,169 @@ public static Random Random
1919
return R.Value;
2020
}
2121
}
22-
public static T RandomSelectOne<T>(this IList<T> source)
23-
{
24-
return source[R.Value.Next(source.Count)];
25-
}
26-
public static T RandomPluck<T>(this IList<T> source)
22+
23+
24+
public static bool TryRandomPluck<T>(this LinkedList<T> source, out T value)
2725
{
28-
var e = source[R.Value.Next(source.Count)];
29-
source.Remove(e);
30-
return e;
26+
if (source.Count == 0)
27+
{
28+
value = default(T);
29+
return false;
30+
}
31+
32+
var r = R.Value.Next(source.Count);
33+
var node = source.First;
34+
for (var i = 0; i <= r; i++)
35+
node = node.Next;
36+
value = node.Value;
37+
source.Remove(node);
38+
return true;
3139
}
3240

33-
public static T RandomSelectOne<T>(this T[] source)
41+
public static T RandomPluck<T>(this LinkedList<T> source)
3442
{
35-
return source[R.Value.Next(source.Length)];
43+
if (source.TryRandomPluck(out T value))
44+
return value;
45+
46+
throw new InvalidOperationException("Source collection is empty.");
3647
}
37-
public static T RandomSelectOne<T>(this ICollection<T> source)
48+
49+
public static bool TryRandomPluck<T>(this IList<T> source, out T value)
3850
{
39-
return source.Skip(R.Value.Next(source.Count)).First();
51+
if (source.Count == 0)
52+
{
53+
value = default(T);
54+
return false;
55+
}
56+
57+
var r = R.Value.Next(source.Count);
58+
value = source[r];
59+
source.RemoveAt(r);
60+
return true;
4061
}
41-
public static T RandomSelectOne<T>(this IEnumerable<T> source)
62+
63+
public static T RandomPluck<T>(this IList<T> source)
4264
{
43-
return source.Skip(R.Value.Next(source.Count())).First();
65+
if (source.TryRandomPluck(out T value))
66+
return value;
67+
68+
throw new InvalidOperationException("Source collection is empty.");
4469
}
4570

46-
public static int NextRandomIntegerExcluding(
47-
int range,
48-
HashSet<int> excludeSet)
71+
public static bool TryRandomSelectOne<T>(
72+
this IReadOnlyList<T> source,
73+
out T value,
74+
ISet<T> excluding = null)
4975
{
50-
if (range < 0)
51-
throw new ArgumentOutOfRangeException("range", range, "Must be a number greater than zero.");
52-
var r = new List<int>();
76+
var count = source.Count;
77+
if (count == 0)
78+
{
79+
value = default(T);
80+
return false;
81+
}
5382

54-
for (var i = 0; i < range; ++i)
83+
if (excluding == null || excluding.Count == 0)
5584
{
56-
if (!excludeSet.Contains(i)) r.Add(i);
85+
value = source[R.Value.Next(count)];
86+
return true;
5787
}
5888

59-
return r.RandomSelectOne();
89+
return source
90+
.Where(o => !excluding.Contains(o))
91+
.ToArray()
92+
.TryRandomSelectOne(out value);
6093
}
6194

62-
public static uint NextRandomIntegerExcluding(
63-
uint range,
64-
HashSet<uint> excludeSet)
95+
public static T RandomSelectOne<T>(
96+
this IReadOnlyList<T> source,
97+
ISet<T> excluding = null)
6598
{
66-
var r = new List<uint>();
99+
if (source.Count == 0)
100+
throw new InvalidOperationException("Source collection is empty.");
67101

68-
for (uint i = 0; i < range; ++i)
102+
if (source.TryRandomSelectOne(out T value, excluding))
103+
return value;
104+
105+
throw new InvalidOperationException("Exclusion set invalidates the source. No possible value can be selected.");
106+
}
107+
108+
public static bool TryRandomSelectOneExcept<T>(
109+
this IReadOnlyList<T> source,
110+
T excluding,
111+
out T value)
112+
{
113+
var count = source.Count;
114+
if (count == 0)
69115
{
70-
if (!excludeSet.Contains(i)) r.Add(i);
116+
value = default(T);
117+
return false;
71118
}
72119

73-
return r.RandomSelectOne();
120+
return source
121+
.Where(o => !excluding.Equals(o))
122+
.ToArray()
123+
.TryRandomSelectOne(out value);
124+
}
125+
126+
public static T RandomSelectOneExcept<T>(
127+
this IReadOnlyList<T> source,
128+
T excluding)
129+
{
130+
if (source.Count == 0)
131+
throw new InvalidOperationException("Source collection is empty.");
132+
133+
if (source.TryRandomSelectOneExcept(excluding, out T value))
134+
return value;
135+
136+
throw new InvalidOperationException("Exclusion set invalidates the source. No possible value can be selected.");
74137
}
75138

76-
public static uint NextRandomIntegerExcluding(
139+
public static ushort NextRandomIntegerExcluding(
140+
ushort range,
141+
ISet<ushort> excludeSet)
142+
{
143+
if (range == 0)
144+
throw new ArgumentOutOfRangeException("range", range, "Must be a number greater than zero.");
145+
146+
if (excludeSet == null || excludeSet.Count == 0)
147+
return (ushort)R.Value.Next(range);
148+
149+
if (excludeSet.Count == 1)
150+
return (ushort)NextRandomIntegerExcluding(range, excludeSet.Single());
151+
152+
return UEnumerable
153+
.Range(range)
154+
.Where(i => !excludeSet.Contains(i))
155+
.ToArray()
156+
.RandomSelectOne();
157+
}
158+
159+
public static int NextRandomIntegerExcluding(
77160
int range,
78-
HashSet<uint> excludeSet)
161+
ISet<int> excludeSet)
79162
{
80-
if (range < 0)
163+
if (range <= 0)
81164
throw new ArgumentOutOfRangeException("range", range, "Must be a number greater than zero.");
82-
var r = new List<uint>();
83165

84-
for (uint i = 0; i < range; ++i)
85-
{
86-
if (!excludeSet.Contains(i)) r.Add(i);
87-
}
166+
if (excludeSet == null || excludeSet.Count == 0)
167+
return R.Value.Next(range);
88168

89-
return r.RandomSelectOne();
169+
if (excludeSet.Count == 1)
170+
return NextRandomIntegerExcluding(range, excludeSet.Single());
171+
172+
return Enumerable
173+
.Range(0, range)
174+
.Where(i => !excludeSet.Contains(i))
175+
.ToArray()
176+
.RandomSelectOne();
90177
}
91178

179+
public static ushort NextRandomIntegerExcluding(
180+
ushort range,
181+
IEnumerable<ushort> excluding)
182+
{
183+
return NextRandomIntegerExcluding(range, new HashSet<ushort>(excluding));
184+
}
92185

93186
public static int NextRandomIntegerExcluding(
94187
int range,
@@ -101,50 +194,37 @@ public static int NextRandomIntegerExcluding(
101194
int range,
102195
int excluding)
103196
{
104-
if (range < 0)
197+
if (range <= 0)
105198
throw new ArgumentOutOfRangeException("range", range, "Must be a number greater than zero.");
106-
var r = new List<int>();
107199

108-
for (var i = 0; i < range; ++i)
200+
if (excluding == 0)
109201
{
110-
if (excluding != i) r.Add(i);
202+
if (range == 1)
203+
throw new ArgumentException("No value is available with a range of 1 and exclusion of 0.", "range");
204+
return R.Value.Next(range - 1) + 1;
111205
}
112206

113-
return r.RandomSelectOne();
114-
}
207+
if (excluding >= range || excluding < 0)
208+
return R.Value.Next(range);
115209

116-
public static uint NextRandomIntegerExcluding(
117-
int range,
118-
uint excluding)
119-
{
120-
if (range < 0)
121-
throw new ArgumentOutOfRangeException("range", range, "Must be a number greater than zero.");
122-
var r = new List<uint>();
210+
if (excluding == range - 1)
211+
return R.Value.Next(range - 1);
123212

124-
for (uint i = 0; i < range; ++i)
125-
{
126-
if (excluding != i) r.Add(i);
127-
}
128-
129-
return r.RandomSelectOne();
213+
return Enumerable
214+
.Range(0, range)
215+
.Where(i => i != excluding)
216+
.ToArray()
217+
.RandomSelectOne();
130218
}
131219

132-
public static uint NextRandomIntegerExcluding(
133-
uint range,
220+
public static int NextRandomIntegerExcluding(
221+
int range,
134222
uint excluding)
135223
{
136-
var r = new List<uint>();
137-
138-
for (uint i = 0; i < range; ++i)
139-
{
140-
if (excluding != i) r.Add(i);
141-
}
142-
143-
return r.RandomSelectOne();
224+
return NextRandomIntegerExcluding(range,
225+
excluding > int.MaxValue ? -1 : (int)excluding);
144226
}
145227

146228
}
147229

148-
149-
150230
}

UEnumerable.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Open.Numeric
5+
{
6+
public static class UEnumerable
7+
{
8+
public static IEnumerable<ushort> Range(ushort start, ushort count)
9+
{
10+
while (count > 0)
11+
{
12+
yield return start;
13+
start++;
14+
count--;
15+
}
16+
}
17+
18+
public static IEnumerable<ushort> Range(ushort count)
19+
{
20+
return Range(0, count);
21+
}
22+
23+
24+
public static IEnumerable<uint> Range(uint start, uint count)
25+
{
26+
while (count>0)
27+
{
28+
yield return start;
29+
start++;
30+
count--;
31+
}
32+
}
33+
34+
public static IEnumerable<uint> Range(uint count)
35+
{
36+
return Range(0, count);
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)