private void CalcAllowedRemainders() { var additionals = new ulong[] { 1, 3, 7, 9, 13, 27 }; allowedRemainders = new List <Tuple <ulong, HashSet <ulong> > >(); foreach (var i in firstFewPrimes.Take(1000)) { var allowed = new HashSet <ulong>(); for (var j = 0ul; j < i; j++) { var jsqr = (j * j) % i; if (additionals.All(a => MyMath.ExtendedEuclidGcd(jsqr + a, i) == 1)) { allowed.Add(j); } } allowedRemainders.Add(Tuple.Create(i, allowed)); } }
public override string Part2() { var init = GetMoons().ToList(); var moons = GetMoons().ToList(); var pairs = Ext.GetCombinations(moons, 2).Select(x => (x.First(), x.Last())).ToList(); var cycles = new ulong[3]; ulong steps = 0; while (true) { steps++; Step(moons, pairs); for (var j = 0; j < 3; j++) { var ok = true; foreach (var i in Enumerable.Range(0, moons.Count)) { if (!(moons[i].Pos[j] == init[i].Pos[j] && moons[i].Vel[j] == 0 && cycles[j] == 0)) { ok = false; break; } } if (ok) { cycles[j] = steps; } } if (cycles.All(x => x != 0)) { return(Ext.NWW(cycles[0], Ext.NWW(cycles[1], cycles[2])).ToString()); } } }
/// <summary> /// Perform an audio fingerprint correlation /// n signatures, taken from s1 are compared with m signatures taken from s2 /// m must be greater than n. /// The output is an array of coincident bits for each offset of the (n - m) * NBITS possible /// where NBITS is the number of bits per signature (frame) /// /// The expected alignment should be with s1 located centrally in s2 /// e.g. if n = 9, m = 19, the expected alignment should look like this: /// ######### /// ################### /// </summary> /// <param name="channel"></param> /// <param name="s1"></param> /// <param name="n"></param> /// <param name="s2"></param> /// <param name="m"></param> /// <returns></returns> public static int[] Correlate(int channel, IEnumerable <Fingerprint> s1, int n, IEnumerable <Fingerprint> s2, int m, out bool chPresent1, out bool chPresent2) { int nbits = 0; chPresent1 = false; chPresent2 = false; var bufn = new ulong[n + 1]; var mask = 0UL; var i = 0; foreach (var s in s1) { if (nbits == 0) { nbits = s.AudioSize; mask = (1UL << nbits) - 1UL; } else if (nbits != s.AudioSize) { throw new ApplicationException("Incompatible audio fingerprints"); } bufn[i++] = s.AudioFingerprints[channel] & mask; if ((s.AudioFingerprints[channel] & 0x8000000000000000) != 0) { chPresent1 = true; } if (i > n) { break; } } var bufm = new ulong[m]; i = 0; foreach (var s in s2) { if (nbits != s.AudioSize) { throw new ApplicationException("Incompatible audio fingerprints"); } bufm[i++] = s.AudioFingerprints[channel] & mask; if ((s.AudioFingerprints[channel] & 0x8000000000000000) != 0) { chPresent2 = true; } if (i >= m) { break; } } // If either buffer is empty then just return null // Note: This is principally checking the "signal present" bit, the MSB of the fingerprint if (bufn.All(b => b == 0) || bufm.All(b => b == 0)) { return(null); } var frameShifts = m - n; if (frameShifts < 0) { throw new ApplicationException("needle bigger than haystack"); } // Set up the correlation results var result = new int[nbits * frameShifts]; // Do the correlation for (var bitShift = 0; bitShift < nbits; bitShift++) { for (var frameShift = 0; frameShift < frameShifts; frameShift++) { var count = 0; for (var frame = 0; frame <= n; frame++) { count += 16 - BitCounter.Count(bufn[frame] ^ bufm[frame + frameShift]); } result[frameShift * nbits + bitShift] = count; } // Now shift bufn by one bit // Note that the signatures run in time from MSB to LSB so we shift right var carry = 0UL; for (var j = 0; j < n; j++) { var carryout = bufn[j] & 1; bufn[j] = (bufn[j] >> 1) | carry << (nbits - 1); carry = carryout; } } return(result); }