.NET-使用附加规则和扭曲计算组合

.NET-使用附加规则和扭曲计算组合,.net,math,combinations,permutation,powerset,.net,Math,Combinations,Permutation,Powerset,更新:@bphelpsjr-answer提供了我正在寻找的内容。不幸的是,有人投了他的反对票,而我没有投票权。我认为他的回答就是答案 这是非常冗长的,但我想提供尽可能多的细节 本质上,我希望获取一组数据,并根据规则(定义如下)生成列表列表。这本质上是电源集的过滤版本 然后,我将存储这些结果以供重复使用(类似于a的结果),以避免对相同的N进行常量计算。然后,在应用其他逻辑之前,我将使用变量替换(例如,A=18,B=30)(下文未描述,我的问题不需要) 下面是我在尝试创建解决方案时尝试过的两个输入选

更新:@bphelpsjr-answer提供了我正在寻找的内容。不幸的是,有人投了他的反对票,而我没有投票权。我认为他的回答就是答案

这是非常冗长的,但我想提供尽可能多的细节

本质上,我希望获取一组数据,并根据规则(定义如下)生成列表列表。这本质上是电源集的过滤版本

然后,我将存储这些结果以供重复使用(类似于a的结果),以避免对相同的
N
进行常量计算。然后,在应用其他逻辑之前,我将使用变量替换(例如,A=18,B=30)(下文未描述,我的问题不需要)

下面是我在尝试创建解决方案时尝试过的两个输入选项您也可以使用数字代替字母。

输入选项#1 规则 前三条是明确的规则,而第四条则更多的是一种欲望

  • 解决方案必须能够处理N个不同的字母和项目列表

  • 每个不同的字母必须在项目列表中至少出现一次。例如:


    AA-BB-CC-DD我没有足够的代表发表评论,因此我发布了一个不完整的答案。 我有一个解决方案,但还没有完善。目前,它会吐出不完整的组合(例如AD-CC),并且可以使用一些修剪来避免查看无用的列表

    我的方法是递归的,但通过存储解避免了一些计算。例如,当查看C列表时,使用了A和B字母的剩余组合是相同的,无论到目前为止的组合是AA-BB还是AB

    我还没有实现
    memory()
    IKnowThis()
    方法,但是它们应该使用哈希表非常简单

    foreach(GenerateCombinations(“,0”)中的var组合)
    {
    控制台写入线(组合);
    }
    私有静态列表生成器组合(使用字符串,int-listIndex)
    {
    如果(listIndex>=_allLists.Count | | used.Length==_allLists.Count)
    返回新列表();
    列表组合;
    如果(!IKnowThis(已使用、列表索引、输出组合))
    {
    if(used.Contains(_allLists[listIndex][0].First))
    返回生成组合(已使用,listIndex+1);
    combos=新列表();
    foreach(所有列表[listIndex]中的变量项)
    {
    var newcombos=新列表();
    字符串newUsed=组合(已使用,项目);
    AddRange(GenerateCombinations(newUsed,listIndex+1));
    如果(!used.Contains(item.Second)和&!used.Contains(item.First))
    {
    如果(newcombos.Count==0)
    {
    newcombos.Add(item.ToString());
    }
    其他的
    {
    for(int i=0;i
    这能给你想要的东西吗

    如果我从您的
    完整列表开始,再加上缺少的向后转换:

    var completeList = new List<Item>
    {
        new Item('A', 'A'),
        new Item('A', 'B'),
        new Item('A', 'C'),
        new Item('A', 'D'),
        new Item('B', 'B'),
        new Item('B', 'C'),
        new Item('B', 'D'),
        new Item('C', 'B'),
        new Item('C', 'C'),
        new Item('C', 'D'),
        new Item('D', 'B'),
        new Item('D', 'C'),
        new Item('D', 'D'),
    };
    
    这应该有效(使用数字而不是字母):

    private static BlockingCollection getcompositions(int到consider)
    {
    var allResults=new BlockingCollection();
    变量可能性=可枚举的.Range(0,toConsider.ToList();
    Parallel.ForEach(可能性,可能性=>
    {
    GetIteratively(新列表{new[]{0,可能性}},allResults,Probabilities.RemoveAllClone(x=>x==0 | | x==Probability));
    });
    返回所有结果;
    }
    以迭代方式公开静态void(列出结果、BlockingCollection所有结果、列出可能性)
    {
    堆栈=新堆栈();
    Push(新元组(结果,可能性));
    而(stack.Count>0)
    {
    var pop=stack.pop();
    如果(pop.Item2.Count>0)
    pop.Item2.ForEach(x=>stack.Push(新元组(新列表(结果){new int[]{pop.Item2[0],x}}},pop.Item2.RemoveAllClone(y=>(y==pop.Item2[0]| | y==x俬俬));
    其他的
    添加(结果);
    }   
    }
    
    这是RemoveAllClone的LinqExtension

        public static List<T> RemoveAllClone<T>(this IEnumerable<T> source, Predicate<T> match)
        {
            var clone = new List<T>(source);
            clone.RemoveAll(match);
            return clone;
        }
    
    publicstaticlist RemoveAllClone(此IEnumerable源,谓词匹配)
    {
    var clone=新列表(源);
    clone.RemoveAll(匹配);
    返回克隆;
    }
    
    恐怕这对我来说毫无意义。我看不到输入和输出之间的联系。这些“规则”似乎是对如何解决问题的限制,但问题本身没有解释。如果不清楚,我道歉。我将编辑以尝试更具体。我已经编辑并重新安排了一些内容,以尝试更清晰。如果你有任何问题,请告诉我。好的,你现在想做的事情是有道理的!谢谢你的澄清。你对解决问题的最好方法或解决问题有什么想法吗
    AA BB CC DD
    AA BB CD
    AA BC    DD
    AA BD CC
    AB    CC DD 
    AB    CD
    AC BB    DD
    AC BD
    AD BB CC
    AD BC
    
    public class Item
    {
        public char First { get; set; }
        public char Second { get; set; }
    
        public Item(char first, char second)
        {
            First = first;
            Second = second;
    
        public List<char> DistinctCharacters()
        {
            return First == Second ? new List<char> { First } : new List<char> { First,  Second };
        }
    }
    
    var completeList = new List<Item>
    {
        new Item('A', 'A'),
        new Item('A', 'B'),
        new Item('A', 'C'),
        new Item('A', 'D'),
        new Item('B', 'B'),
        new Item('B', 'C'),
        new Item('B', 'D'),
        new Item('C', 'B'),
        new Item('C', 'C'),
        new Item('C', 'D'),
        new Item('D', 'B'),
        new Item('D', 'C'),
        new Item('D', 'D'),
    };
    
    var lookup = completeList.ToLookup(x => x.First, x => x.Second);
    
    Func<IEnumerable<string>, IEnumerable<string>> f = null;
    f = xs =>
    {
        var query =
            from x in xs
            let ys = lookup[x.Last()]
                .Where(y => !x
                    .Take(x.Length % 2 == 1 ? x.Length - 1 : x.Length)
                    .Contains(y))
                .Select(y => x + y)
                .ToArray()
            group new { x, ys } by ys.Any();
    
        return query
            .Where(c => c.Key == false)
            .SelectMany(qs => qs.Select(q => q.x))
            .Concat(query
                .Where(c => c.Key == true)
                .SelectMany(ys => Generate(ys.SelectMany(y => y.ys))));
    };
    
    var results = f(new [] { "A" });
    
    ABCD 
    ABDC 
    ACBD 
    ACDB 
    ADBC 
    ADCB 
    AABBCD 
    AABBDC 
    AABCDD 
    AABDCC 
    AACBDD 
    AACCBD 
    AACCDB 
    AACDBB 
    AADBCC 
    AADCBB 
    AADDBC 
    AADDCB 
    ABCCDD 
    ABDDCC 
    ACBBDD 
    ACDDBB 
    ADBBCC 
    ADCCBB 
    AABBCCDD 
    AABBDDCC 
    AACCBBDD 
    AACCDDBB 
    AADDBBCC 
    AADDCCBB 
    
        private static BlockingCollection<List<int[]>> GetCombinations(int toConsider)
        {
            var allResults = new BlockingCollection<List<int[]>>();
            var possibilities = Enumerable.Range(0, toConsider).ToList();
            Parallel.ForEach(possibilities, possibility =>
            {
                GetIteratively(new List<int[]> { new[] { 0, possibility } }, allResults, possibilities.RemoveAllClone(x => x == 0 || x == possibility));
            });
            return allResults;
        }
        public static void GetIteratively(List<int[]> result, BlockingCollection<List<int[]>> allResults, List<int> possibilities)
        {
            Stack<Tuple<List<int[]>, List<int>>> stack = new Stack<Tuple<List<int[]>, List<int>>>();
            stack.Push(new Tuple<List<int[]>,List<int>>(result, possibilities));
            while (stack.Count > 0)
            {
                var pop = stack.Pop();
                if (pop.Item2.Count > 0)
                    pop.Item2.ForEach(x => stack.Push(new Tuple<List<int[]>, List<int>>(new List<int[]>(result) { new int[] { pop.Item2[0], x } }, pop.Item2.RemoveAllClone(y => (y == pop.Item2[0] || y == x)))));
                else
                    allResults.Add(result);
            }   
        }
    
        public static List<T> RemoveAllClone<T>(this IEnumerable<T> source, Predicate<T> match)
        {
            var clone = new List<T>(source);
            clone.RemoveAll(match);
            return clone;
        }