MackySoft.Moira
1.0.0
dotnet add package MackySoft.Moira --version 1.0.0
NuGet\Install-Package MackySoft.Moira -Version 1.0.0
<PackageReference Include="MackySoft.Moira" Version="1.0.0" />
<PackageVersion Include="MackySoft.Moira" Version="1.0.0" />
<PackageReference Include="MackySoft.Moira" />
paket add MackySoft.Moira --version 1.0.0
#r "nuget: MackySoft.Moira, 1.0.0"
#:package MackySoft.Moira@1.0.0
#addin nuget:?package=MackySoft.Moira&version=1.0.0
#tool nuget:?package=MackySoft.Moira&version=1.0.0
MackySoft.Moira
MackySoft.Moira provides deterministic weighted selection primitives for .NET Standard 2.1. The caller supplies each selection sample, so the library does not own a random number generator.
Install
dotnet add package MackySoft.Moira
Fixed distribution
Use WeightedDistribution<T> when every selection uses the same source-ordered weights. Choose the compiled selection
method explicitly: Cumulative uses binary search, while Alias builds an alias table for constant-time selections.
using MackySoft.Moira;
WeightedDistribution<string> distribution = new(
[
new WeightedEntry<string>("common", 80d),
new WeightedEntry<string>("rare", 20d),
],
WeightedSelectionMethod.Cumulative);
double sample = GetSampleFromYourRandomSource();
string? selected = distribution.Select(sample);
double[] samples = GetSamplesFromYourRandomSource(10);
string[] selectedBatch = new string[samples.Length];
distribution.SelectMany(samples, selectedBatch);
Use WeightedSelectionMethod.Alias for a fixed distribution that is selected from often enough to amortize the alias
table construction. Use Cumulative for distributions with fewer selections or shorter lifetimes. The library does not
select a method automatically because the break-even point depends on the target runtime and workload.
Finite bag
Use WeightedBagDefinition<T> to create independent bags whose remaining quantities decrease after a draw.
using MackySoft.Moira;
WeightedBagDefinition<string> definition = new(
[
new WeightedBagEntry<string>("potion", 4d, 3),
new WeightedBagEntry<string>("elixir", 1d, 1),
]);
WeightedBag<string> bag = definition.CreateBag();
double sample = GetSampleFromYourRandomSource();
string? drawn = bag.Draw(sample);
double[] samples = GetSamplesFromYourRandomSource(10);
string[] drawnBatch = new string[samples.Length];
bag.DrawMany(samples, drawnBatch);
WeightedBag<string> restored = definition.Restore(bag.RemainingCounts);
The span-based batch methods write directly into caller-owned storage and do not allocate a result array. Batch bag draws are ordered sequential draws: each result changes the remaining quantities used by the next sample. TryDrawMany(samples, destination) writes the available prefix and returns its length when the bag may contain fewer items than requested.
RemainingCounts is a transient, allocation-free ReadOnlySpan<int> over the bag-owned counts in definition order. Copy it into caller-owned storage before a draw when the previous state must remain stable. CaptureRemainingCounts provides the allocating convenience form. Restore copies and validates either input before returning a new bag.
Samples and validation
Pass a finite sample in the half-open range [0, 1) to Select, Draw, and a nonempty TryDraw. Within the same package
version, the same distribution method, source order, weights, and sample bits select the same source entry. Cumulative
and Alias can map the same sample to different source entries, so persist the selected method with replay metadata.
Distribution entries require finite nonnegative weights, with at least one positive weight. Bag entries require finite positive unit weights and positive initial counts. Definitions and restored counts reject invalid or unrepresentable selection states with ArgumentException; invalid samples produce ArgumentOutOfRangeException.
Draw throws InvalidOperationException for an empty bag. Use TryDraw when an empty bag is an expected result; it returns false and sets the out value to its default.
License
MackySoft.Moira is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 222 | 9/8/2026 |