Найти значения, которые составляют 0 в Excel со многими элементами - PullRequest
0 голосов
/ 16 ноября 2018

Я должен найти каждое подмножество в достаточно большом списке, 500/1000 элементов, которые являются положительными и отрицательными и являются десятичными, а сумма равна 0. Я не эксперт, поэтому я прочитал много и много статей и решений, и Затем я написал свой код. Данные поступают из таблицы Excel, и я хотел бы отметить найденные суммы там. Код работает следующим образом:

  • Изначально я нахожу все пары с суммой 0
  • Затем я кладу суммы остатков в список и беру комбинации в пределах 20 предметов, поскольку я знаю, что невозможно увеличить сумму комбинации до 0
  • В этих комбинациях я ищу, если одна из комбинаций суммирует 0, и сохраняет ее в списке результатов, в противном случае я сохраняю сумму в словаре в качестве ключа, а затем я буду искать, содержит ли словарь следующие суммы (поэтому я проверяю пары этих подмножеств)
  • Я отслеживаю индекс, чтобы я мог добраться до ячеек и изменить их

Найти решения достаточно быстро, но когда я хочу уточнить, результаты в Excel становятся очень медленными. Я не забочусь о поиске всех решений, но я хочу найти максимально возможное за короткое время.

Что вы думаете об этом решении? Как я могу улучшить скорость? Как я могу легко пропустить суммы, которые уже взяты? И как быстро пометить ячейки в моем рабочем листе, потому что теперь здесь есть узкое место программы?

Надеюсь, это достаточно ясно :) Спасибо всем за помощь

Вот мой код части комбинации:

        List<decimal> listDecimal = new List<decimal>();
        List<string> listRange = new List<string>();
        List<decimal> resDecimal = new List<decimal>();
        List<IEnumerable<decimal>> resDecimal2 = new List<IEnumerable<decimal>>();
        List<IEnumerable<string>> resIndex = new List<IEnumerable<string>>();
        Dictionary<decimal, int> dicSumma = new Dictionary<decimal, int>();
        foreach (TarkistaSummat.CellsRemain el in list)
        {
            decimal sumDec = Convert.ToDecimal(el.Summa.Value);
            listDecimal.Add(sumDec);
            string row = el.Summa.Cells.Row.ToString();
            string col = el.Summa.Cells.Column.ToString();
            string range = el.Summa.Cells.Row.ToString() + ":" + el.Summa.Cells.Column.ToString();
            listRange.Add(range);
        }

        var subsets = new List<IEnumerable<decimal>> { new List<decimal>() };
        var subsetsIndex = new List<IEnumerable<string>> { new List<string>() };

        for (int i = 0; i < list.Count; i++)
        {
            if (i > 20)
            {
                List<IEnumerable<decimal>> parSubsets = subsets.GetRange(i, i + 20);
                List<IEnumerable<string>> parSubsetsIndex = subsetsIndex.GetRange(i, i + 20);
                var Z = parSubsets.Select(x => x.Concat(new[] { listDecimal[i] }));
                //var Zfound = Z.Select(x => x).Where(w => w.Sum() ==0);
                subsets.AddRange(Z.ToList());
                var Zr = parSubsetsIndex.Select(x => x.Concat(new[] { listRange[i] }));
                subsetsIndex.AddRange(Zr.ToList());
            }
            else
            {
                var T = subsets.Select(y => y.Concat(new[] { listDecimal[i] }));
                //var Tfound = T.Select(x => x).Where(w => w.Sum() == 0);
                //resDecimal2.AddRange(Tfound);
                //var TnotFound = T.Except(Tfound);
                subsets.AddRange(T.ToList());
                var Tr = subsetsIndex.Select(y => y.Concat(new[] { listRange[i] }));
                subsetsIndex.AddRange(Tr.ToList());
            }
        for (int i = 0; i < subsets.Count; i++)
        {
            decimal sumDec = subsets[i].Sum();

            if (sumDec == 0m)
            {
                resDecimal2.Add(subsets[i]);
                resIndex.Add(subsetsIndex[i]);
                continue;
            }
            else
            {
                if(dicSumma.ContainsKey(sumDec * -1))
                {
                    dicSumma.TryGetValue(sumDec * -1, out int index);
                    IEnumerable<decimal> addComb = subsets[i].Union(subsets[index]);
                    resDecimal2.Add(addComb);
                    var indexComb = subsetsIndex[i].Union(subsetsIndex[index]);
                    resIndex.Add(indexComb);
                }
                else
                {
                    if(!dicSumma.ContainsKey(sumDec))
                    {
                        dicSumma.Add(sumDec, i);
                    }
                }
            }

        }

        for (int i = 0; i < resIndex.Count; i++)
        {
            //List<Range> ranges = new List<Range>();
            foreach(string el in resIndex[i])
            {
                string[] split = el.Split(':');
                Range cell = actSheet.Cells[Convert.ToInt32(split[0]), Convert.ToInt32(split[1])];
                cell.Interior.ColorIndex = 6;
            }

} }

...