コード例 #1
0
        //Binary decision between doubling and adding the next sequential power of 3
        //Starts from 1, first power of 3 added is 3^1 = 3
        public static IEnumerable <long> EnumerateTwoThreeDecisionSequenceResults(int max)        //capToMaximum = true
        {
            if (max > int.MaxValue)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(max),
                          max,
                          nameof(max) + " is greater than int.MaxValue, so not all summed paths would be possible to return."
                          );
            }
            if (max < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(max), max, "Cannot be less than 1.");
            }

            var decisionTracker = new TwoThreeDecisionTracker(max: max);

            //Console.WriteLine("#A : " + decisionTracker.Current + " " + decisionTracker.ToString());
            decisionTracker.DoubleRepeatedlyUpToMax();

            while (decisionTracker.TryAddNextPowerOf3())
            {
                //Console.WriteLine("#A2: " + decisionTracker.Current + " " + decisionTracker.ToString());
            }

            //Console.WriteLine("#B : " + decisionTracker.Current + " " + decisionTracker.ToString());
            yield return(decisionTracker.Current);        //Reached maximum length of this branch; yield the branch's result

            while (!decisionTracker.IsAtRoot)             //Starts at root but we did an initial repeated doubling; when we get back to the root we're done
            {
                //Console.WriteLine("#C : " + decisionTracker.Current + " " + decisionTracker.ToString());
                if (decisionTracker.BacktrackAndCheckIfWasDoublingOp())
                {
                    //Console.WriteLine("#D : " + decisionTracker.Current + " " + decisionTracker.ToString());
                    if (decisionTracker.TryAddNextPowerOf3())
                    {
                        //Console.WriteLine("#E : " + decisionTracker.Current + " " + decisionTracker.ToString());
                        decisionTracker.DoubleRepeatedlyUpToMax();

                        while (decisionTracker.TryAddNextPowerOf3())
                        {
                            //Console.WriteLine("#E2: " + decisionTracker.Current + " " + decisionTracker.ToString());
                        }

                        //Console.WriteLine("#F : " + decisionTracker.Current + " " + decisionTracker.ToString());
                        yield return(decisionTracker.Current);                        //Reached maximum length of this branch; yield the branch's result
                    }
                    else
                    {
                        //Console.WriteLine("#G : " + decisionTracker.Current + " " + decisionTracker.ToString());
                        //Adding the next power of 3 makes it too big; loop around to backtrack again
                        //But first, yield the current branch as we've now explored all sub-branches (see below)
                        yield return(decisionTracker.Current);

                        continue;
                    }
                }
                else
                {
                    //Console.WriteLine("#H : " + decisionTracker.Current + " " + decisionTracker.ToString());
                    //Explored all sub-branches of the current branch; yield the current branch
                    //When we first go into the branch, we're doubling repeatedly so can't yield at every step,
                    //but here we can't do anything repeatedly, so for efficiency do the yielding here.
                    yield return(decisionTracker.Current);
                }
            }
        }
コード例 #2
0
        //Returns an array that, for each position corresponding to a result found, contains the exponents
        //used on the highest power of 3 involved each time that result was reached, all encoded as binary flags.
        public static LongChunkedArray <int> GetExpansionRegister(int max)
        {
            if (max > int.MaxValue)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(max),
                          max,
                          nameof(max) + " is greater than int.MaxValue, so not all summed paths would be possible to return."
                          );
            }
            if (max < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(max), max, "Cannot be less than 1.");
            }

            var decisionTracker   = new TwoThreeDecisionTracker(max: max);
            var expansionRegister = new LongChunkedArray <int>(max + 1, 16777216);

            // ^ For each position corresponding to a result found, contains exponent that was used on the
            //last power of 3 added to get to that result. This is encoded as a binary flag, so that if a
            //given result is reached multiple times using different powers of 3, all of the powers can be
            //recorded without needing additional storage.
            //	//If that result has been reached multiple times,
            //	//contains the one that was reached most recently.
            //	//	//contains the one that's closest to 3/4 * log3(10,000). This is a rough estimate for the
            //	//	//exponent that is likely to be repeated the most, saving the most steps.

            //Console.WriteLine("#A : " + decisionTracker.Current + " " + decisionTracker.ToString());
            decisionTracker.DoubleRepeatedlyUpToMax();

            while (decisionTracker.TryAddNextPowerOf3())
            {
                //Console.WriteLine("#A2: " + decisionTracker.Current + " " + decisionTracker.ToString());
            }

            //Console.WriteLine("#B : " + decisionTracker.Current + " " + decisionTracker.ToString());
            //Console.WriteLine(decisionTracker.LastAddedThreeExponent + " " + decisionTracker.Current);
            //yield return decisionTracker.Current;
            //Reached maximum length of this branch; yield the branch's result
            expansionRegister[decisionTracker.Current] |= 1 << decisionTracker.LastAddedThreeExponent;

            while (!decisionTracker.IsAtRoot)             //Starts at root but we did an initial repeated doubling; when we get back to the root we're done
            {
                //Console.WriteLine("#C : " + decisionTracker.Current + " " + decisionTracker.ToString());
                if (decisionTracker.BacktrackAndCheckIfWasDoublingOp())
                {
                    if ((expansionRegister[decisionTracker.Current] & (1 << decisionTracker.LastAddedThreeExponent)) > 0)
                    {
                        continue;                                                                                                                       //Already done this branch
                    }
                    //Console.WriteLine("#D : " + decisionTracker.Current + " " + decisionTracker.ToString());
                    if (decisionTracker.TryAddNextPowerOf3())
                    {
                        if ((expansionRegister[decisionTracker.Current] & (1 << decisionTracker.LastAddedThreeExponent)) > 0)
                        {
                            continue;                                                                                                                           //Already done this branch
                        }
                        //Console.WriteLine("#E : " + decisionTracker.Current + " " + decisionTracker.ToString());
                        decisionTracker.DoubleRepeatedlyUpToMax();

                        if ((expansionRegister[decisionTracker.Current] & (1 << decisionTracker.LastAddedThreeExponent)) > 0)
                        {
                            continue;                                                                                                                           //Already done this branch
                        }
                        while (decisionTracker.TryAddNextPowerOf3())
                        {
                            if ((expansionRegister[decisionTracker.Current] & (1 << decisionTracker.LastAddedThreeExponent)) > 0)
                            {
                                continue;                                                                                                                               //Already done this branch
                            }
                            //Console.WriteLine("#E2: " + decisionTracker.Current + " " + decisionTracker.ToString());
                        }

                        //Console.WriteLine("#F : " + decisionTracker.Current + " " + decisionTracker.ToString());
                        //Console.WriteLine(decisionTracker.LastAddedThreeExponent + " " + decisionTracker.Current);
                        //yield return decisionTracker.Current;
                        //Reached maximum length of this branch; yield the branch's result
                        expansionRegister[decisionTracker.Current] |= 1 << decisionTracker.LastAddedThreeExponent;
                    }
                    else
                    {
                        //Console.WriteLine("#G : " + decisionTracker.Current + " " + decisionTracker.ToString());
                        //Console.WriteLine(decisionTracker.LastAddedThreeExponent + " " + decisionTracker.Current);
                        //yield return decisionTracker.Current;
                        //Adding the next power of 3 makes it too big; loop around to backtrack again
                        //But first, yield the current branch as we've now explored all sub-branches (see below)
                        expansionRegister[decisionTracker.Current] |= 1 << decisionTracker.LastAddedThreeExponent;

                        continue;
                    }
                }
                else
                {
                    //Console.WriteLine("#H : " + decisionTracker.Current + " " + decisionTracker.ToString());
                    //Console.WriteLine(decisionTracker.LastAddedThreeExponent + " " + decisionTracker.Current);
                    //yield return decisionTracker.Current;
                    //Explored all sub-branches of the current branch; yield the current branch
                    //When we first go into the branch, we're doubling repeatedly so can't yield at every step,
                    //but here we can't do anything repeatedly, so for efficiency do the yielding here.
                    expansionRegister[decisionTracker.Current] |= 1 << decisionTracker.LastAddedThreeExponent;
                }
            }

            return(expansionRegister);
        }