using System;
using System.Linq;
using System.Collections.Generic;
public class WeightedItem<T>
{
public T Item { get; set; }
public double Weight { get; set; } = 1;
}
class WeightedRandom<T>
{
private static Random random = new Random();
private List<WeightedItem<T>> list { get; set; } = new List<WeightedItem<T>>();
public WeightedItem<T> this[T item] => list.FirstOrDefault(x => x.Item.Equals(item)) ?? ((Func<WeightedItem<T>>)(() => { list.Add(new WeightedItem<T>{ Item = item }); return this[item]; }))();
public double TotalWeight => list.Sum(x => x.Weight);
public WeightedRandom(params T[] items) => list.AddRange(items.Select(x => new WeightedItem<T> { Item = x }));
public WeightedRandom(IEnumerable<T> items):this(items.ToArray()) {}
public T Next()
{
var limit = list.Sum(x => x.Weight);
var value = random.NextDouble() * limit;
var e = list.GetEnumerator();
while(e.MoveNext())
if((e.Current.Weight) > value)
return e.Current.Item;
else
value -= e.Current.Weight;
return e.Current.Item;
}
}
class MainClass
{
static void Main()
{
var items = new[] { "Sam", "Lia", "Kind Lenny", "Boomer Badlad", "Handsum Jim" };
var occurs = new Dictionary<string, int>();
var rand = new WeightedRandom<string>(items);
rand["Sam"].Weight = 5;
rand["Handsum Jim"].Weight = .5;
var length = rand.TotalWeight * 1000000;
for(var i = 0; i < length; i++)
{
var item = rand.Next();
if(occurs.ContainsKey(item))
occurs[item]++;
else
occurs[item] = 1;
}
foreach(var item in items)
Console.WriteLine($"{item}: {occurs[item]}");
}
}