Skip to content

Instantly share code, notes, and snippets.

@francipvb
Created March 29, 2019 01:19
Show Gist options
  • Save francipvb/1b02db167e29a02bfa1343e60b4e6d8b to your computer and use it in GitHub Desktop.
Save francipvb/1b02db167e29a02bfa1343e60b4e6d8b to your computer and use it in GitHub Desktop.
Calculating prime numbers with enumerable functions and tasks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Prime
{
class Program
{
public static void Main(string[] args)
{
// Without this, we cann't cancel the operation gracefully
var token = new CancellationTokenSource();
// Here we use the cancellation token to cancel an operation
Console.CancelKeyPress += (sender, e) =>
{
e.Cancel = true;
token.Cancel();
};
// Start time
var t1 = DateTime.Now;
// This is not a list of prime numbers, but an enumerable
// This functions doesn't runs until we attempt to get the enumeration results
var numList = GetPrimeNumbers(8, token.Token);
// This runs the iterator until the end
var numCount = numList.Count();
// End time
var t2 = DateTime.Now;
// Time difference
var tDif = t2 - t1;
// Print our results (not the number list, but the number count)
Console.WriteLine("Got {0} prime numbers in {1:m' minutes, 's' seconds'}.", numCount, tDif);
Console.ReadKey();
}
private static IEnumerable<ulong> GetPrimeNumbers(int tasks, CancellationToken token)
{
var tList = new List<Task<(ulong, bool)>>();
for (ulong i = 1; i < ulong.MaxValue; i++)
{
if (tList.Count < tasks)
{
// We need to do this concurrently, so we must add these tasks to a list
tList.Add(Task.Run(
() => (i, IsPrime(i, token))));
}
if (token.IsCancellationRequested)
{
// If we pressed CTRL+C, it is true
// We can break the for loop here and check for completed tasks.
break;
}
if (tList.Count == tasks)
{
var tarea = Task.WhenAny(tList);
// We must wait until any of these tasks is completed
tarea.Wait();
// Now, we must make a place to another task
tList.Remove(tarea.Result);
if (!tarea.Result.IsCompletedSuccessfully)
{
throw tarea.Result.Exception;
}
if (tarea.Result.Result.Item2)
{
// Here are the magic of enumerator functions
yield return tarea.Result.Result.Item1;
}
}
}
// Probably there are incomplete tasks
foreach (var t in Task.WhenAll(tList)
.GetAwaiter()
.GetResult())
{
if (t.Item2)
{
// Returning the rest of the results
yield return t.Item1;
}
}
}
private static bool IsPrime(ulong num, CancellationToken token = default(CancellationToken))
{
if (num == 0)
{
return false;
}
if (num <= 3)
{
return true;
}
for (ulong i = 2; i <= num / 2; i++)
{
if (num % i == 0)
{
return false;
}
}
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment