コード例 #1
0
ファイル: Part2.cs プロジェクト: jorupp/adventofcode2019
 public ModMathEvaluator AsInputTo(ModMathEvaluator wrap)
 {
     if (this.C != wrap.C)
     {
         throw new NotImplementedException();
     }
     return(new ModMathEvaluator((A * wrap.A).ModAbs(C), (wrap.A * B + wrap.B).ModAbs(C), C));
 }
コード例 #2
0
ファイル: Part2.cs プロジェクト: jorupp/adventofcode2019
        protected void RunScenario(string title, string input, long numCards, BigInteger targetPosition, long numShuffles)
        {
            RunScenario(title, () =>
            {
                var lines = input.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);


                ModMathEvaluator DealNewStack()
                {
                    return(new ModMathEvaluator(-1, -1, numCards));
                    //return (targetPosition) => (-1 * input(targetPosition) + -1).ModAbs(numCards);
                }

                ModMathEvaluator Cut(long count)
                {
                    return(new ModMathEvaluator(1, count, numCards));

                    ////if (count < 0)
                    ////{
                    ////    count = numCards + count;
                    ////}

                    //return (prev) =>
                    //{
                    //    var targetPosition = input(prev);
                    //    return (1 * targetPosition + count).ModAbs(numCards);
                    //    //if (targetPosition < numCards - count)
                    //    //{
                    //    //    return targetPosition + count;
                    //    //}
                    //    //else
                    //    //{
                    //    //    return targetPosition - (numCards - count);
                    //    //}
                    //};
                }

                ModMathEvaluator DealWithIncrement(long increment)
                {
                    long dealt         = 0;
                    long startPosition = 0;
                    for (var i = 0; ; i++)
                    {
                        //Console.WriteLine($"T {targetPosition} {startPosition} {increment}");
                        if ((1 - startPosition) % increment == 0)
                        {
                            break;
                        }

                        dealt         += (long)Math.Ceiling(((decimal)numCards - startPosition) / increment);
                        startPosition += increment - (numCards % increment);
                        startPosition %= increment;
                    }

                    //Console.WriteLine($"D {dealt} {targetPosition} {startPosition} {increment}");
                    dealt += (1 - startPosition) / increment;
                    var a  = dealt;

                    return(new ModMathEvaluator(a, 0, numCards));

                    //return (prev) =>
                    //{
                    //    var targetPosition = input(prev);
                    //    checked
                    //    {
                    //        return (a * targetPosition + 0).ModAbs(numCards);
                    //    }
                    //    //long dealt = 0;
                    //    //long startPosition = 0;
                    //    //for (var i = 0; ; i++)
                    //    //{
                    //    //    //Console.WriteLine($"T {targetPosition} {startPosition} {increment}");
                    //    //    if ((targetPosition - startPosition) % increment == 0)
                    //    //    {
                    //    //        break;
                    //    //    }

                    //    //    dealt += (long)Math.Ceiling(((decimal)numCards - startPosition) / increment);
                    //    //    startPosition += increment - (numCards % increment);
                    //    //    startPosition %= increment;
                    //    //}

                    //    ////Console.WriteLine($"D {dealt} {targetPosition} {startPosition} {increment}");
                    //    //dealt += (targetPosition - startPosition) / increment;

                    //    //return dealt;
                    //};
                }

                ModMathEvaluator Compute()
                {
                    var result = new ModMathEvaluator(1, 0, numCards);
                    foreach (var line in lines.Reverse())
                    {
                        if (line.StartsWith("deal with increment"))
                        {
                            var x  = long.Parse(line.Split(' ').Last());
                            result = result.AsInputTo(DealWithIncrement(x));
                        }
                        else if (line.StartsWith("cut"))
                        {
                            var x  = long.Parse(line.Split(' ').Last());
                            result = result.AsInputTo(Cut(x));
                        }
                        else if (line.StartsWith("deal into new stack"))
                        {
                            result = result.AsInputTo(DealNewStack());
                        }
                        else
                        {
                            throw new NotImplementedException(line);
                        }
                    }

                    return(result);
                }

                var compute = Compute();
                Console.WriteLine($"compute: {compute}");
                Console.WriteLine(compute.Apply(targetPosition));

                long shufflesComputeIs = 1;
                while (numShuffles > 0)
                {
                    Console.WriteLine($"Need to shuffle {numShuffles} more times");
                    Console.WriteLine($"Formula to shuffle {shufflesComputeIs} times is {compute}");
                    if (numShuffles % (shufflesComputeIs * 2) != 0)
                    {
                        Console.WriteLine($"Shuffling {shufflesComputeIs} times");
                        targetPosition = compute.Apply(targetPosition);

                        numShuffles -= shufflesComputeIs;
                    }

                    compute            = compute.AsInputTo(compute);
                    shufflesComputeIs *= 2;
                }

                Console.WriteLine(targetPosition);


                //var valForZero = Compute()(0);

                //// magic number derived from excel magic
                //Func<long, long> compute = (i) =>
                //{
                //    {
                //        return (long)((((new BigInteger(valForZero) - i * 15432842991580)) % numCards + numCards) % numCards);
                //        //return ((((valForZero - i * 15432842991580)) % numCards + numCards) % numCards);
                //    }
                //};

                //var realCompute = Compute();

                //Console.WriteLine(compute(1970) == realCompute(1970));
                //Console.WriteLine(compute(12124) == realCompute(12124));
                //Console.WriteLine(compute(312341) == realCompute(312341));
                //Console.WriteLine(compute(1212434) == realCompute(1212434));
                //Console.WriteLine(compute(12124322) == realCompute(12124322));
                //Console.WriteLine(compute(121243344) == realCompute(121243344));
                //Console.WriteLine(compute(1212233324) == realCompute(1212233324));
                //Console.WriteLine(compute(34324534523) == realCompute(34324534523));
                //Console.WriteLine(compute(123412341234) == realCompute(123412341234));


                //var splitPoint = BinarySearch.GetMax(i => compute(i) == realCompute(i), 312341, 0, numCards);
                ////Console.WriteLine($"Split point: {splitPoint}");
                ////Console.WriteLine(compute(splitPoint - 1));
                ////Console.WriteLine(realCompute(splitPoint - 1));
                ////Console.WriteLine(compute(splitPoint));
                ////Console.WriteLine(realCompute(splitPoint));
                ////Console.WriteLine(compute(splitPoint + 1));
                ////Console.WriteLine(realCompute(splitPoint + 1));


                //for (long i = -60; i < 50; i++)
                //{
                //    Console.WriteLine($"{splitPoint + i}: {realCompute(splitPoint + i):00000000000000000}  {compute(splitPoint + i):00000000000000000}");
                //}


                //var compute = Compute();
                //var targetForMax = compute(numCards - 1);
                //Console.WriteLine(targetForMax);
                //compute = (i) =>
                //    ((targetForMax - (i - (numCards - 1)) * 15432842991580)) % 119315717514047;
                //var initialTarget = targetPosition;

                //for (long i = -60; i < 50; i++)
                //{
                //    Console.WriteLine($"{targetPosition + i}: {compute(targetPosition + i):00000000000000000}");

                //}

                ////Console.WriteLine(targetPosition);

                //if (initialTarget == targetPosition)
                //{
                //    Console.WriteLine($"Looped in {i}");
                //    return;
                //}

                //if (targetPosition < 10000000)
                //{

                //    Console.WriteLine($"Got to {targetPosition} in  {i}");
                //    return;
                //}

                //if (i % 10000 == 0)
                //{
                //    Console.WriteLine($"Loop number {i}");
                //}
                //for (long i = 0; i < 50; i++)
                //{
                //    Console.WriteLine($"{i:000}: {string.Join(" ", Enumerable.Range(11, 10).Select(i => $"{(targetPosition / i):000000000000000}"))}");
                //    targetPosition = Compute(targetPosition);
                //}


                ////var compute = Compute();
                //var initialTarget = targetPosition;

                //var loopTarget = 101741582076661;
                //////var loopTarget = 101741582076661 % 8828312 + 8828312 * 1;
                ////long loopTarget = 1234567 + 8828312;

                ////Console.WriteLine($"Target: {loopTarget}");
                ////targetPosition = initialTarget;
                ////for (long j = 0; j < loopTarget; j++)
                ////{
                ////    targetPosition = compute(targetPosition);
                ////}
                ////Console.WriteLine($"True result for {loopTarget}: {targetPosition}");
                ////targetPosition = initialTarget;

                //var seen = new Dictionary<long, long>();
                //for (long i = 1; ; i++)
                //{

                //    targetPosition = compute(targetPosition);
                //    //Console.WriteLine(targetPosition);

                //    if (initialTarget == targetPosition)
                //    {
                //        Console.WriteLine($"Looped in {i}");
                //        return;
                //    }
                //    //if (targetPosition < 10000000)
                //    //{
                //    //    Console.WriteLine($"Got to {targetPosition} in  {i}");
                //    //    return;
                //    //}

                //    if (i % 10000 == 0)
                //    {
                //        Console.WriteLine($"Loop number {i}");
                //    }


                //    if (seen.TryGetValue(targetPosition, out var v))
                //    {
                //        var loopLength = (i - v);
                //        Console.WriteLine($"Looped from {i} to {v} in {loopLength}");
                //        var toRun = (loopTarget - v) % loopLength + v;
                //        Console.WriteLine($"Simulating {toRun} times");


                //        //targetPosition = initialTarget;
                //        //for (long j = 0; j < toRun; j++)
                //        //{
                //        //    targetPosition = compute(targetPosition);
                //        //}

                //        //Console.WriteLine(targetPosition);
                //        Console.WriteLine(seen.Single(i => i.Value == toRun).Key);

                //        return;
                //    }


                //    seen[targetPosition] = i;
                //}
            });
        }