﻿using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace P12_HighlyDivisibleTriangular {
	/// <summary>
	/// From: https://projecteuler.net/problem=12
	/// The sequence of triangle numbers is generated by adding the natural numbers.
	/// So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28.
	/// The first ten terms would be:
	/// 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
	/// </summary>

	internal class Program {
		private static void Main(string[] args) {
			int runCount = 0;
			char escape = 'y';
			do {
				runCount++;
				Console.Clear();
				Console.WriteLine("\n==Regular==");
				TriangularNumDivisors();
				Console.WriteLine("\n==Threaded==");
				ParallelTriangularNumDivisors();
				Console.WriteLine("\n[Hit 'y' to run again or anything else to end]");
				escape = Console.ReadKey().KeyChar;
			} while (escape == 'y');

		}

		#region SingleThread

		private static void TriangularNumDivisors() {
			long num = 0L;
			long i = 1L;
			TimeSpan ts;
			long tickCounter;
			Stopwatch stw = new Stopwatch();
			stw.Start();
			while (FindDivisorsOfTriangularNumber(num) < 500) {
				num += i;
				i++;
			}
			stw.Stop();
			ts = stw.Elapsed;
			tickCounter = stw.ElapsedTicks;
			string elapsed = String.Format("{0}ms", ts.TotalMilliseconds);
			Console.WriteLine("Triangular number with 500 divisors: {0} \nTime:\t{1} \nTicks:\t{2}", num, elapsed, tickCounter);
		}
		private static long FindDivisorsOfTriangularNumber(long triNum) {
			long divCount;
			divCount = 0;
			long squareRoot = (long)Math.Sqrt(triNum);
			for (int i = 1; i <= squareRoot; i++) {
				if ((triNum % i) == 0) {
					divCount += 2;
				}
			}
			if (squareRoot * squareRoot == triNum) {
				divCount--;
			}
			return divCount;
		}

		#endregion SingleThread

		#region Parallel

		private static void ParallelTriangularNumDivisors() {
			long num = 0L;
			long i = 1L;
			TimeSpan ts;
			long tickCounter;
			Stopwatch stw = new Stopwatch();
			stw.Start();
			while (ParallelFindDivisorsOfTriangularNumber(num) < 500) {
				num += i;
				i++;
			}
			stw.Stop();
			ts = stw.Elapsed;
			tickCounter = stw.ElapsedTicks;
			string elapsed = String.Format("{0}ms", ts.TotalMilliseconds);
			Console.WriteLine("Triangular number with 500 divisors: {0} \nTime:\t{1} \nTicks:\t{2}", num, elapsed, tickCounter);

		}
		private static long ParallelFindDivisorsOfTriangularNumber(long triNum) {
			long divCount;

			divCount = 0;
			long squareRoot = (long)Math.Sqrt(triNum);
			Parallel.For(1L, squareRoot, i =>
			{
				if ((triNum % i) == 0) {
					divCount += 2;
				}
			});
			if (squareRoot * squareRoot == triNum) {
				divCount--;
			}

			return divCount;
		}

		#endregion Parallel

	}
}