Взвешенный случайный выбор с использованием метода псевдонима Уолкера


Я искал этот алгоритм
(алгоритм, который будет случайным образом выбирать из списка элементов, где каждый элемент имеет различную вероятность выбора (вес))
и нашел только реализации python и c, после того, как я сделал С# один, немного другой (но, я думаю, проще), я думал, что должен поделиться им, также мне нужно F # imlementation, если кто-нибудь сможет это сделать отправьте ответ

using System;
using System.Collections.Generic;
using System.Linq;

namespace ChuckNorris
{
    class Program
    {
        static void Main(string[] args)
        {
            var oo = new Dictionary<string, int>
                         {
                             {"A",7},
                             {"B",1},
                             {"C",9},
                             {"D",8},
                             {"E",11},
                         };

            var rnd = new Random();
            var pick = rnd.Next(oo.Values.Sum());

            var sum = 0;
            var res = "";

            foreach (var o in oo)
            {
                sum += o.Value;
                if(sum >= pick)
                {
                    res = o.Key;
                    break;
                }
            }

            Console.WriteLine("result is "+  res);
        }
    }
}

, если кто-то может переделать его в F #, напишите свой код

Ответ 1

Вот аналогичный код в F #:

let rng = new System.Random()
let d = [| "A", 3
           "B", 2
           "C", 3 |]
let sums = Seq.scan (+) 0 (dict d).Values |> Seq.skip 1 |> Seq.toArray 
let pick = rng.Next(sums.[sums.Length-1])
let res = fst d.[sums |> Seq.findIndex ((<) pick)]

Ответ 2

open System

let oo = dict [ "A", 7;
                "B", 1;
                "C", 9;
                "D", 8;
                "E", 11 ]

let rnd = Random()
let pick = oo.Values |> Seq.sum |> rnd.Next

let res = oo |> Seq.scan (fun (_, s) (KeyValue(k, v)) -> k, s + v) ("", 0)
             |> Seq.tryPick (fun (k, s) -> if s >= pick 
                                           then printfn "Result is %s" k; Some k 
                                           else None)