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)); }
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; //} }); }