转换嵌套的for循环,深度为n

时间:2014-08-27 06:01:48

标签: c# recursion

我一直在尝试构建一个递归函数来替换以下n个深嵌套循环算法,深度将根据组合的长度在2到n(最可能小于20)的任何位置发生变化

    Edit: removed confusing code

我搜索了这个网站,找到了Converting nested loopMore nested loop conversions,但我无法调整它们以输出我需要的内容。

或者我可能只是看错了,根本不需要递归函数。

尝试在C#中执行此操作,感谢您的帮助。

编辑:希望这可以解释一些事情。

我要做的是找到最佳的选项和金额组合,以便在不超出预算的情况下为我提供最大回报。

所以我有一个符合我要求的选项列表,然后我想将它们提供给这个程序/脚本以获得最佳组合和高回报率,我还需要通过购买多个选项来降低风险通常3-10

以下是我到目前为止修正的深度为3的完整代码:

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

    namespace Combinations
    {
        class Program
        {
            static void Main(string[] args)
            {

                Stopwatch stopwatch = new Stopwatch();

                List<option> options = new List<option> {
                            new option("A", 6.50, 0.18, 25000, 3),
                            new option("B", 23.00, 0.59, 25000, 3),
                            new option("C", 27.50, 0.60, 25000, 3),
                            new option("D", 21.00, 0.40, 25000, 3),
                            new option("E", 16.00, 0.30, 25000, 3),
                            new option("F", 7.00, 0.13, 25000, 3),
                            new option("G", 22.50, 0.38, 25000, 3),
                            new option("H", 27.00, 0.45, 25000, 3),
                            new option("I", 13.00, 0.20, 25000, 3),
                            new option("J", 20.50, 0.30, 25000, 3),
                            new option("K", 17.50, 0.25, 25000, 3),
                            new option("L", 10.50, 0.15, 25000, 3),
                            new option("M", 29.00, 0.41, 25000, 3),
                            new option("N", 26.50, 0.37, 25000, 3),
                            new option("P", 15.50, 0.21, 25000, 3),
                            new option("Q", 16.00, 0.20, 25000, 3),
                            new option("R", 10.00, 0.12, 25000, 3),
                            new option("S", 25.00, 0.30, 25000, 3),
                            new option("T", 27.00, 0.32, 25000, 3),
                            new option("U", 22.00, 0.25, 25000, 3),
                            new option("V", 26.50, 0.30, 25000, 3),
                            new option("W", 27.00, 0.30, 25000, 3),
                            new option("X", 14.50, 0.16, 25000, 3),
                            new option("Y", 28.50, 0.31, 25000, 3),
                            new option("Z", 28.50, 0.30, 25000, 3)
                        };
                stopwatch.Start();
                IEnumerable<List<option>> combinations = GetCombination(options, 3);
                stopwatch.Stop();
                Console.WriteLine("Combinations - Time elapsed: {0}", stopwatch.Elapsed);

                stopwatch.Start();
                bestFit(combinations);
                stopwatch.Stop();
                Console.WriteLine("Best Fit - Time elapsed: {0}", stopwatch.Elapsed);

                Console.ReadKey();
            }

            static IEnumerable<List<option>> GetCombination(List<option> list, int _size)
            {
                double count = Math.Pow(2, list.Count);
                List<option> combination = new List<option>();

                int size = 0;

                for (int i = 1; i <= count - 1; i++)
                {
                    for (int j = 0; j < list.Count; j++)
                    {
                        if (((i >> j) & 1) == 1)
                        {
                            combination.Add(list[j]);
                            size++;
                        }
                    }

                    if (size == _size)
                    {
                        yield return combination;
                    }
                    combination.Clear();
                    size = 0;
                }
            }

            static void bestFit(IEnumerable<List<option>> combinations)
            {
                double max = 0d;
                double results = 0d;
                double total = 0d;
                string output = "";
                string tmpOutput = "";

                int y0 = 0;
                int y1 = 1;
                int yn = 2;

                foreach (var combination in combinations)
                {
                    option A1 = combination[y0];
                    for (int x1 = A1.lower; x1 < A1.upper; x1++)
                    {
                        option A2 = combination[y1];
                        for (int x2 = A2.lower; x2 < A2.upper; x2++)
                        {
                            option An = combination[yn];
                            for (int xn = An.lower; xn < An.upper; xn++)
                            {
                                int[] counts = { x1, x2, xn };
                                int i = 0;
                                foreach (option objOption in combination)
                                {
                                    results += objOption.bid * 100 * counts[i] / objOption.cash;
                                    total += (objOption.strike - objOption.bid) * 100 * counts[i];
                                    tmpOutput += objOption.symbol + " STO " + counts[i].ToString() + " @ $" + objOption.strike + ", ";

                                    i++;
                                }

                                if (results > max && total < A1.cash)
                                {
                                    output = tmpOutput.Remove(tmpOutput.Length - 2) + " for a gain of " + results*100 + "% using a total of $" + total;
                                    max = results;
                                }
                                results = 0d;
                                total = 0d;
                                tmpOutput = "";
                            }
                        }
                    }

                }
                Console.WriteLine(output);
            }
        }

        class option
        {
            public string symbol { get; set; }
            public double strike { get; set; }
            public double bid { get; set; }
            public double cash { get; set; }
            public int lower;
            public int upper;

            public option(string _symbol, double _strike, double _bid, double _cash, int _trades)
            {
                this.symbol = _symbol;
                this.strike = _strike;
                this.bid = _bid;
                this.cash = _cash;

                double tradeCash = _cash / _trades;

                this.lower = (int)((0.25 * tradeCash) / ((_strike - _bid) * 100));
                this.upper = (int)((1.25 * tradeCash) / ((_strike - _bid) * 100));

            }
        }
    }

这应该输出:

Combinations - Time elapsed: 00:00:00.0002575
A STO 15 @ $6.5, B STO 3 @ $23, D STO 4 @ $21 for a gain of 2.428% using a total of $24443
Best Fit - Time elapsed: 00:00:11.9196411

希望这有助于澄清事情。

1 个答案:

答案 0 :(得分:0)

好像您只是使用for循环来生成count条目。我首先要将这部分重构成这样的东西:

public struct Bound
{
    public int Lower { get; set; }
    public int Upper { get; set; }
}

public static class Counting
{
    public static IEnumerable<int[]> Indizes(this Bound[] bounds)
    {
        return Indizes(bounds, 0);
    }

    static IEnumerable<int[]> Indizes(this Bound[] bounds, int index)
    {
        if (index >= bounds.Length)
            yield return new int[] {};
        else
        {
            foreach(var comb in Indizes(bounds, index+1))
            {
                for (var i = bounds[index].Lower; i < bounds[index].Upper; i++)
                {
                    var newArr = new int[comb.Length + 1];
                    Array.Copy(comb, 0, newArr, 1, comb.Length);
                    newArr[0] = i;
                    yield return newArr;
                }
            }
        }
    }
}

评论最有可能你可以更快地获得这个但我认为它会告诉你如何使用递归来做这样的想法

使用类似的东西(用你的数据结构替换Bound结构 - 它只在那里,所以我可以测试我的代码)你的疯狂 -loop简化为:

   foreach(var combination in combinations)
   {
        foreach (var counts in Counting.Indizes(combination))
        {
            int i = 0;
            foreach (myClass objMyClass in combination)
            {
               results += objMyClass.a * 100 * counts[i] / objMyClass.b;
               total += (objMyClass.c - objMyClass.a) * 100 * counts[i];
               tmpOutput += objMyClass.symbol + " count " + counts[i].ToString() + ", ";
               i++;
            }
            // ...
        }
   }

其余的我不太了解您的代码以提供任何建议