/// <summary> /// Gets the lowest positive integer which when combined with a secret key has an MD5 hash whose /// hexadecimal representation starts with the specified number of zeroes. /// </summary> /// <param name="secretKey">The secret key to use.</param> /// <param name="zeroes">The number of zeroes to get the value for.</param> /// <returns> /// A <see cref="Task{TResult}"/> that represents the asynchronous operation to find the /// lowest positive integer that generates an MD5 hash with the number of zeroes specified. /// </returns> internal static async Task <int> GetLowestPositiveNumberWithStartingZeroesAsync(string secretKey, int zeroes) { var solutions = new ConcurrentBag <int>(); var searchedRanges = new ConcurrentBag <int>(); int fromInclusive = 1; int rangeSize = 50000; var chunks = Enumerable.Chunk(Enumerable.Range(fromInclusive, int.MaxValue - 1), rangeSize); using var cts = new CancellationTokenSource(); try { await Parallel.ForEachAsync( chunks, cts.Token, (range, cancellationToken) => { try { // Does this range start at a value greater than an already found value? if (!solutions.IsEmpty) { int bestSolution = solutions.Min(); if (range[0] > bestSolution) { var orderedRanges = searchedRanges.ToList(); if (orderedRanges.Count == 0) { return(ValueTask.CompletedTask); } orderedRanges.Sort(); // Have we searched the first possible range already? if (orderedRanges[0] == fromInclusive) { for (int i = 1; i < orderedRanges.Count; i++) { int lastRange = orderedRanges[i - 1]; int thisRange = orderedRanges[i]; // Is this range the next range? if (thisRange != lastRange + rangeSize) { // A range before the current best solution has not been searched yet break; } if (thisRange > bestSolution) { // We have found the best solution cts.Cancel(); } } } } return(ValueTask.CompletedTask); } foreach (int i in range) { if (cancellationToken.IsCancellationRequested) { break; } if (IsSolution(i, secretKey, zeroes)) { solutions.Add(i); break; } } } finally { searchedRanges.Add(range[0]); } return(ValueTask.CompletedTask); }); } catch (TaskCanceledException) { // Solution found } if (solutions.IsEmpty) { throw new PuzzleException("No answer was found for the specified secret key."); } return(solutions.Min()); }