Find valid assignments of integers in arrays (permutations with given order)

前端 未结 5 1389
醉梦人生
醉梦人生 2021-01-06 06:33

I am having a general problem finding a good algorithm for generating each possible assignment for some integers in different arrays.

Lets say I have n arrays and m

5条回答
  •  臣服心动
    2021-01-06 07:32

    The following code is written in C#.

    class LineList : List 
    {
        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.Append(Count).AppendLine(" lines:");
            foreach (var line in this)
            {
                if (line.Length > 0)
                {
                    foreach (var bucket in line)
                    {
                        sb.Append('{');
                        foreach (var item in bucket)
                        {
                            sb.Append(item).Append(',');
                        }
                        if (bucket.Length > 0)
                        {
                            sb.Length -= 1;
                        }
                        sb.Append("}, ");
                    }
                    sb.Length -= 2;
                }
                sb.AppendLine();
            }
            return sb.ToString();
        }
    }
    
    class Permutor
    {
        public T[] Items { get; private set; }
        public bool ReuseBuckets { get; set; }
        private T[] emptyBucket_;
        private Dictionary> buckets_;   // for memoization when ReuseBuckets=true
        public Permutor(T[] items)
        {
            ReuseBuckets = true;  // faster and uses less memory
            Items = items;
            emptyBucket_ = new T[0];
            buckets_ = new Dictionary>();
        }
        private T[] GetBucket(int index, int size)
        {
            if (size == 0)
            {
                return emptyBucket_;
            }
            Dictionary forIndex;
            if (!buckets_.TryGetValue(index, out forIndex))
            {
                forIndex = new Dictionary();
                buckets_[index] = forIndex;
            }
            T[] bucket;
            if (!forIndex.TryGetValue(size, out bucket))
            {
                bucket = new T[size];
                Array.Copy(Items, index, bucket, 0, size);
                forIndex[size] = bucket;
            }
            return bucket;
        }
        public LineList GetLines(int bucketsPerLine)
        {
            var lines = new LineList();
            if (bucketsPerLine > 0)
            {
                AddLines(lines, bucketsPerLine, 0);
            }
            return lines;
        }
        private void AddLines(LineList lines, int bucketAllotment, int taken)
        {
            var start = bucketAllotment == 1 ? Items.Length - taken : 0;
            var stop = Items.Length - taken;
            for (int nItemsInNextBucket = start; nItemsInNextBucket <= stop; nItemsInNextBucket++)
            {
                T[] nextBucket;
                if (ReuseBuckets)
                {
                    nextBucket = GetBucket(taken, nItemsInNextBucket);
                }
                else
                {
                    nextBucket = new T[nItemsInNextBucket];
                    Array.Copy(Items, taken, nextBucket, 0, nItemsInNextBucket);
                }
                if (bucketAllotment > 1)
                {
                    var subLines = new LineList();
                    AddLines(subLines, bucketAllotment - 1, taken + nItemsInNextBucket);
                    foreach (var subLine in subLines)
                    {
                        var line = new T[bucketAllotment][];
                        line[0] = nextBucket;
                        subLine.CopyTo(line, 1);
                        lines.Add(line);
                    }
                }
                else
                {
                    var line = new T[1][];
                    line[0] = nextBucket;
                    lines.Add(line);
                }
            }
        }
    
    }
    

    These calls...

    var permutor = new Permutor(new[] { 1, 2, 3 });
    for (int bucketsPerLine = 0; bucketsPerLine <= 4; bucketsPerLine++)
    {
        Console.WriteLine(permutor.GetLines(bucketsPerLine));
    }
    

    generate this output...

    0 lines:
    
    1 lines:
    {1,2,3}
    
    4 lines:
    {}, {1,2,3}
    {1}, {2,3}
    {1,2}, {3}
    {1,2,3}, {}
    
    10 lines:
    {}, {}, {1,2,3}
    {}, {1}, {2,3}
    {}, {1,2}, {3}
    {}, {1,2,3}, {}
    {1}, {}, {2,3}
    {1}, {2}, {3}
    {1}, {2,3}, {}
    {1,2}, {}, {3}
    {1,2}, {3}, {}
    {1,2,3}, {}, {}
    
    20 lines:
    {}, {}, {}, {1,2,3}
    {}, {}, {1}, {2,3}
    {}, {}, {1,2}, {3}
    {}, {}, {1,2,3}, {}
    {}, {1}, {}, {2,3}
    {}, {1}, {2}, {3}
    {}, {1}, {2,3}, {}
    {}, {1,2}, {}, {3}
    {}, {1,2}, {3}, {}
    {}, {1,2,3}, {}, {}
    {1}, {}, {}, {2,3}
    {1}, {}, {2}, {3}
    {1}, {}, {2,3}, {}
    {1}, {2}, {}, {3}
    {1}, {2}, {3}, {}
    {1}, {2,3}, {}, {}
    {1,2}, {}, {}, {3}
    {1,2}, {}, {3}, {}
    {1,2}, {3}, {}, {}
    {1,2,3}, {}, {}, {}
    

    The approximate size of the solution (bucketsPerLine * NumberOfLines) dominates the execution time. For these tests, N is the length of the input array and the bucketsPerLine is set to N as well.

    N=10, solutionSize=923780, elapsedSec=0.4, solutionSize/elapsedMS=2286
    N=11, solutionSize=3879876, elapsedSec=2.1, solutionSize/elapsedMS=1835
    N=12, solutionSize=16224936, elapsedSec=10.0, solutionSize/elapsedMS=1627
    N=13, solutionSize=67603900, elapsedSec=47.9, solutionSize/elapsedMS=1411
    

提交回复
热议问题