Skip to content

Instantly share code, notes, and snippets.

@RichardVasquez
Last active December 24, 2015 09:49
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save RichardVasquez/6780214 to your computer and use it in GitHub Desktop.
WAY overdoing Euler Project Problem 1. It was fun, though.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace OverOiled01
{
/// <summary>
/// WAY overdoing Euler Project Problem 1.
///
/// It was fun, though.
/// </summary>
class Program
{
/// <summary>
/// The highest number to consider in finding our sum.
/// </summary>
private const long Max = 999;
/// <summary>
/// The first number we need to find the multiples of.
/// </summary>
private const int Factor1 = 3;
/// <summary>
/// The second number we need to find multiples of.
/// </summary>
private const int Factor2 = 5;
/// <summary>
/// The number that is the product of <see cref="Factor1"/> amd <see cref="Factor2"/>
/// </summary>
private const int Factor3 = Factor1 * Factor2;
/// <summary>
/// A formatting string that will create a dynamic formatting string in <see cref="MakeOutput"/>
/// </summary>
private const string PreFormat = "{{3,{0}}}: {{0:N0}}\t{{1,8:N0}} ticks\t{{2,15}} ns";
/// <summary>
/// A measuring value that shows closely the accuracy of a <see cref="Stopwatch.Frequency"/> in terms of nanoseconds.
/// </summary>
private static readonly double Nanos = (1000 * 1000 * 1000) / (double)Stopwatch.Frequency;
static void Main(string[] args)
{
WriteOutput
(
new List<Tracker> {ProcessElegance(), ProcessFunction(), ProcessLinq(), ProcessBruteForce()}
.OrderBy(tr => tr.Duration.Ticks)
.ToList()
);
Console.ReadLine();
}
#region Output methods
/// <summary>
/// Presents the results of all the time measuring methods.
/// </summary>
private static void WriteOutput(IEnumerable<Tracker> ltr)
{
var trackers = ltr as Tracker[] ?? ltr.ToArray();
int maxLen = trackers.Select(tracker => tracker.Name.Length).Concat(new[] {0}).Max();
foreach (Tracker tracker in trackers)
{
Console.WriteLine(MakeOutput(maxLen, tracker.Name, tracker.Result, tracker.Duration));
}
Console.WriteLine();
Console.WriteLine("Frequency: {0:n0} ticks per second.", Stopwatch.Frequency);
Console.WriteLine("Frequency: ~{0:n3} ns per tick.", Nanos);
}
/// <summary>
/// Creates the output line used to present the measurements of a specific tracking mechanism.
/// </summary>
private static string MakeOutput(int maxLen, string name, long total, TimeSpan ts)
{
string format = string.Format(PreFormat, maxLen);
return string.Format
(
format,
total, ts.Ticks, (ts.Ticks * Nanos).ToString("N3"), name
);
}
#endregion
#region Various calculation methods
/// <summary>
/// The quickest way so far that I know of to solve this.
///
/// Find the multiples of 3, find the multiples of 5, find the multiples of 15.
/// Use n*(n+1) to get the triangle number.
/// Add 3s and 5s. Subtract 15s since they've already been counted twice.
/// </summary>
private static Tracker ProcessElegance()
{
Stopwatch sw = new Stopwatch();
sw.Start();
const long nFactor1 = (((Max / Factor1) * (Max / Factor1) + (Max / Factor1)) / 2) * Factor1;
const long nFactor2 = (((Max / Factor2) * (Max / Factor2) + (Max / Factor2)) / 2) * Factor2;
const long nFactor3 = (((Max / Factor3) * (Max / Factor3) + (Max / Factor3)) / 2) * Factor3;
const long total = nFactor1 + nFactor2 - nFactor3;
sw.Stop();
return new Tracker(sw.Elapsed, total, "Elegance");
}
/// <summary>
/// Abstract one of the aspects of <see cref="ProcessElegance()"/>
/// via a function that returns the same results.
/// </summary>
private static Tracker ProcessFunction()
{
Stopwatch sw = new Stopwatch();
sw.Start();
long res = GetSum(Max, Factor1) + GetSum(Max, Factor2) - GetSum(Max, Factor3);
sw.Stop();
return new Tracker(sw.Elapsed, res, "Call Function");
}
/// <summary>
/// Takes the sum of all numbers up to max that are evenly divisable by mod.
/// </summary>
/// <param name="max">Maximum number to consider. (Inclusive)</param>
/// <param name="mod">Number to find multiples of in sequence.</param>
private static long GetSum(long max, long mod)
{
return ((((max / mod) * (max / mod)) + (max / mod)) / 2) * mod;
}
/// <summary>
/// The LINQ answer to the problem. It's a little easier to have LINQ wander off the deep end
/// with larger values of <see cref="Max"/>, so this was thrown into a try/catch block
/// </summary>
private static Tracker ProcessLinq()
{
Stopwatch sw = new Stopwatch();
long e2 = 0;
try
{
sw.Start();
e2 = Enumerable.Range(1, (int)Max).Sum(i => (i % Factor1 == 0 || i % Factor2 == 0) ? i : 0);
}
catch (OverflowException)
{
Console.WriteLine("Overflow Exception");
}
finally
{
sw.Stop();
}
return new Tracker(sw.Elapsed, e2, "LINQ");
}
/// <summary>
/// The brute force method counting from 1 to Max and adding it all up.
/// </summary>
private static Tracker ProcessBruteForce()
{
Stopwatch sw = new Stopwatch();
long sum = 0;
sw.Start();
for (int i = 0; i <= Max; i++)
{
if (i % Factor1 == 0 || i % Factor2 == 0)
{
sum += i;
}
}
sw.Stop();
return new Tracker(sw.Elapsed, sum, "Brute Force");
}
#endregion
}
}
using System;
namespace OverOiled01
{
/// <summary>
/// Stores results of a specific calculation, the provided
/// name of the calculation, and the resulting time.
/// </summary>
public struct Tracker
{
public Tracker(TimeSpan duration, long result, string name)
: this()
{
Name = name;
Result = result;
Duration = duration;
}
/// <summary>
/// Results of <see cref="System.Diagnostics.Stopwatch.Elapsed"/>
/// value after performing calculations.
/// </summary>
public TimeSpan Duration { get; private set; }
/// <summary>
/// Actual calculation result.
/// </summary>
public long Result{ get; private set; }
/// <summary>
/// Name of calculation method.
/// </summary>
public string Name { get; private set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment