计算序列的超集

时间:2016-05-09 08:15:18

标签: c# .net

给定任意数量的序列,我需要计算包含输入序列的超集""。

结果的长度必须最小,并且不得更改输入元素的顺序。输入的项目不一定要保持在一起。

提供比较以在计算期间确定任何符号/元素的优先级。

好奇数字理论中的特定问题是什么。

我希望能够使用.NET类型和IEnumerable Extensions来解决这个问题。

基于字母表的比较示例:

ABC, ABC -> ABC

ABC, ABD -> ABCD

ABCD, BCD, ACD, ACB -> ABCDB

ABCD, EBCD -> AEBCD

到目前为止我的方法,而不是最后一个(ABCD,EBCD)

namespace Ra.Essentials
{
   using System;
   using System.Collections.Generic;
   using System.Linq;

   public static class SequenceReductionExtensions
   {
      public static IEnumerable<T> Reduce<T>(this IEnumerable<IEnumerable<T>> input)
      {
         return input.Reduce(Comparer<T>.Default.Compare);
      }

      public static IEnumerable<T> Reduce<T>(this IEnumerable<IEnumerable<T>> input, Comparison<T> comparison)
      {
         var enumerators = input.Select(o => o.GetEnumerator()).ToList();

         enumerators.RemoveAll(o => !o.MoveNext());

         while (enumerators.Any())
         {
            var symbols = enumerators.GroupBy(o => o.Current);

            // review: orderby key
            var spread = symbols.GroupBy(o => o.Count()).OrderByDescending(o => o.Count());

            T ret;

            var firstSpread = spread.First();

            // gleiche Anzahl verschiedener Symbole
            if (firstSpread.Count() > 1)
            {
               var a1 = firstSpread.First().Key;
               var a2 = firstSpread.Skip(1).First().Key;

               ret = comparison(a1, a2) < 0 ? a1 : a2;
            }
            else
            {
               ret = firstSpread.First().Key;
            }

            enumerators.RemoveAll(o => comparison(o.Current, ret) == 0 && !o.MoveNext());

            yield return ret;
         }
      }
   }
}

单元测试:

namespace Ra.Essentials.Tests
{
   using System.Collections.Generic;
   using System.Linq;
   using NUnit.Framework;
   using XBase.Essentials;

   [TestFixture]
   public class SequenceReductionExtensionsTests
   {
      [TestCase("ABC", new[] { "ABC" })]
      [TestCase("ABC", new[] { "ABC", "ABC" })]
      [TestCase("ABCD", new[] { "ABC", "ABD" })]
      [TestCase("ABCDB", new[] { "ABCD", "BCD", "ACD", "ACB" })]
      [TestCase("AEBCD", new[] { "ABCD", "EBCD" })]
      public void Should_Reduce(string expected, IEnumerable<string> input)
      {
         "Ex:".ToOutput();
         expected.ToOutput();

         "In:".ToOutput();
         input.ForEach(o => o.ToOutput());

         CollectionAssert.AreEqual(expected, CallReduce(input));
      }

      private static string CallReduce(IEnumerable<string> input)
      {
         var sequences = input.Select(o => o.ToList());

         return string.Join(string.Empty, sequences.Reduce(Comparer<char>.Default.Compare));
      }
   }

}

0 个答案:

没有答案