【问题标题】:C# Random algorithm until fulfills conditionC# 随机算法,直到满足条件
【发布时间】:2017-07-22 16:04:01
【问题描述】:

我有以下场景:

  1. 生成n一定范围内的随机数个数
  2. 将所有数字相加
  3. 检查sum == x是否(x是用户设置的数字)
  4. 如果sum != x 则继续循环运行
  5. 如果sum == x,则显示总和为x的随机数列表

基于这个逻辑,我可以这样做,但是需要很长时间才能达到结果,有没有更好的/方法来解决这个问题?

    static void Main(string[] args)
    {
        Console.WriteLine("starting...");
        List<int> checkList = generate(5);
        while(!checkSum(checkList, 100))
        {
            checkList = generate(5)
        }
        Console.WriteLine("done!");
    }


    private static bool checkSum(List<int> n, int sum)
    {
        if(n.Sum() == sum)
        {
            return true;
        }
        else
        {
            return false;
        }
    }


    public static List<int> generate(int n)
    {
        Random rng = new Random();
        List<int> list = new List<int>();
        for (int i = 0; i < 5; i++)
        {
            //int ran = some random number
            list.Add(ran);
        }

        return list;
    }

编辑

我的场景是获得n 的随机整数组合,总和为 100。组合的数量取自用户输入。所以程序将给出n 的可能组合数,总和为 100。

可能的组合:

  • 25+37+9+20+9 = 100
  • 46+21+13+8+12 = 100

【问题讨论】:

  • 你的场景是一个算法(解决方案),而不是一个问题。由于蛮力方法,该算法当然很慢。您试图用更好的算法解决的问题是什么?
  • it takes forever to achieve the result 很明显。有一种情况(所有项目 = 20)将使您的条件为真。其实 20 是独家的,所以我不知道这是怎么结束的。
  • 打印出不工作的序列(不仅仅是成功的序列),你会看到代码中的错误在哪里。
  • 您可以通过将rng.Next(5,20) 更改为rng.Next(20,21) 之类的名称来加快速度。
  • 你在开玩笑吗?您甚至没有使用您发送的 int n 来生成。你期望 5 rng.Next(5, 20);总计 100。最大值 (20) 不包括在内。即使 20 包含在内,只有在 random 是每个值的最大值时才会总计。

标签: c# algorithm random


【解决方案1】:

如果您有固定的总和和固定数量的元素,请将问题视为分区。例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PartitionAndAllocateTEst
{
    class Program
    {
        static void Main(string[] args)
        {
            var rand = new Random();
            int desiredTotal = 100;
            int partitions = 5;

            for (int i = 0; i < 10; i++)
            {
                List<int> result = GetRandomCollection(rand, desiredTotal, partitions);
                Console.WriteLine(string.Join(", ", result.Select(r => r.ToString()).ToArray()));
            }
        }

        private static List<int> GetRandomCollection(Random rand, int desiredTotal, int partitions)
        {
            // calculate the weights
            var weights = new List<double>();
            for (int i = 0; i < partitions; i++)
            {
                weights.Add(rand.NextDouble());
            }
            var totalWeight = weights.Sum();

            // allocate the integer total by weight
            // http://softwareengineering.stackexchange.com/questions/340393/allocating-an-integer-sum-proportionally-to-a-set-of-reals/340394#340394
            var result = new List<int>();
            double allocatedWeight = 0;
            int allocatedCount = 0;
            foreach (var weight in weights)
            {
                var newAllocatedWeight = allocatedWeight + weight;
                var newAllocatedCount = (int)(desiredTotal * (newAllocatedWeight / totalWeight));
                var thisAllocatedCount = newAllocatedCount - allocatedCount;
                allocatedCount = newAllocatedCount;
                allocatedWeight = newAllocatedWeight;

                result.Add(thisAllocatedCount);
            }

            return result;
        }
    }
}

示例输出:

30, 6, 19, 15, 30
36, 8, 22, 10, 24
2, 25, 32, 21, 20
22, 7, 30, 12, 29
36, 21, 22, 0, 21
24, 24, 2, 29, 21
18, 13, 10, 39, 20
11, 19, 20, 27, 23
24, 19, 7, 25, 25
24, 14, 27, 18, 17

【讨论】:

    【解决方案2】:

    您可以尝试使用遗传算法。从一组 100 组五个随机整数开始。对每组求和。选择 50 个更好的集合,总和接近 100 的集合。保留更好的 50 个,转储其他 50 个并用最佳 50 个的调整版本替换它们。调整是用另一个随机整数替换集合中的一个整数。

    当总体中的某个成员的总和正好为 100 时,将其拉出到您的输出数组中,并使用新生成的五个整数组成总体。

    遗传算法的运行速度比蛮力算法快得多。

    【讨论】:

      【解决方案3】:

      我不明白你为什么被否决。你的问题很清楚,而且你已经知道你的算法不好。

      我会分两次解决这个问题。 Pass 1 是计算从每个部分点到最终答案有多少种方法。 Pass 2 正在选择一条随机路径。

      对于第 1 步,您构建了一个数组数组。根据要选择的数字数量,根据您需要将它们求和的数量,有多少种方法可以得到答案? (有关如何执行此操作的更多信息,请搜索动态编程。)

      在第 2 步中,您继续前进。您在每一步都知道有多少种方法可以完成您的任务,以及您可以选择的每个值有多少种方法。因此,您知道选择每个值的概率。因此,在(0, 1) 中选择一个随机值,浏览答案,选择下一个数字,然后继续。

      这种通用策略不仅适用于数字。它可用于生成任何可以使用动态编程技术计数的随机样本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-29
        • 2017-09-11
        • 1970-01-01
        • 2019-11-10
        • 2014-10-18
        • 2021-12-24
        • 1970-01-01
        相关资源
        最近更新 更多