【问题标题】:pick between several actions using percentage使用百分比在多个操作之间进行选择
【发布时间】:2018-04-20 16:00:44
【问题描述】:

我有一个有 X 个爱好的对象,每个爱好都有一个介于 0-100 之间的值(代表 %),它们加起来是 100。

每天早上我都想运行一个函数来决定这个对象要做什么,一个爱好的价值越高,他们被选中的可能性就越大。

我不知道如何将最后一部分翻译成代码。例如使用这些变量:

    int fishing = 25;
    int sleeping = 25;
    int drinking = 50;
    int running = 0;

【问题讨论】:

  • 是的,但是假设我将数字 23 随机化。然后呢?我看到的唯一方法是让每个爱好都有一个范围。即 0-24、25-50、51-100

标签: c# math logic


【解决方案1】:

这对你有用:

 class Program
{
    private static List<KeyValuePair<string, int>> Actions = new List<KeyValuePair<string, int>>()
    {
        new KeyValuePair<string, int>("fishing", 25),
        new KeyValuePair<string, int>("sleeping", 25),
        new KeyValuePair<string, int>("drinking", 5),
        new KeyValuePair<string, int>("running", 0),
    };

    static void Main(string[] args)
    {
        var result = Actions.OrderByDescending(r => r.Value).First();

        Console.WriteLine(result.Key);
    }
}

这假设您已经拥有这些操作及其百分比。现在,如果任何 2 个(或更多)项目具有相同的百分比,它将显示添加到列表中的第一个。

编辑

很抱歉没有得到随机化的要求。试试这个:

var listOfActionsToTake = new List<string>() { "fishing", "sleeping", "drinking", "running" };

        var listOFActions = new List<KeyValuePair<string, int>>();

        var rand = new Random();
        var currentPercentage = 101;


        for (int i = 0; i < listOfActionsToTake.Count; i++)
        {
            var current = rand.Next(currentPercentage);
            if (i == listOfActionsToTake.Count - 1)
            {
                current = currentPercentage - 1;
            }
            listOFActions.Add(new KeyValuePair<string, int>(listOfActionsToTake[i], current));

            currentPercentage -= current;
        }
        foreach (var action in listOFActions)
        {
            Console.WriteLine($"{action.Key}: {action.Value}");
        }

        var result = listOFActions.OrderByDescending(r => r.Value).First();

        Console.WriteLine(result.Key);

这样,无论您向listOfActionsToTake 添加多少个值,它们之间的总和始终为 100,并且将选择最大的值

【讨论】:

  • 随机化发生在哪里?
  • @Majs - 抱歉,没有得到这个要求。检查更新的答案
【解决方案2】:

我找到了this 示例,这似乎是有道理的。您添加这些值以获得累积值。如果创建的随机值小于累积概率,则选择当前项。

基本上,如果该条件为假,那么您忽略条件中的当前项目概率。所以下一个要比较的项目现在被选中的概率更高。

例如:

// 1. RandNum = 0.4
// 2. cumulative = 0.0
// 3. fishing = 0.25
// 4. cumulative = cumulative + fishing = 0.25
// 5. RandNum < cumulative ? false

随机数是0.4,钓鱼可能有0.25 被选中。由于钓鱼的概率低于随机数,我们将其添加到累积值中,并在下一项中基本上忽略它。下一个项目现在将有更高的概率被选中,因为现在它只是 sleepingdrinking。他们现在都有.50 的概率被选中。

// 1. RandNum = 0.4
// 2. cumulative = 0.25
// 3. sleeping = 0.25
// 4. cumulative = cumulative + sleeping = .50
// 5. RanNum < cumulative ? true

虽然您必须修改它以考虑百分比相等的情况,因为它只会采用第一个。您可以在找到要执行的初始操作后检查百分比是否相同。如果随机选择的动作与另一个动作的百分比相同,则随机选择其中一个。

static void Main(string[] args)
{
    int fishing = 25;
    int sleeping = 25;
    int drinking = 50;
    int running = 0;

    List<KeyValuePair<string, double>> elements = new List<KeyValuePair<string, double>>();
    elements.Add(new KeyValuePair<string, double>("fishing", (fishing * (1.0 / 100.0)))); // 25 * (1 /100) = .25
    elements.Add(new KeyValuePair<string, double>("sleeping", (sleeping * (1.0 / 100.0))));
    elements.Add(new KeyValuePair<string, double>("drinking", (drinking * (1.0 / 100.0))));
    elements.Add(new KeyValuePair<string, double>("running", (running * (1.0 / 100.0))));


    Random r = new Random();
    double rand = r.NextDouble();

    double cumulative = 0.0;
    string selectedElement = "";
    for (int i = 0; i < elements.Count; i++)
    {
        cumulative += elements[i].Value;
        if (rand < cumulative)
        {
            selectedElement = elements[i].Key;
            break;
        }
    }
    Console.WriteLine("Selected Element: " + selectedElement);
    Console.ReadKey();
}

// Test 1: rand: 0.522105917
//         cumulative: 1
//         Selected Element: drinking
// Test 2: rand: 0.49201479
//         cumulative: 0.5
//         Selected Element: sleeping

【讨论】:

    【解决方案3】:

    这应该可以,并且当它们不加到 100 时也会起作用。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    class Program
    {
        static Dictionary<string, int> activities = new Dictionary<string, int>
        {
            { "running", 0 },
            { "fishing", 25 },
            { "sleeping", 25 },
            { "drinking", 50 }
        };
    
        static void Main(string[] args)
        {
            int sum = activities.Sum(a => a.Value);
            int rand = new Random().Next(sum);
            int total = -1;
            string activity = activities.SkipWhile(a => (total += a.Value) < rand).First().Key;
            Console.WriteLine(activity);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 1970-01-01
      • 2014-11-07
      • 2021-02-19
      • 1970-01-01
      • 1970-01-01
      • 2018-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多