需要数学库来进行序列/范围的操作

时间:2012-10-04 12:19:38

标签: c# .net windows algorithm math

我有三种数值范围,它们在某个区间内定义如下:
1.计数范围(指定范围内的任何值)
2.定期序列(指定序列开始,步骤和步骤计数)
3.一组精确值(如1,3,7等)

我需要将它们联合/交叉(从2到N的不同类型)并获得优化结果。显然,上面的交点将返回上述类型的结果并将它们联合起来将产生上述1到M种类型。
例1:
第一个范围定义为5到11的连续范围,第二个范围定义为2到18的定期序列,步骤2(因此,8个步骤)。
交叉点将返回从步骤2到6的周期序列。
联盟将返回三个结果:从步骤2的2到4的周期性序列,从5到11的连续范围以及从步骤2到12到18的周期序列。 例2:
第一个范围定义为周期序列0到10,步骤2和第二个周期序列从1到7,步骤2(因此,3个步骤)。
交叉点将返回null,因为它们不相交 Union将返回两个结果:1到8的周期序列,步骤1(注意:优化结果)和精确值10 希望我没有犯错误:) 那么,这些序列上的这些操作不应该太复杂,我希望有一个像这里的东西的库。请建议任何(将在C#.NET中使用) 谢谢!

更新
回答“我怎么认为我使用图书馆”。以上三种类型都可以用编程语言轻松定义为:
1. Contionous:{decimal Start;小数结束;其中Start是范围的开始,End是结束
2.期刊:{decimal Start;小数步; int Count;其中Start是序列的开头,Step是递增,Count是步数
3.精确数字集:{decimal []值;其中Values是一些小数的数组。

当我在上面列出的任何类型的任何两个范围的交集时,我肯定会得到其中一种类型的结果,例如“连续”和“期刊”范围交叉将导致“期刊”,“续”。并且“精确的集合”将导致精确的“续”。而“确切”也将返回精确。相同类型的交点将返回输入类型的结果 2个范围的联合稍微复杂一些,但无论如何也会返回上面类型中定义的2到3个范围 具有交集/并集功能,我将始终能够在2到N个范围内运行它,并且将以输入类型术语获得结果。

2 个答案:

答案 0 :(得分:2)

首先,遵循之前的其他答案:我不相信有一个标准的库:它看起来非常特殊。

其次,问题/要求没有明确说明。我将按照问题介绍并参考3种不同的类型,如“set”,“periodic”,“continuous”。

考虑两组{1,4,5,6}和{4,5,6,8}。他们的交集是{4,5,6}。我们是否必须将其标记为“周期性”,因为该描述符合大小写,或者作为“set”,因为它是集合的交集?

从这一点来看,一般来说,我们是否需要在其内容为周期性时将“set”标签更改为“periodic”?毕竟,“周期性”是“集合”的特殊情况。

同样,考虑“周期性”{4,6,8}和一组{10,15,16}的联合。我们是否必须将结果定义为周期性{4,6,8,10}加上周期性{15,16}或者更确切地说是一组包含所有值,还是另一种变体?

堕落情况如何:{3}是“集合”,“定期”,甚至是“连续”?什么类型是“连续”{1-4}和“集合”{4,7,8}的交集?连续{1-4}和连续{4-7}?

的交集

依此类推:必须清楚的是,必须如何标记/描述任何结果 - 来自联合和/或交叉 - 无论是 - 例如 - 两个离散类型(非连续)的交集或并集总是一个类型(通常是一组,可能是一个周期),或者更确切地说是一系列的周期,或者......

第三,假设上述问题已经得到解决,我相信您可以按照以下准则来实施:

  • 只考虑两种“类型”,即“连续”和“设置”。 “周期性”只是“集合”的一种特殊形式,在任何时候我们都可以在适当的时候将“集合”标记为“周期性”。

  • 定义一个公共基类,并使用适当的派生(交叉)方法进行联合,交集和任何你可能需要的方法,以产生 - 例如 - 一个(baseType)列表作为结果。

    < / LI>

逐案实现基本上非常简单 - 假设我的介绍性问题已得到解答。只要最初的问题看起来有些“困难”,只是因为问题和规范还没有很好地定义。

答案 1 :(得分:0)

所有听起来都非常习惯 - 所以我认为你不会找到一个可以完成所有这些工作的图书馆 - 但那里没什么太难的。

我会开始你的。对于第一个示例工作正常,但方法Range.ConstructAppropriate将需要特别复杂,以返回“从步骤2的2到4的周期序列,从5到11的连续范围和来自的周期序列12到18,步骤2 “来自集合{ 5, 6, 7, 8, 9, 10, 11, 2, 4, 12, 14, 16, 18 },这是由示例1中两个集合的结合产生的。

另外(在连接所有代码的麻烦之后)我从评论中注意到你需要非整数。这使事情复杂化。我想你可以想出一种创造性的方式来应用这种模式。

class Program
{
    static void Main(string[] args)
    {
        // Example 1:
        // 1st range is defined as continous range from 5 to 11 and 2nd is periodical sequence from 2 to 18 with step 2 (thus, 8 steps).
        // Intersection will return a periodic sequence from 6 to 10 with step 2.example 1

        ContinuousRange ex1_r1 = new ContinuousRange(5, 11);
        PeriodicRange ex1_r2 = new PeriodicRange(2, 2, 8);

        IEnumerable<int> ex1_intersection = ex1_r1.Values.Intersect(ex1_r2.Values);
        IList<Range> ex1_intersection_results = Range.ConstructAppropriate(ex1_intersection);
    }
}

abstract class Range
{
    public abstract IEnumerable<int> Values { get; }

    public static IList<Range> ConstructAppropriate(IEnumerable<int> values)
    {
        var results = new List<Range>();

        results.Add(ContinuousRange.ConstructFrom(values));
        results.Add(PeriodicRange.ConstructFrom(values));

        if (!results.Any(r => r != null))
            results.Add(Points.ConstructFrom(values));

        return results.Where(r => r != null).ToList();
    }
}

class ContinuousRange : Range
{
    int start, endInclusive;

    public ContinuousRange(int start, int endInclusive)
    {
        this.start = start;
        this.endInclusive = endInclusive;
    }

    public override IEnumerable<int> Values
    {
        get
        {
            return Enumerable.Range(start, endInclusive - start + 1);
        }
    }

    internal static ContinuousRange ConstructFrom(IEnumerable<int> values)
    {
        int[] sorted = values.ToArray();
        if (sorted.Length <= 1)
            return null;

        for (int i = 1; i < sorted.Length; i++)
        {
            if (sorted[i] - sorted[i - 1] != 1)
                return null;
        }

        return new ContinuousRange(sorted.First(), sorted.Last());
    }
}

class PeriodicRange : Range
{
    int start, step, count;

    public PeriodicRange(int start, int step, int count)
    {
        this.start = start;
        this.step = step;
        this.count = count;
    }

    public override IEnumerable<int> Values
    {
        get
        {
            var nums = new List<int>();
            int i = start;
            int cur = 0;

            while (cur <= count)
            {
                nums.Add(i);
                i += step;
                cur++;
            }

            return nums;
        }
    }

    internal static Range ConstructFrom(IEnumerable<int> values)
    {
        // check the difference is the same between all values

        if (values.Count() < 2)
            return null;

        var sorted = values.OrderBy(a => a).ToArray();

        int step = sorted[1] - sorted[0];

        for (int i = 2; i < sorted.Length; i++)
        {
            if (step != sorted[i] - sorted[i - 1])
                return null;
        }

        return new PeriodicRange(sorted[0], step, sorted.Length - 1);
    }
}

class Points : Range
{
    int[] nums;

    public Points(params int[] nums)
    {
        this.nums = nums;
    }

    public override IEnumerable<int> Values
    {
        get { return nums; }
    }

    internal static Range ConstructFrom(IEnumerable<int> values)
    {
        return new Points(values.ToArray());
    }
}