Quick actions

cmd+k|ctrl+k

Navigation

Languages

Weighted random

Snippet info

Language

Csharp

Visibility

public

Author

linus.aspelin

Created

2018-10-04T08:42:03Z

Updated

2018-10-10T13:17:57Z

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]}");
    }
}
INFO