コード例 #1
0
        public static (int number, int newNumber) Solve(int[] numbers)
        {
            Array.Sort(numbers);

            int maxSum = 0;

            for (int i = 0; i < numbers.Length; i++)
            {
                maxSum += numbers[i];
            }

            PartialSumsData data = new PartialSumsData(maxSum);

            BitArraySlim currSums = new BitArraySlim(1);

            currSums.ForceSet(0, 1);


            CreateAllSumsDatas(numbers, currSums, data);

            return(CreateCollisionAvoidanceArray(data.Sums, data.Datas, data));
        }
コード例 #2
0
        private static (int number, int newNumber) CreateCollisionAvoidanceArray(BitArraySlim sums, BestSumsData bestData, PartialSumsData data)
        {
            SumsData sumData = bestData.Data.ToSumsData(bestData.Number, data.SumsCount);

            foreach (var unique in sumData.Uniques)
            {
                sums.ForceSet(unique, 0);
            }

            for (int i = 1; i <= sums.Length;)
            {
                bool foundObstacle = false;
                foreach (var newSum in sumData.NewSums)
                {
                    int overlapIndex = newSum - (bestData.Number - i);
                    int offset       = 0;
                    while (overlapIndex + offset < sums.Length && sums[overlapIndex + offset] == 1)
                    {
                        offset++;
                    }

                    i += offset;
                    if (offset > 0)
                    {
                        foundObstacle = true;
                        break;
                    }
                }

                if (!foundObstacle)
                {
                    return(bestData.Number, i);
                }
            }

            throw new Exception("impossible!.... i thought");
        }
コード例 #3
0
 private static void CreateAllSums(int number, BitArraySlim currSums, PartialSumsData data)
 {
     data.Sums      = CreatePartialSums(new int[] { number }, currSums, data);
     data.SumsCount = BoolArrayTrueCount(data.Sums);
 }
コード例 #4
0
        private static PreSumsData FinishCreateSumsData(int number, BitArraySlim currSums, int currSumsCount, PartialSumsData data)
        {
            if (data.SumsCount != -1)
            {
                int uniqueSums = data.SumsCount - currSumsCount;
                return(new PreSumsData(currSums, uniqueSums));
            }

            if (data.SumsCount == -1)
            {
                CreateAllSums(number, currSums, data);
                data.SumsCount = BoolArrayTrueCount(data.Sums);
            }

            int uniques = 0;

            for (int i = 0; i < currSums.Length; i++)
            {
                if (currSums[i] == 1)
                {
                    int newSum = i + number;
                    if (newSum >= currSums.Length)
                    {
                        uniques++;
                    }
                    else if (currSums[newSum] == 0)
                    {
                        uniques++;
                    }
                }
            }

            return(new PreSumsData(currSums, uniques));
        }
コード例 #5
0
        private static BitArraySlim CreatePartialSums(Span <int> numbers, BitArraySlim currSums, PartialSumsData data)
        {
            int maxSum = currSums.Length;

            for (int i = 0; i < numbers.Length; i++)
            {
                maxSum += numbers[i];
            }

            BitArraySlim newSums = data.Storage.Pop(maxSum);

            currSums.CopyToAndClearRest(newSums);


            int prevMaxSum = currSums.Length - 1;

            for (int i = 0; i < numbers.Length; i++)
            {
                CreateSumsVectorized(prevMaxSum, numbers[i], newSums);
                prevMaxSum += numbers[i];
            }

            return(newSums);
        }
コード例 #6
0
        private static bool CreateAllSumsDatas(Span <int> numbers, BitArraySlim currSums, PartialSumsData data)
        {
            if (numbers.Length > 1)
            {
                int        midPoint   = numbers.Length / 2;
                Span <int> firstPart  = numbers.Slice(0, midPoint);
                Span <int> secondPart = numbers.Slice(midPoint);

                BitArraySlim secondPartSums = CreatePartialSums(secondPart, currSums, data);
                if (!CreateAllSumsDatas(firstPart, secondPartSums, data))
                {
                    data.Storage.Push(secondPartSums);
                }

                BitArraySlim firstPartSums = CreatePartialSums(firstPart, currSums, data);
                if (!CreateAllSumsDatas(secondPart, firstPartSums, data))
                {
                    data.Storage.Push(firstPartSums);
                }
            }
            else
            {
                data.Created++;

                int actualSumCount = BoolArrayTrueCount(currSums);
                if (data.SumsCount - actualSumCount > data.Minuniques)
                {
                    return(false);
                }

                int number = numbers[0];
                if (!data.FoundData.Contains(number))
                {
                    BestSumsData newData = new BestSumsData(number, FinishCreateSumsData(number, currSums, actualSumCount, data));
                    data.Minuniques = Math.Min(data.Minuniques, data.Datas.Data.Uniques);

                    if (newData.Data.Uniques < data.Datas.Data.Uniques ||
                        (newData.Data.Uniques == data.Datas.Data.Uniques &&
                         newData.Number < data.Datas.Number))
                    {
                        if (data.Datas.Data.BitArray != null)
                        {
                            data.Storage.Push(data.Datas.Data.BitArray);
                        }
                        data.Datas = newData;
                        return(true);
                    }
                }
            }

            return(false);
        }