public void TestModdedLongArithmetic() { ModdedLong m = new ModdedLong(2, 3); long test = m + 2 - 1; Assert.AreEqual(0, test); //Was an interesting bug where m was being implicity converted to an int first test = m + 2L - 1L; Assert.AreEqual(0, test); }
/// <summary> /// The expected money we get while filling out the interval [i, j) /// so that the last filled gondola is at position (i+k) is: /// </summary> /// <param name="gondalas"></param> /// <param name="i"></param> /// <param name="j"></param> /// <param name="k"></param> /// <param name="N"></param> /// <returns></returns> public static BruteForceFracClass E_bruteForce(bool[] gondalas, int i, int j, int k, int N) { Preconditions.checkState(gondalas[j] == false); Logger.LogDebug("E_bruteForce {} [{} to {}] k={}", gondalas.ToCommaString(), i, j, k); bool[] ij = Wheel.copyArray(gondalas, i, j); //Otherwise too slow Preconditions.checkState(ij.Length <= 7); int holeCount = ij.Count((b) => !b); ModdedLong pos = new ModdedLong(i, gondalas.Length); ModdedLong stop = new ModdedLong(j, gondalas.Length); ModdedLong mid = new ModdedLong(i + k, gondalas.Length); Preconditions.checkState(ModdedLong.isStrictlyBetween(pos - 1, stop, mid)); if (gondalas[mid]) return 0; //Now cycle through all permutations int numerator = 0; int denominator = 0; foreach (List<int> perm in Combinations.nextPermutationWithRepetition(holeCount - 1, ij.Length - 1)) { int value = simulatePermutationExpectedValue(ij, perm, k, N); Logger.LogTrace("Perm {} for ij {} Value {}", perm.ToCommaString(), ij.ToCommaString(), value); if (value == -1) continue; numerator += value; ++denominator; } Logger.LogTrace(" Return {} / {}", numerator, denominator); return new BruteForceFracClass(numerator, denominator); }
public void TestInc() { ModdedLong l = new ModdedLong(1, 3); Assert.AreEqual(1, l); Assert.AreEqual(2, ++l); Assert.AreEqual(2, l); Assert.AreEqual(2, l++); Assert.AreEqual(0, l); }
// /// <summary> /// The probability that gondola j stays empty while we fill interval [i, j) and that /// gondola at position (i+k) is filled last is P(i, j, k) and can be computed as: /// </summary> /// <param name="gondalas">True if filled, false if empty</param> /// <param name="i"></param> /// <param name="j"></param> /// <param name="k"></param> /// <returns></returns> public static BruteForceFracClass P_bruteForce(bool[] gondalas, int i, int j, int k) { Preconditions.checkState(gondalas[j] == false); Logger.LogDebug("P_bruteForce {} [{} to {}] k={}", gondalas.ToCommaString(), i, j, k); bool[] ij = Wheel.copyArray(gondalas, i, j); //Otherwise too slow Preconditions.checkState(ij.Length <= 8); int holeCount = ij.Count((b) => !b); ModdedLong pos = new ModdedLong(i, gondalas.Length); ModdedLong stop = new ModdedLong(j, gondalas.Length); ModdedLong mid = new ModdedLong(i + k, gondalas.Length); Preconditions.checkState(ModdedLong.isStrictlyBetween(pos - 1, stop, mid)); if (gondalas[mid]) return 0; //Now cycle through all permutations int numerator = 0; int denominator = 0; foreach (List<int> perm in Combinations.nextPermutationWithRepetition(holeCount, ij.Length)) { Logger.LogTrace("Perm {} for ij {}. ", perm.ToCommaString(), ij.ToCommaString()); if (0 != simulatePermutation(ij, perm, k)) { Logger.LogTrace("Perm {} for ij {}. mid filled 2nd to last {}", perm.ToCommaString(), ij.ToCommaString(), mid.Value); ++numerator; } ++denominator; } return new BruteForceFracClass(numerator, denominator); }
public void testModdedLong2() { int mod = 1000002013; //int an = ModdedLong.modInverse(2, mod); long start = 35184372088832; long end = start + 1000; for (long v = start; v <= end; ++v) { for (long j = 2; j < 3; ++j) { if (v % j != 0) continue; long real = v / j; ModdedLong ml = new ModdedLong(v, mod); ml /= (int)j; Assert.AreEqual(real % mod, ml.Value, "{0} / {1} % {2}".FormatThis(v, j, mod)); } } }
public void testModdedLong() { int mod = 7; for(int i = 2; i <= 800; ++i) { for(int j = 2; j < 3; ++j) { if (i % j != 0) continue; int real = i / j; ModdedLong ml = new ModdedLong(i, mod); ml /= j; Assert.AreEqual(real % mod, ml.Value, "{0} / {1} % {2}".FormatThis(i,j,mod)); } } }
private int GetHoleCount(int i, int j, out int ijLength) { int holeCount = 0; ModdedLong stop = new ModdedLong(j, N); for (ModdedLong idx = new ModdedLong(i, N); idx != stop; ++idx) if (!gondalas[idx]) holeCount++; ijLength = ModdedLong.diff(i, j, N) + 1; return holeCount; }
/// <summary> /// The expected money we get while filling out the interval [i, j) /// so that the last filled gondola is at position (i+k). /// /// This means that the value for filling j is not counted /// </summary> /// <param name="i"></param> /// <param name="j"></param> /// <param name="k"></param> /// <returns></returns> public FracClass E(int i, int j, int k) { if (init != Eijk_memoize[i][j][k]) { //Logger.LogDebug("Memoize E {} {} {}", i, j, k); return Eijk_memoize[i][j][k]; } //Logger.LogTrace("E {} {} {} {} N {}", gondalas.ToCommaString(), i, j, k, N); // ModdedLong start = new ModdedLong(i, gondalas.Length); ModdedLong stop = new ModdedLong(j, gondalas.Length); ModdedLong mid = new ModdedLong(i + k, N); Preconditions.checkState(!gondalas[stop]); if (gondalas[mid]) { return Eijk_memoize[i][j][k] = 0; } FracClass expectedLeft = E(i, mid); FracClass expectedRight = E(mid + 1, stop); #if USE_DOUBLE FracClass ans = expectedLeft + expectedRight + N - (double) k /2; #else FracClass ans = expectedLeft + expectedRight + N - new FracClass(k, 2); #endif Logger.LogTrace(" E({},{}) = {} + E({},{}) = {} + {} = {}", i, mid, expectedLeft, mid + 1, stop, expectedRight, N, ans); //FracClass check = Wheel.E_bruteForce(gondalas, i, j, k, N); // Preconditions.checkState(check.Equals(ans)); return Eijk_memoize[i][j][k] = ans; }
/// <summary> /// The probability that gondola j stays empty while we fill interval [i, j) /// and that gondola at position (i+k) is filled last is P(i, j, k) and can be computed as /// </summary> /// <param name="i"></param> /// <param name="j"></param> /// <param name="k"></param> /// <returns></returns> public FracClass P(int i, int j, int k) { Preconditions.checkState(gondalas[j] == false); if (init != Pijk_memoize[i][j][k]) { //Logger.LogDebug("Memoize P {} {} {}", i, j, k); return Pijk_memoize[i][j][k]; } ModdedLong start = new ModdedLong(i, N); ModdedLong stop = new ModdedLong(j, N); ModdedLong mid = new ModdedLong(i + k, N); Preconditions.checkState(ModdedLong.isStrictlyBetween(start - 1, stop, mid)); if (gondalas[mid]) return Pijk_memoize[i][j][k] = 0; int totalLen = ModdedLong.diff(i, j, N) + 1; // [i, i+k] //bool[] firstHalf = Wheel.copyArray(gondalas, start, mid); // [i+k+1, j] //bool[] secondHalf = Wheel.copyArray(gondalas, mid + 1, stop); Preconditions.checkState(!gondalas[mid]); Preconditions.checkState(!gondalas[stop]); //Gondolas free in [i, k) int freeBeforeK = 0; //Gondolas free is [k+1, j) int freeAfterK = 0; //Does not count endpoints (mid for 1st half, stop for 2nd) for (ModdedLong idx = start; idx != mid; ++idx) if (!gondalas[idx]) ++freeBeforeK; for (ModdedLong idx = mid + 1; idx != stop; ++idx) if (!gondalas[idx]) ++freeAfterK; int firstHalfLen = 1 + ModdedLong.diff(start, mid, N); int secondHalfLen = 1 + ModdedLong.diff(mid + 1, stop, N); Preconditions.checkState(firstHalfLen + secondHalfLen == totalLen); //Choose people to go to first half -or- we can choose which ones go to second half. k and j are predetermined //int choose = Combinations.combin(freeBeforeK + freeAfterK, freeBeforeK); //long choose = Combinations.combin(freeBeforeK + freeAfterK, freeAfterK); BigInteger choose = CombinArray.Instance.combinArray[freeBeforeK + freeAfterK][freeAfterK]; //Probability that a + 1 people have a gondola on the left side FracClass f = 1; #if USE_DOUBLE for (int t = 0; t <= freeBeforeK; ++t) f *= (double)firstHalfLen / totalLen; for (int t = 0; t < freeAfterK; ++t) f *= (double) secondHalfLen / totalLen; #else for (int t = 0; t <= freeBeforeK; ++t) f *= new FracClass(firstHalfLen, totalLen); for (int t = 0; t < freeAfterK; ++t) f *= new FracClass(secondHalfLen, totalLen); #endif FracClass probLeft = P(start, mid); FracClass probRight = P(mid + 1, stop); #if USE_DOUBLE FracClass ans = (double)choose * f * probLeft * probRight; #else FracClass ans = choose * f * probLeft * probRight; #endif Preconditions.checkState(ans >= 0); //FracClass check = P_bruteForce(gondalas, i, j, k); //Preconditions.checkState(ans.Equals(check)); return Pijk_memoize[i][j][k] = ans; }