给定任意数量的序列,我需要计算包含输入序列的超集""。
结果的长度必须最小,并且不得更改输入元素的顺序。输入的项目不一定要保持在一起。
提供比较以在计算期间确定任何符号/元素的优先级。
好奇数字理论中的特定问题是什么。
我希望能够使用.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));
}
}
}