Browse files

Problems 79-99

  • Loading branch information...
1 parent c9315f3 commit c8aa21f77399222c26b5eb85a3dc35438e09ca94 @ckknight committed Jun 24, 2010
Showing with 4,701 additions and 18 deletions.
  1. +3 −0 .gitignore
  2. BIN Ckknight.ProjectEuler.suo
  3. +742 −0 Ckknight.ProjectEuler/BigDecimal.cs
  4. +16 −1 Ckknight.ProjectEuler/BigFraction.cs
  5. +26 −0 Ckknight.ProjectEuler/Ckknight.ProjectEuler.csproj
  6. +43 −0 Ckknight.ProjectEuler/CollectionUtilities.cs
  7. +11 −4 Ckknight.ProjectEuler/Collections/BooleanArray.cs
  8. +17 −0 Ckknight.ProjectEuler/Collections/BooleanMatrix.cs
  9. +277 −0 Ckknight.ProjectEuler/Collections/EnumerableExtensions.cs
  10. +28 −0 Ckknight.ProjectEuler/Collections/FactorGenerator.cs
  11. +459 −0 Ckknight.ProjectEuler/Collections/Int32PointSet.cs
  12. +22 −7 Ckknight.ProjectEuler/Collections/Int32Set.cs
  13. +101 −0 Ckknight.ProjectEuler/Collections/MemorableEnumerable.cs
  14. +138 −0 Ckknight.ProjectEuler/Collections/Point.cs
  15. +4 −4 Ckknight.ProjectEuler/Collections/PrimeGenerator.cs
  16. +16 −1 Ckknight.ProjectEuler/Fraction.cs
  17. +126 −0 Ckknight.ProjectEuler/FuncExtensions.cs
  18. +128 −0 Ckknight.ProjectEuler/MathUtilities.cs
  19. +74 −0 Ckknight.ProjectEuler/Problems/Problem079.cs
  20. +57 −0 Ckknight.ProjectEuler/Problems/Problem080.cs
  21. +92 −0 Ckknight.ProjectEuler/Problems/Problem081.cs
  22. +107 −0 Ckknight.ProjectEuler/Problems/Problem082.cs
  23. +127 −0 Ckknight.ProjectEuler/Problems/Problem083.cs
  24. +354 −0 Ckknight.ProjectEuler/Problems/Problem084.cs
  25. +74 −0 Ckknight.ProjectEuler/Problems/Problem085.cs
  26. +55 −0 Ckknight.ProjectEuler/Problems/Problem086.cs
  27. +38 −0 Ckknight.ProjectEuler/Problems/Problem087.cs
  28. +77 −0 Ckknight.ProjectEuler/Problems/Problem088.cs
  29. +135 −0 Ckknight.ProjectEuler/Problems/Problem089.cs
  30. +73 −0 Ckknight.ProjectEuler/Problems/Problem090.cs
  31. +62 −0 Ckknight.ProjectEuler/Problems/Problem091.cs
  32. +65 −0 Ckknight.ProjectEuler/Problems/Problem092.cs
  33. +94 −0 Ckknight.ProjectEuler/Problems/Problem093.cs
  34. +44 −0 Ckknight.ProjectEuler/Problems/Problem094.cs
  35. +63 −0 Ckknight.ProjectEuler/Problems/Problem095.cs
  36. +428 −0 Ckknight.ProjectEuler/Problems/Problem096.cs
  37. +25 −0 Ckknight.ProjectEuler/Problems/Problem097.cs
  38. +179 −0 Ckknight.ProjectEuler/Problems/Problem098.cs
  39. +61 −0 Ckknight.ProjectEuler/Problems/Problem099.cs
  40. +1 −1 Ckknight.ProjectEuler/Program.cs
  41. +214 −0 Ckknight.ProjectEulerTest/BigDecimalTest.cs
  42. +4 −0 Ckknight.ProjectEulerTest/Ckknight.ProjectEulerTest.csproj
  43. +39 −0 Ckknight.ProjectEulerTest/FractionTest.cs
  44. +2 −0 Ckknight.ProjectEulerTest/Test References/Ckknight.ProjectEuler.accessor
View
3 .gitignore
@@ -1 +1,4 @@
TestResults/
+_ReSharper.Ckknight.ProjectEuler
+*.user
+
View
BIN Ckknight.ProjectEuler.suo
Binary file not shown.
View
742 Ckknight.ProjectEuler/BigDecimal.cs
@@ -0,0 +1,742 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Numerics;
+using System.Runtime.Serialization;
+
+namespace Ckknight.ProjectEuler
+{
+ [Serializable]
+ public struct BigDecimal : IComparable<BigDecimal>, IEquatable<BigDecimal>, ISerializable
+ {
+ public BigDecimal(BigInteger coefficient)
+ : this(coefficient, BigInteger.Zero) { }
+
+ public BigDecimal(BigInteger coefficient, BigInteger exponent)
+ {
+ Reduce(ref coefficient, ref exponent);
+
+ _coefficient = coefficient;
+ _exponent = exponent;
+ }
+
+ public BigDecimal(int value)
+ : this((BigInteger)value) { }
+
+ public BigDecimal(long value)
+ : this((BigInteger)value) { }
+
+ public BigDecimal(decimal value)
+ {
+ if (value == 0m)
+ {
+ _coefficient = BigInteger.Zero;
+ _exponent = BigInteger.Zero;
+ }
+ else
+ {
+ bool negative = value < 0m;
+ if (negative)
+ {
+ value = -value;
+ }
+ BigInteger bigValue = (BigInteger)value;
+ value %= 1m;
+ int shifts = 0;
+ while (value > 0m)
+ {
+ value *= 10m;
+ bigValue *= BigTen;
+ bigValue += (int)value;
+ value %= 1m;
+ shifts--;
+ }
+ if (negative)
+ {
+ bigValue = -bigValue;
+ }
+
+ BigInteger exponent = shifts;
+
+ Reduce(ref bigValue, ref exponent);
+ _coefficient = bigValue;
+ _exponent = exponent;
+ }
+ }
+
+ private static readonly BigInteger BigTen = new BigInteger(10);
+ private static void Reduce(ref BigInteger coefficient, ref BigInteger exponent)
+ {
+ if (coefficient.IsZero)
+ {
+ exponent = BigInteger.Zero;
+ }
+ else
+ {
+ while (true)
+ {
+ BigInteger remainder;
+ BigInteger result = BigInteger.DivRem(coefficient, BigTen, out remainder);
+ if (!remainder.IsZero)
+ {
+ break;
+ }
+ coefficient = result;
+ exponent++;
+ }
+ }
+ }
+
+ private readonly BigInteger _coefficient;
+ private readonly BigInteger _exponent;
+ public BigInteger Coefficient
+ {
+ get
+ {
+ return _coefficient;
+ }
+ }
+ public BigInteger Exponent
+ {
+ get
+ {
+ return _exponent;
+ }
+ }
+
+ public static readonly BigDecimal Zero = new BigDecimal();
+ public static readonly BigDecimal One = new BigDecimal(1);
+ public static readonly BigDecimal MinusOne = new BigDecimal(-1);
+
+ public bool IsZero
+ {
+ get
+ {
+ return _coefficient.IsZero;
+ }
+ }
+
+ public bool IsOne
+ {
+ get
+ {
+ return _coefficient.IsOne && _exponent.IsZero;
+ }
+ }
+
+ public bool IsInteger
+ {
+ get
+ {
+ return _exponent.Sign >= 0;
+ }
+ }
+
+ public int Sign
+ {
+ get
+ {
+ return _coefficient.Sign;
+ }
+ }
+
+ private static readonly int _maximumExponentToStringSize = 1000;
+ public override string ToString()
+ {
+ string coefficientString = _coefficient.ToString();
+ if (_exponent.IsZero)
+ {
+ return coefficientString;
+ }
+ else
+ {
+ StringBuilder sb = new StringBuilder(coefficientString);
+ if (_exponent > 0)
+ {
+ if (_exponent > _maximumExponentToStringSize)
+ {
+ sb.Append('e');
+ sb.Append(_exponent);
+ }
+ else
+ {
+ int exponent = (int)_exponent;
+ for (int i = 0; i < exponent; i++)
+ {
+ sb.Append('0');
+ }
+ }
+ }
+ else
+ {
+ if (_exponent < -_maximumExponentToStringSize)
+ {
+ sb.Append('e');
+ sb.Append(_exponent);
+ }
+ else
+ {
+ int exponent = (int)-_exponent;
+ if (sb.Length <= exponent)
+ {
+ int max = exponent - sb.Length + 2;
+ sb.Insert(0, "0.");
+ for (int i = 2; i < max; i++)
+ {
+ sb.Insert(i, '0');
+ }
+ }
+ else
+ {
+ sb.Insert(sb.Length - exponent, '.');
+ }
+ }
+ }
+ return sb.ToString();
+ }
+ }
+
+ #region IEquatable<BigDecimal> Members
+
+ public bool Equals(BigDecimal other)
+ {
+ return this._coefficient == other._coefficient && this._exponent == other._exponent;
+ }
+
+ #endregion
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ else if (obj is BigDecimal)
+ {
+ return Equals((BigDecimal)obj);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return _coefficient.GetHashCode() ^ _exponent.GetHashCode();
+ }
+
+ public static double Log10(BigDecimal number)
+ {
+ return BigInteger.Log10(number._coefficient) + (double)number._exponent;
+ }
+
+ public static BigInteger Log10Floor(BigDecimal number)
+ {
+ if (number.IsZero)
+ {
+ throw new DivideByZeroException();
+ }
+ return (BigInteger)Math.Floor(BigInteger.Log10(number._coefficient)) + number._exponent;
+ }
+
+ public static BigInteger Log10Ceiling(BigDecimal number)
+ {
+ if (number.IsZero)
+ {
+ throw new DivideByZeroException();
+ }
+ return (BigInteger)Math.Ceiling(BigInteger.Log10(number._coefficient)) + number._exponent;
+ }
+
+ private static readonly double _log10 = Math.Log(10);
+ public static double Log(BigDecimal number, double baseValue)
+ {
+ if (baseValue == 10.0)
+ {
+ return Log10(number);
+ }
+ else
+ {
+ return Log10(number) * baseValue / _log10;
+ }
+ }
+
+ public static double Log(BigDecimal number)
+ {
+ return Log(number, Math.E);
+ }
+
+ private static readonly BigInteger _longMaxValueAsBigInteger = long.MaxValue;
+ public static BigDecimal Pow(BigDecimal number, BigInteger exponent)
+ {
+ if (number.IsZero)
+ {
+ return BigDecimal.Zero;
+ }
+ else if (exponent.IsZero || number.IsOne)
+ {
+ return BigDecimal.One;
+ }
+ else if (exponent.IsOne)
+ {
+ return number;
+ }
+ else if (exponent.Sign < 0)
+ {
+ throw new ArgumentOutOfRangeException("exponent", exponent, "Must be at least 0");
+ }
+ else if (exponent <= _longMaxValueAsBigInteger)
+ {
+ return Pow(number, (long)exponent);
+ }
+ else if (number == BigDecimal.MinusOne)
+ {
+ if (exponent.IsEven)
+ {
+ return BigDecimal.One;
+ }
+ else
+ {
+ return BigDecimal.MinusOne;
+ }
+ }
+
+ BigDecimal result = BigDecimal.One;
+ while (!exponent.IsZero)
+ {
+ if (!exponent.IsEven)
+ {
+ result *= number;
+ }
+ exponent >>= 1;
+ number *= number;
+ }
+
+ return result;
+ }
+
+ public static BigDecimal Pow(BigDecimal number, long exponent)
+ {
+ if (number.IsZero)
+ {
+ return BigDecimal.Zero;
+ }
+ else if (exponent == 0L || number.IsOne)
+ {
+ return BigDecimal.One;
+ }
+ else if (exponent == 1L)
+ {
+ return number;
+ }
+ else if (exponent == 2L)
+ {
+ return number * number;
+ }
+ else if (exponent < 0L)
+ {
+ throw new ArgumentOutOfRangeException("exponent", exponent, "Must be at least 0");
+ }
+ else if (number == BigDecimal.MinusOne)
+ {
+ if ((exponent & 1L) == 0)
+ {
+ return BigDecimal.One;
+ }
+ else
+ {
+ return BigDecimal.MinusOne;
+ }
+ }
+
+ BigDecimal result = BigDecimal.One;
+ while (exponent != 0L)
+ {
+ if ((exponent & 1L) != 0L)
+ {
+ result *= number;
+ }
+ exponent >>= 1;
+ number *= number;
+ }
+
+ return result;
+ }
+
+ #region IComparable<BigDecimal> Members
+
+ public int CompareTo(BigDecimal other)
+ {
+ int thisSign = this._coefficient.Sign;
+ int otherSign = other._coefficient.Sign;
+ if (thisSign != otherSign)
+ {
+ if (thisSign < otherSign)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else if (thisSign == 0)
+ {
+ return 0;
+ }
+
+ if (this._exponent.Equals(other._exponent))
+ {
+ return _coefficient.CompareTo(other._coefficient);
+ }
+
+ BigInteger alpha = this._coefficient;
+ BigInteger bravo = other._coefficient;
+ int multiplier = 1;
+ if (thisSign < 0)
+ {
+ multiplier = -1;
+ alpha = -alpha;
+ bravo = -bravo;
+ }
+
+ BigInteger alphaLog10 = (BigInteger)Math.Floor(BigInteger.Log10(alpha)) + _exponent;
+ BigInteger bravoLog10 = (BigInteger)Math.Floor(BigInteger.Log10(bravo)) + other._exponent;
+
+ if (!alphaLog10.Equals(bravoLog10))
+ {
+ if (alphaLog10.CompareTo(bravoLog10) > 0)
+ {
+ return multiplier;
+ }
+ else
+ {
+ return -multiplier;
+ }
+ }
+
+ BigInteger exponentDifference = _exponent - other._exponent;
+ if (exponentDifference.Sign > 0)
+ {
+ bravo /= MathUtilities.Pow(BigTen, exponentDifference);
+ }
+ else
+ {
+ alpha /= MathUtilities.Pow(BigTen, -exponentDifference);
+ }
+
+ int cmp = alpha.CompareTo(bravo);
+ switch (alpha.CompareTo(bravo))
+ {
+ case 1:
+ return multiplier;
+ case -1:
+ return -multiplier;
+ default:
+ return -multiplier * exponentDifference.Sign;
+ }
+ }
+
+ #endregion
+
+ public static bool operator ==(BigDecimal alpha, BigDecimal bravo)
+ {
+ return alpha.Equals(bravo);
+ }
+
+ public static bool operator !=(BigDecimal alpha, BigDecimal bravo)
+ {
+ return !alpha.Equals(bravo);
+ }
+
+ public static bool operator >(BigDecimal alpha, BigDecimal bravo)
+ {
+ return alpha.CompareTo(bravo) > 0;
+ }
+
+ public static bool operator <(BigDecimal alpha, BigDecimal bravo)
+ {
+ return alpha.CompareTo(bravo) < 0;
+ }
+
+ public static bool operator >=(BigDecimal alpha, BigDecimal bravo)
+ {
+ return alpha.CompareTo(bravo) >= 0;
+ }
+
+ public static bool operator <=(BigDecimal alpha, BigDecimal bravo)
+ {
+ return alpha.CompareTo(bravo) <= 0;
+ }
+
+ public static implicit operator BigDecimal(int value)
+ {
+ return new BigDecimal(value);
+ }
+
+ public static implicit operator BigDecimal(long value)
+ {
+ return new BigDecimal(value);
+ }
+
+ public static implicit operator BigDecimal(BigInteger value)
+ {
+ return new BigDecimal(value);
+ }
+
+ public static implicit operator BigDecimal(decimal value)
+ {
+ return new BigDecimal(value);
+ }
+
+ public static explicit operator BigDecimal(double value)
+ {
+ return (BigDecimal)((decimal)value);
+ }
+
+ public static explicit operator double(BigDecimal value)
+ {
+ return Math.Pow(10.0, BigDecimal.Log10(value));
+ }
+
+ public static explicit operator BigInteger(BigDecimal value)
+ {
+ BigDecimal remainder;
+ return DivRem(value, One, out remainder);
+ }
+
+ public static BigDecimal operator +(BigDecimal value)
+ {
+ return value;
+ }
+
+ public static BigDecimal operator -(BigDecimal value)
+ {
+ return new BigDecimal(-value._coefficient, value._exponent);
+ }
+
+ public static BigDecimal operator +(BigDecimal alpha, BigDecimal bravo)
+ {
+ BigInteger exponentDifference = alpha._exponent - bravo._exponent;
+
+ BigInteger alphaCoefficient;
+ BigInteger bravoCoefficient;
+ BigInteger resultantExponent;
+ switch (exponentDifference.Sign)
+ {
+ case 1:
+ alphaCoefficient = alpha._coefficient * MathUtilities.Pow(BigTen, exponentDifference);
+ bravoCoefficient = bravo._coefficient;
+ resultantExponent = bravo._exponent;
+ break;
+ case -1:
+ alphaCoefficient = alpha._coefficient;
+ bravoCoefficient = bravo._coefficient * MathUtilities.Pow(BigTen, -exponentDifference);
+ resultantExponent = alpha._exponent;
+ break;
+ default:
+ alphaCoefficient = alpha._coefficient;
+ bravoCoefficient = bravo._coefficient;
+ resultantExponent = alpha._exponent;
+ break;
+ }
+
+ return new BigDecimal(alphaCoefficient + bravoCoefficient, resultantExponent);
+ }
+
+ public static BigDecimal operator -(BigDecimal alpha, BigDecimal bravo)
+ {
+ return alpha + (-bravo);
+ }
+
+ public static BigDecimal operator *(BigDecimal alpha, BigDecimal bravo)
+ {
+ if (alpha.IsZero || bravo.IsZero)
+ {
+ return BigDecimal.Zero;
+ }
+ else if (alpha.IsOne)
+ {
+ return bravo;
+ }
+ else if (bravo.IsOne)
+ {
+ return alpha;
+ }
+ else
+ {
+ return new BigDecimal(alpha._coefficient * bravo._coefficient, alpha._exponent + bravo._exponent);
+ }
+ }
+
+ public static BigInteger DivRem(BigDecimal dividend, BigDecimal divisor, out BigDecimal remainder)
+ {
+ if (divisor.IsZero)
+ {
+ throw new DivideByZeroException();
+ }
+ else if (dividend.IsZero)
+ {
+ remainder = BigDecimal.Zero;
+ return BigInteger.Zero;
+ }
+ else if (divisor.Equals(dividend))
+ {
+ remainder = BigDecimal.Zero;
+ return BigInteger.One;
+ }
+ else
+ {
+ BigInteger dividendCoefficient = dividend._coefficient;
+ BigInteger divisorCoefficient = divisor._coefficient;
+ bool negative = false;
+ if (dividendCoefficient.Sign < 0)
+ {
+ dividendCoefficient = -dividendCoefficient;
+ negative = !negative;
+ }
+ if (divisorCoefficient.Sign < 0)
+ {
+ divisorCoefficient = -divisorCoefficient;
+ negative = !negative;
+ }
+ BigInteger resultantExponent;
+ BigInteger exponentDifference = dividend._exponent - divisor._exponent;
+ switch (exponentDifference.Sign)
+ {
+ case 1:
+ dividendCoefficient *= MathUtilities.Pow(BigTen, exponentDifference);
+ resultantExponent = divisor._exponent;
+ break;
+ case -1:
+ divisorCoefficient *= MathUtilities.Pow(BigTen, -exponentDifference);
+ resultantExponent = dividend._exponent;
+ break;
+ default:
+ resultantExponent = dividend._exponent;
+ break;
+ }
+
+ BigInteger mod;
+ BigInteger quotient = BigInteger.DivRem(dividendCoefficient, divisorCoefficient, out mod);
+ remainder = new BigDecimal(mod, resultantExponent);
+ if (negative)
+ {
+ quotient = -quotient;
+ }
+ return quotient;
+ }
+ }
+
+ private static readonly BigInteger _divisionLimit = 1500;
+ private const int _digitsPerModulo = 20;
+ private static readonly BigInteger _divisionTenMultiplier = MathUtilities.Pow(BigTen, _digitsPerModulo);
+ public static BigDecimal operator /(BigDecimal dividend, BigDecimal divisor)
+ {
+ if (divisor.IsZero)
+ {
+ throw new DivideByZeroException();
+ }
+ else if (divisor.IsOne)
+ {
+ return dividend;
+ }
+ else if (divisor.Equals(dividend))
+ {
+ return BigDecimal.One;
+ }
+ else if (divisor._coefficient == dividend._coefficient)
+ {
+ return new BigDecimal(BigInteger.One, dividend._exponent - divisor._exponent);
+ }
+ else if (divisor._coefficient.IsOne)
+ {
+ return new BigDecimal(dividend._coefficient, dividend._exponent - divisor._exponent);
+ }
+ else
+ {
+ BigInteger dividendCoefficient = dividend._coefficient;
+ BigInteger divisorCoefficient = divisor._coefficient;
+ bool negative = false;
+ if (dividendCoefficient.Sign < 0)
+ {
+ dividendCoefficient = -dividendCoefficient;
+ negative = !negative;
+ }
+ if (divisorCoefficient.Sign < 0)
+ {
+ divisorCoefficient = -divisorCoefficient;
+ negative = !negative;
+ }
+ BigInteger exponentDifference = dividend._exponent - divisor._exponent;
+ switch (exponentDifference.Sign)
+ {
+ case 1:
+ dividendCoefficient *= MathUtilities.Pow(BigTen, exponentDifference);
+ break;
+ case -1:
+ divisorCoefficient *= MathUtilities.Pow(BigTen, -exponentDifference);
+ break;
+ }
+
+ BigInteger mod;
+ BigInteger quotient = BigInteger.DivRem(dividendCoefficient, divisorCoefficient, out mod);
+
+ BigInteger exponent = BigInteger.Zero;
+
+ BigInteger currentResult = quotient;
+ while (!mod.IsZero && exponent < _divisionLimit)
+ {
+ BigInteger addition = BigInteger.DivRem(mod * _divisionTenMultiplier, divisor._coefficient, out mod);
+ exponent += _digitsPerModulo;
+ currentResult = currentResult * _divisionTenMultiplier + addition;
+ }
+ if (exponent >= _divisionLimit)
+ {
+ BigInteger addition = BigInteger.DivRem(mod * BigTen, divisor._coefficient, out mod);
+ if (addition >= 5)
+ {
+ currentResult++;
+ }
+ }
+
+ if (negative)
+ {
+ currentResult = -currentResult;
+ }
+
+ return new BigDecimal(currentResult, -exponent);
+ }
+ }
+
+ public static BigDecimal operator %(BigDecimal dividend, BigDecimal divisor)
+ {
+ BigDecimal remainder;
+ DivRem(dividend, divisor, out remainder);
+ return remainder;
+ }
+
+ #region ISerializable Members
+
+ private BigDecimal(SerializationInfo info, StreamingContext context)
+ {
+ BigInteger coefficient = (BigInteger)info.GetValue("c", typeof(BigInteger));
+ BigInteger exponent = (BigInteger)info.GetValue("e", typeof(BigInteger));
+
+ Reduce(ref coefficient, ref exponent);
+
+ _coefficient = coefficient;
+ _exponent = exponent;
+ }
+
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("c", _coefficient, typeof(BigInteger));
+ info.AddValue("e", _exponent, typeof(BigInteger));
+ }
+
+ #endregion
+ }
+}
View
17 Ckknight.ProjectEuler/BigFraction.cs
@@ -3,10 +3,12 @@
using System.Linq;
using System.Text;
using System.Numerics;
+using System.Runtime.Serialization;
namespace Ckknight.ProjectEuler
{
- public struct BigFraction : IComparable<BigFraction>, IEquatable<BigFraction>
+ [Serializable]
+ public struct BigFraction : IComparable<BigFraction>, IEquatable<BigFraction>, ISerializable
{
public BigFraction(BigInteger numerator)
: this(numerator, 1) { }
@@ -620,5 +622,18 @@ public static BigFraction DivRem(BigFraction dividend, BigFraction divisor, out
return new BigFraction((BigInteger)number, BigInteger.Pow(10, power));
}
+
+ #region ISerializable Members
+
+ private BigFraction(SerializationInfo info, StreamingContext context)
+ : this((BigInteger)info.GetValue("n", typeof(BigInteger)), (BigInteger)info.GetValue("d", typeof(BigInteger))) { }
+
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("n", _numerator, typeof(BigInteger));
+ info.AddValue("d", _denominator, typeof(BigInteger));
+ }
+
+ #endregion
}
}
View
26 Ckknight.ProjectEuler/Ckknight.ProjectEuler.csproj
@@ -44,12 +44,17 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="BigDecimal.cs" />
<Compile Include="BigFraction.cs" />
<Compile Include="BigContinuedFraction.cs" />
<Compile Include="Collections\CombinationGenerator.cs" />
<Compile Include="Collections\BooleanArray.cs" />
<Compile Include="Collections\BooleanMatrix.cs" />
<Compile Include="Collections\DictionaryExtensions.cs" />
+ <Compile Include="Collections\Int32PointSet.cs" />
+ <Compile Include="Collections\MemorableEnumerable.cs" />
+ <Compile Include="Collections\Point.cs" />
+ <Compile Include="FuncExtensions.cs" />
<Compile Include="Collections\PrimeGenerator.cs" />
<Compile Include="Collections\DefaultDictionary.cs" />
<Compile Include="ContinuedFraction.cs" />
@@ -147,6 +152,27 @@
<Compile Include="Problems\Problem076.cs" />
<Compile Include="Problems\Problem077.cs" />
<Compile Include="Problems\Problem078.cs" />
+ <Compile Include="Problems\Problem079.cs" />
+ <Compile Include="Problems\Problem080.cs" />
+ <Compile Include="Problems\Problem081.cs" />
+ <Compile Include="Problems\Problem082.cs" />
+ <Compile Include="Problems\Problem083.cs" />
+ <Compile Include="Problems\Problem084.cs" />
+ <Compile Include="Problems\Problem085.cs" />
+ <Compile Include="Problems\Problem086.cs" />
+ <Compile Include="Problems\Problem087.cs" />
+ <Compile Include="Problems\Problem088.cs" />
+ <Compile Include="Problems\Problem089.cs" />
+ <Compile Include="Problems\Problem090.cs" />
+ <Compile Include="Problems\Problem091.cs" />
+ <Compile Include="Problems\Problem092.cs" />
+ <Compile Include="Problems\Problem093.cs" />
+ <Compile Include="Problems\Problem094.cs" />
+ <Compile Include="Problems\Problem095.cs" />
+ <Compile Include="Problems\Problem096.cs" />
+ <Compile Include="Problems\Problem097.cs" />
+ <Compile Include="Problems\Problem098.cs" />
+ <Compile Include="Problems\Problem099.cs" />
<Compile Include="Problems\ProblemAttribute.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
View
43 Ckknight.ProjectEuler/CollectionUtilities.cs
@@ -42,6 +42,49 @@ public static HashSet<T> NewHashSet<T>(params T[] args)
return new HashSet<T>(args);
}
+ public static IEqualityComparer<T> NewEqualityComparer<T>(Func<T, T, bool> equalityChecker, Func<T, int> hashCodeCreator)
+ {
+ if (equalityChecker == null)
+ {
+ throw new ArgumentNullException("equalityChecker");
+ }
+ else if (hashCodeCreator == null)
+ {
+ throw new ArgumentNullException("hashCodeCreator");
+ }
+ return new EqualityComparerHelper<T>(equalityChecker, hashCodeCreator);
+ }
+
+ private class EqualityComparerHelper<T> : IEqualityComparer<T>
+ {
+ public EqualityComparerHelper(Func<T, T, bool> equalityChecker, Func<T, int> hashCodeCreator)
+ {
+ _equalityChecker = equalityChecker;
+ _hashCodeCreator = hashCodeCreator;
+ }
+ private readonly Func<T, T, bool> _equalityChecker;
+ private readonly Func<T, int> _hashCodeCreator;
+
+ #region IEqualityComparer<T> Members
+
+ public bool Equals(T x, T y)
+ {
+ return _equalityChecker(x, y);
+ }
+
+ public int GetHashCode(T obj)
+ {
+ return _hashCodeCreator(obj);
+ }
+
+ #endregion
+ }
+
+ public static IEqualityComparer<T> NewEqualityComparer<T>(Func<T, T, bool> equalityChecker, Func<T, int> hashCodeCreator, Func<T> typeCreator)
+ {
+ return NewEqualityComparer<T>(equalityChecker, hashCodeCreator);
+ }
+
public static IEqualityComparer<IEnumerable<T>> GetSequenceEqualityComparer<T>()
{
return SequenceEqualityComparerHelper<T>.Instance;
View
15 Ckknight.ProjectEuler/Collections/BooleanArray.cs
@@ -22,10 +22,7 @@ public BooleanArray(int length, bool defaultValue)
_data = new byte[dataLength];
if (defaultValue)
{
- for (int i = 0; i < dataLength; i++)
- {
- _data[i] = 255;
- }
+ SetAll(true);
}
}
@@ -88,6 +85,16 @@ public BooleanArray(IEnumerable<bool> source)
}
}
+ public void SetAll(bool value)
+ {
+ int length = _data.Length;
+ byte byteValue = value ? byte.MaxValue : (byte)0;
+ for (int i = 0; i < length; i++)
+ {
+ _data[i] = byteValue;
+ }
+ }
+
private static int GetDataLength(int length)
{
int dataLength = length >> 3;
View
17 Ckknight.ProjectEuler/Collections/BooleanMatrix.cs
@@ -9,6 +9,9 @@ namespace Ckknight.ProjectEuler.Collections
public class BooleanMatrix
{
public BooleanMatrix(int width, int height)
+ : this(width, height, false) { }
+
+ public BooleanMatrix(int width, int height, bool defaultValue)
{
if (width < 0)
{
@@ -27,6 +30,10 @@ public BooleanMatrix(int width, int height)
_height = height;
_data = new byte[GetDataLength(width, height)];
+ if (defaultValue)
+ {
+ SetAll(true);
+ }
}
public BooleanMatrix(BooleanMatrix source)
@@ -92,6 +99,16 @@ public BooleanMatrix(bool[,] source)
_data[majorOffset] = current;
}
+ public void SetAll(bool value)
+ {
+ int length = _data.Length;
+ byte byteValue = value ? byte.MaxValue : (byte)0;
+ for (int i = 0; i < length; i++)
+ {
+ _data[i] = byteValue;
+ }
+ }
+
private static int GetDataLength(int width, int height)
{
int length = width * height;
View
277 Ckknight.ProjectEuler/Collections/EnumerableExtensions.cs
@@ -77,6 +77,11 @@ public static string StringJoin<T>(this IEnumerable<T> sequence, string separato
return string.Join(separator, sequence);
}
+ public static string StringJoin<T, TResult>(this IEnumerable<T> sequence, string separator, Func<T, TResult> selector)
+ {
+ return string.Join(separator, sequence.Select(selector));
+ }
+
/// <summary>
/// Return an enumerable that skips the last <paramref name="count"/> items of the given <paramref name="sequence"/>.
/// </summary>
@@ -107,6 +112,36 @@ public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> sequence, int count
}
}
+ public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> sequence, int count)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+ else if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException("count", count, "Must be at least 0");
+ }
+
+ if (count == 0)
+ {
+ return Enumerable.Empty<T>();
+ }
+
+ Queue<T> queue = new Queue<T>(count);
+
+ foreach (T item in sequence)
+ {
+ if (queue.Count == count)
+ {
+ queue.Dequeue();
+ }
+ queue.Enqueue(item);
+ }
+
+ return queue;
+ }
+
/// <summary>
/// Create a new HashSet from the provided <paramref name="sequence"/>.
/// </summary>
@@ -755,6 +790,35 @@ public static IEnumerable<T> TakeWhileDistinct<T>(this IEnumerable<T> sequence,
}
}
+ public static bool IsDistinct<T>(this IEnumerable<T> sequence)
+ {
+ return IsDistinct(sequence, null);
+ }
+
+ public static bool IsDistinct<T>(this IEnumerable<T> sequence, IEqualityComparer<T> comparer)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+
+ if (comparer == null)
+ {
+ comparer = EqualityComparer<T>.Default;
+ }
+
+ HashSet<T> set = new HashSet<T>(comparer);
+ foreach (T item in sequence)
+ {
+ if (set.Contains(item))
+ {
+ return false;
+ }
+ set.Add(item);
+ }
+ return true;
+ }
+
public static TElement WithMax<TElement, TValue>(this IEnumerable<TElement> sequence, Func<TElement, TValue> selector)
{
if (sequence == null)
@@ -880,6 +944,10 @@ public static IEnumerable<T> AssertEach<T>(this IEnumerable<T> sequence, Func<T,
{
throw new ArgumentNullException("sequence");
}
+ else if (tester == null)
+ {
+ throw new ArgumentNullException("tester");
+ }
List<T> list = new List<T>();
@@ -894,5 +962,214 @@ public static IEnumerable<T> AssertEach<T>(this IEnumerable<T> sequence, Func<T,
return list;
}
+
+ public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+ else if (action == null)
+ {
+ throw new ArgumentNullException("action");
+ }
+
+ foreach (T item in sequence)
+ {
+ action(item);
+ }
+ }
+
+ public static void ForEach<T>(this IEnumerable<T> sequence, Action<T, int> action)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+ else if (action == null)
+ {
+ throw new ArgumentNullException("action");
+ }
+
+
+ int i = 0;
+ foreach (T item in sequence)
+ {
+ action(item, i++);
+ }
+ }
+
+ /// <summary>
+ /// Return a shuffled sequence of the sequence passed in.
+ /// </summary>
+ /// <typeparam name="T">Type of the sequence</typeparam>
+ /// <param name="sequence">The sequence to check</param>
+ /// <returns>A sequence with the same values in a random order.</returns>
+ public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> sequence)
+ {
+ return sequence.Shuffle(null);
+ }
+
+ [ThreadStatic]
+ private static readonly Random _random = MathUtilities.CreateRandom();
+ /// <summary>
+ /// Return a shuffled sequence of the sequence passed in.
+ /// </summary>
+ /// <typeparam name="T">Type of the sequence</typeparam>
+ /// <param name="sequence">The sequence to check</param>
+ /// <param name="random">The random object to get new indices from.</param>
+ /// <returns>A sequence with the same values in a random order.</returns>
+ public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> sequence, Random random)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+ if (random == null)
+ {
+ random = _random;
+ }
+ T[] array = sequence.ToArray();
+ int length = array.Length;
+ for (int i = length - 1; i > 0; i--)
+ {
+ int index = random.Next(i);
+ if (index != i)
+ {
+ T tmp = array[i];
+ array[i] = array[index];
+ array[index] = tmp;
+ }
+ }
+ return array;
+ }
+
+ public static T[,] ToMatrix<T>(this T[][] jaggedArray)
+ {
+ if (jaggedArray == null)
+ {
+ throw new ArgumentNullException("jaggedArray");
+ }
+
+ int height = jaggedArray.Length;
+ if (height == 0)
+ {
+ return new T[0, 0];
+ }
+
+ if (jaggedArray[0] == null)
+ {
+ throw new ArgumentException("First array is null", "jaggedArray");
+ }
+ int width = jaggedArray[0].Length;
+
+ T[,] result = new T[width, height];
+
+ for (int i = 0; i < height; i++)
+ {
+ T[] array = jaggedArray[i];
+ if (array == null)
+ {
+ throw new ArgumentException(string.Format("Array #{0} is null", i), "jaggedArray");
+ }
+
+ if (array.Length != width)
+ {
+ throw new ArgumentException(string.Format("Array #{0} has a width of {1}, expected {2}", i, array.Length, width), "jaggedArray");
+ }
+
+ for (int j = 0; j < width; j++)
+ {
+ result[j, i] = array[j];
+ }
+ }
+
+ return result;
+ }
+
+ public static Queue<T> ToQueue<T>(this IEnumerable<T> sequence)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+
+ return new Queue<T>(sequence);
+ }
+
+ public static Stack<T> ToStack<T>(this IEnumerable<T> sequence)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+
+ return new Stack<T>(sequence);
+ }
+
+ public static IEnumerable<Tuple<T1, T2>> CrossProduct<T1, T2>(this IEnumerable<T1> sequence, IEnumerable<T2> other)
+ {
+ return CrossProduct(sequence, other, (a, b) => new Tuple<T1, T2>(a, b));
+ }
+
+ public static IEnumerable<TResult> CrossProduct<T1, T2, TResult>(this IEnumerable<T1> sequence, IEnumerable<T2> other, Func<T1, T2, TResult> selector)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+ else if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+ else if (selector == null)
+ {
+ throw new ArgumentNullException("selector");
+ }
+
+ T2[] array = other as T2[] ?? other.ToArray();
+ if (other == sequence)
+ {
+ sequence = array as T1[];
+ }
+
+ return sequence
+ .SelectMany(a => array
+ .Select(b => selector(a, b)));
+ }
+
+ public static MemorableEnumerable<T> ToMemorableEnumerable<T>(this IEnumerable<T> sequence)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+
+ return new MemorableEnumerable<T>(sequence);
+ }
+
+ public static IEnumerable<T[]> Partition<T>(this IEnumerable<T> sequence, int amount)
+ {
+ if (amount < 1)
+ {
+ throw new ArgumentOutOfRangeException("amount", amount, "Must be at least 1");
+ }
+
+ List<T> list = new List<T>(amount);
+ foreach (T item in sequence)
+ {
+ if (list.Count == amount)
+ {
+ yield return list.ToArray();
+ list.Clear();
+ }
+
+ list.Add(item);
+ }
+ if (list.Count > 0)
+ {
+ yield return list.ToArray();
+ }
+ }
}
}
View
28 Ckknight.ProjectEuler/Collections/FactorGenerator.cs
@@ -38,6 +38,10 @@ public IEnumerator<long> GetEnumerator()
x.UnionWith(x.Select(v => v * primeFactor).ToArray());
return x;
});
+ if (!_includeNumber)
+ {
+ divisors.Remove(_number);
+ }
return divisors.GetEnumerator();
}
@@ -51,5 +55,29 @@ IEnumerator IEnumerable.GetEnumerator()
}
#endregion
+
+ public static long SumOfFactors(long number)
+ {
+ long value = number;
+ long sum = 1;
+ foreach (long prime in PrimeGenerator.Instance)
+ {
+ if (prime * prime > value)
+ {
+ break;
+ }
+ long lastSum = sum;
+ while (value % prime == 0)
+ {
+ value /= prime;
+ sum = sum*prime + lastSum;
+ }
+ }
+ if (value > 1)
+ {
+ sum *= (value + 1);
+ }
+ return sum - number;
+ }
}
}
View
459 Ckknight.ProjectEuler/Collections/Int32PointSet.cs
@@ -0,0 +1,459 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+
+namespace Ckknight.ProjectEuler.Collections
+{
+ public class Int32PointSet : ISet<Point<int>>, ICollection<Point<int>>
+ {
+ public Int32PointSet(int width, int height)
+ {
+ if (width < 0)
+ {
+ throw new ArgumentOutOfRangeException("width", width, "Must be at least 0");
+ }
+ else if (height < 0)
+ {
+ throw new ArgumentOutOfRangeException("height", height, "Must be at least 0");
+ }
+ _bucket = new BooleanMatrix(width, height);
+ }
+
+ public Int32PointSet(int width, int height, bool includeAllInitially)
+ : this(width, height)
+ {
+ if (includeAllInitially)
+ {
+ _bucket.SetAll(true);
+ }
+ }
+
+ public Int32PointSet(IEnumerable<Point<int>> sequence, int width, int height)
+ : this(width, height)
+ {
+ if (sequence == null)
+ {
+ throw new ArgumentNullException("sequence");
+ }
+
+ foreach (Point<int> item in sequence)
+ {
+ int x = item.X;
+ int y = item.Y;
+ if (x < 0 || x >= width)
+ {
+ throw new ArgumentException("Item's X must be no less than 0 and not greater or equal to the provided width", "sequence");
+ }
+ else if (x < 0 || x >= height)
+ {
+ throw new ArgumentException("Item's Y must be no less than 0 and not greater or equal to the provided width", "sequence");
+ }
+ _bucket[x, y] = true;
+ }
+ }
+
+ private readonly BooleanMatrix _bucket;
+
+ public int Width
+ {
+ get
+ {
+ return _bucket.Width;
+ }
+ }
+
+ public int Height
+ {
+ get
+ {
+ return _bucket.Height;
+ }
+ }
+
+ public IEnumerable<Point<int>> GetInverse()
+ {
+ int height = _bucket.Height;
+ int width = _bucket.Width;
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ if (!_bucket[x, y])
+ {
+ yield return new Point<int>(x, y);
+ }
+ }
+ }
+ }
+
+ #region ICollection<int> Members
+
+ void ICollection<Point<int>>.Add(Point<int> item)
+ {
+ Add(item);
+ }
+
+ public void Clear()
+ {
+ _bucket.SetAll(false);
+ }
+
+ public bool Contains(Point<int> item)
+ {
+ return Contains(item.X, item.Y);
+ }
+
+ public bool Contains(int x, int y)
+ {
+ if (x < 0 || y < 0 || x > Width || y > Height)
+ {
+ return false;
+ }
+ return _bucket[x, y];
+ }
+
+ void ICollection<Point<int>>.CopyTo(Point<int>[] array, int arrayIndex)
+ {
+ int height = _bucket.Height;
+ int width = _bucket.Width;
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ if (_bucket[x, y])
+ {
+ array[arrayIndex++] = new Point<int>(x, y);
+ }
+ }
+ }
+ }
+
+ int ICollection<Point<int>>.Count
+ {
+ get
+ {
+ int count = 0;
+ int height = _bucket.Height;
+ int width = _bucket.Width;
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ if (_bucket[x, y])
+ {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+ }
+
+ bool ICollection<Point<int>>.IsReadOnly
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public bool Remove(Point<int> item)
+ {
+ int x = item.X;
+ int y = item.Y;
+ return Remove(x, y);
+ }
+
+ public bool Remove(int x, int y)
+ {
+ if (x < 0 || y < 0 || x >= Width || y >= Height)
+ {
+ return false;
+ }
+
+ if (_bucket[x, y])
+ {
+ _bucket[x, y] = false;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ #endregion
+
+ public ParallelQuery<Point<int>> AsParallel()
+ {
+ int width = _bucket.Width;
+ return ParallelEnumerable.Range(0, _bucket.Height)
+ .SelectMany(y => Enumerable.Range(0, width)
+ .Where(x => _bucket[x, y])
+ .Select(x => new Point<int>(x, y)));
+ }
+
+ #region IEnumerable<Point<int>> Members
+
+ public IEnumerator<Point<int>> GetEnumerator()
+ {
+ int height = _bucket.Height;
+ int width = _bucket.Width;
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ if (_bucket[x, y])
+ {
+ yield return new Point<int>(x, y);
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.GetEnumerator();
+ }
+
+ #endregion
+
+ public bool Add(Point<int> point)
+ {
+ return Add(point.X, point.Y);
+ }
+
+ public bool Add(int x, int y)
+ {
+ if (x < 0)
+ {
+ throw new ArgumentOutOfRangeException("x", x, "Must be at least 0");
+ }
+ else if (y < 0)
+ {
+ throw new ArgumentOutOfRangeException("y", y, "Must be at least 0");
+ }
+ else if (x >= Width)
+ {
+ throw new ArgumentOutOfRangeException("x", x, string.Format("Must be at most {0}", Width - 1));
+ }
+ else if (y >= Height)
+ {
+ throw new ArgumentOutOfRangeException("y", y, string.Format("Must be at most {0}", Height - 1));
+ }
+
+ if (_bucket[x, y])
+ {
+ return false;
+ }
+ else
+ {
+ _bucket[x, y] = true;
+ return true;
+ }
+ }
+
+ public void ExceptWith(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+ int width = Width;
+ int height = Height;
+ foreach (Point<int> item in other)
+ {
+ int x = item.X;
+ int y = item.Y;
+ if (x >= 0 && y >= 0 && x < width && y < height)
+ {
+ _bucket[x, y] = false;
+ }
+ }
+ }
+
+ public void IntersectWith(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+ ISet<Point<int>> otherSet = other as ISet<Point<int>> ?? other.ToHashSet();
+ foreach (Point<int> item in this)
+ {
+ if (!otherSet.Contains(item))
+ {
+ _bucket[item.X, item.Y] = false;
+ }
+ }
+ }
+
+ public bool IsProperSubsetOf(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ ISet<Point<int>> otherSet = other as ISet<Point<int>> ?? other.ToHashSet();
+ foreach (Point<int> item in this)
+ {
+ if (!otherSet.Contains(item))
+ {
+ return false;
+ }
+ }
+ foreach (Point<int> item in otherSet)
+ {
+ if (!Contains(item))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsProperSupersetOf(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ ISet<Point<int>> otherSet = other as ISet<Point<int>> ?? other.ToHashSet();
+ foreach (Point<int> item in otherSet)
+ {
+ if (!Contains(item))
+ {
+ return false;
+ }
+ }
+
+ foreach (Point<int> item in this)
+ {
+ if (!otherSet.Contains(item))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsSubsetOf(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ ISet<Point<int>> otherSet = other as ISet<Point<int>> ?? other.ToHashSet();
+ foreach (Point<int> item in this)
+ {
+ if (!otherSet.Contains(item))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public bool IsSupersetOf(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ foreach (Point<int> item in other)
+ {
+ if (!Contains(item))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public bool Overlaps(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ foreach (Point<int> item in other)
+ {
+ if (Contains(item))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool SetEquals(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ var otherSet = other.ToHashSet();
+ foreach (Point<int> item in this)
+ {
+ if (!otherSet.Contains(item))
+ {
+ return false;
+ }
+ otherSet.Remove(item);
+ }
+ return otherSet.Count == 0;
+ }
+
+ public void SymmetricExceptWith(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ int width = Width;
+ int height = Height;
+ foreach (Point<int> item in other.Distinct())
+ {
+ int x = item.X;
+ int y = item.Y;
+ if (x >= 0 && y >= 0 && x < width && y < height)
+ {
+ _bucket[x, y] = !_bucket[x, y];
+ }
+ }
+ }
+
+ public void UnionWith(IEnumerable<Point<int>> other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ int width = Width;
+ int height = Height;
+ foreach (Point<int> item in other)
+ {
+ int x = item.X;
+ int y = item.Y;
+ if (x >= 0 && y >= 0 && x < width && y < height)
+ {
+ _bucket[x, y] = true;
+ }
+ }
+ }
+ }
+}
View
29 Ckknight.ProjectEuler/Collections/Int32Set.cs
@@ -23,6 +23,15 @@ public Int32Set(int capacity)
_bucket = new BooleanArray(capacity);
}
+ public Int32Set(int capacity, bool includeAllInitially)
+ : this(capacity)
+ {
+ if (includeAllInitially)
+ {
+ _bucket.SetAll(true);
+ }
+ }
+
public Int32Set(IEnumerable<int> sequence, int capacity)
: this(capacity)
{
@@ -72,10 +81,7 @@ void ICollection<int>.Add(int item)
public void Clear()
{
- for (int i = 0; i < _capacity; i++)
- {
- _bucket[i] = false;
- }
+ _bucket.SetAll(false);
}
public bool Contains(int item)
@@ -202,7 +208,10 @@ public void ExceptWith(IEnumerable<int> other)
}
foreach (int item in other)
{
- _bucket[item] = false;
+ if (item >= 0 && item < _capacity)
+ {
+ _bucket[item] = false;
+ }
}
}
@@ -353,7 +362,10 @@ public void SymmetricExceptWith(IEnumerable<int> other)
foreach (int item in other.Distinct())
{
- _bucket[item] = !_bucket[item];
+ if (item >= 0 && item < _capacity)
+ {
+ _bucket[item] = !_bucket[item];
+ }
}
}
@@ -366,7 +378,10 @@ public void UnionWith(IEnumerable<int> other)
foreach (int item in other)
{
- _bucket[item] = true;
+ if (item >= 0 && item < _capacity)
+ {
+ _bucket[item] = true;
+ }
}
}
}
View
101 Ckknight.ProjectEuler/Collections/MemorableEnumerable.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+
+namespace Ckknight.ProjectEuler.Collections
+{
+ public class MemorableEnumerable<T> : IEnumerable<MemorableEnumerable<T>.Entry>
+ {
+ public MemorableEnumerable(IEnumerable<T> source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ _source = source;
+ }
+
+ private readonly IEnumerable<T> _source;
+
+ public class Entry
+ {
+ public Entry(T value)
+ {
+ _value = value;
+ _hasPreviousValue = false;
+ }
+ public Entry(T value, T previousValue)
+ {
+ _value = value;
+ _hasPreviousValue = true;
+ _previousValue = previousValue;
+ }
+
+ private readonly T _value;
+ private readonly bool _hasPreviousValue;
+ private readonly T _previousValue;
+
+ public T Value
+ {
+ get
+ {
+ return _value;
+ }
+ }
+
+ public bool HasPreviousValue
+ {
+ get
+ {
+ return _hasPreviousValue;
+ }
+ }
+
+ public T PreviousValue
+ {
+ get
+ {
+ if (!_hasPreviousValue)
+ {
+ throw new InvalidOperationException("No previous value.");
+ }
+ return _previousValue;
+ }
+ }
+ }
+
+ #region IEnumerable<Entry> Members
+
+ public IEnumerator<MemorableEnumerable<T>.Entry> GetEnumerator()
+ {
+ bool isFirst = true;
+ T previous = default(T);
+ foreach (T item in _source)
+ {
+ if (isFirst)
+ {
+ isFirst = false;
+ yield return new Entry(item);
+ }
+ else
+ {
+ yield return new Entry(item, previous);
+ }
+ previous = item;
+ }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.GetEnumerator();
+ }
+
+ #endregion
+ }
+}
View
138 Ckknight.ProjectEuler/Collections/Point.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.Serialization;
+
+namespace Ckknight.ProjectEuler.Collections
+{
+ public static class Point
+ {
+ public static Point<TValue> Create<TValue>(TValue x, TValue y) where TValue : IComparable<TValue>, IEquatable<TValue>
+ {
+ return new Point<TValue>(x, y);
+ }
+ }
+
+ [Serializable]
+ public struct Point<TValue> : IComparable<Point<TValue>>, IEquatable<Point<TValue>>, ISerializable where TValue : IComparable<TValue>, IEquatable<TValue>
+ {
+ public Point(TValue x, TValue y)
+ {
+ _x = x;
+ _y = y;
+ }
+
+ private readonly TValue _x;
+ private readonly TValue _y;
+
+ public TValue X
+ {
+ get
+ {
+ return _x;
+ }
+ }
+
+ public TValue Y
+ {
+ get
+ {
+ return _y;
+ }
+ }
+
+ public override string ToString()
+ {
+ return string.Format("({0}, {1})", _x, _y);
+ }
+
+ public override int GetHashCode()
+ {
+ int xCode = _x.GetHashCode();
+ return (xCode << 4) ^ (xCode >> 4) ^ _y.GetHashCode();
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null || !(obj is Point<TValue>))
+ {
+ return false;
+ }
+ else
+ {
+ return Equals((Point<TValue>)obj);
+ }
+ }
+
+ #region IEquatable<Point<TValue>> Members
+
+ public bool Equals(Point<TValue> other)
+ {
+ return this._x.Equals(other._x) && this._y.Equals(other._y);
+ }
+
+ #endregion
+
+ #region IComparable<Point<TValue>> Members
+
+ public int CompareTo(Point<TValue> other)
+ {
+ int cmp = this._x.CompareTo(other._x);
+ if (cmp != 0)
+ {
+ return cmp;
+ }
+
+ return this._y.CompareTo(other._y);
+ }
+
+ #endregion
+
+ public static bool operator ==(Point<TValue> alpha, Point<TValue> bravo)
+ {
+ return alpha.Equals(bravo);
+ }
+
+ public static bool operator !=(Point<TValue> alpha, Point<TValue> bravo)
+ {
+ return !alpha.Equals(bravo);
+ }
+
+ public static bool operator <(Point<TValue> alpha, Point<TValue> bravo)
+ {
+ return alpha.CompareTo(bravo) < 0;
+ }
+
+ public static bool operator >(Point<TValue> alpha, Point<TValue> bravo)
+ {
+ return alpha.CompareTo(bravo) > 0;
+ }
+
+ public static bool operator <=(Point<TValue> alpha, Point<TValue> bravo)
+ {
+ return alpha.CompareTo(bravo) <= 0;
+ }
+
+ public static bool operator >=(Point<TValue> alpha, Point<TValue> bravo)
+ {
+ return alpha.CompareTo(bravo) >= 0;
+ }
+
+ #region ISerializable Members
+
+ private Point(SerializationInfo info, StreamingContext context)
+ {
+ _x = (TValue)info.GetValue("x", typeof(TValue));
+ _y = (TValue)info.GetValue("y", typeof(TValue));
+ }
+
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("x", _x, typeof(TValue));
+ info.AddValue("y", _y, typeof(TValue));
+ }
+
+ #endregion
+ }
+}
View
8 Ckknight.ProjectEuler/Collections/PrimeGenerator.cs
@@ -7,7 +7,7 @@
namespace Ckknight.ProjectEuler.Collections
{
- public class PrimeGenerator : IEnumerable<long>, IEnumerable
+ public sealed class PrimeGenerator : IEnumerable<long>, IEnumerable
{
private PrimeGenerator()
{
@@ -47,7 +47,7 @@ public void CalculateUpTo(long value)
}
}
- public void CalculateNextChuck()
+ private void CalculateNextChunk()
{
CalculatePrimes(_calculatedUpTo + 1, StandardPrimeCalculationChunkSize);
}
@@ -129,7 +129,7 @@ public IEnumerator<long> GetEnumerator()
}
} while (count < _primes.Count);
- CalculateNextChuck();
+ CalculateNextChunk();
}
}
@@ -159,7 +159,7 @@ public long GetPrimeAtIndex(int index)
while (_primes.Count <= index)
{
- CalculateNextChuck();
+ CalculateNextChunk();
}
return _primes[index];
View
17 Ckknight.ProjectEuler/Fraction.cs
@@ -2,10 +2,12 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Runtime.Serialization;
namespace Ckknight.ProjectEuler
{
- public struct Fraction : IComparable<Fraction>, IEquatable<Fraction>
+ [Serializable]
+ public struct Fraction : IComparable<Fraction>, IEquatable<Fraction>, ISerializable
{
public Fraction(long numerator)
: this(numerator, 1) { }
@@ -640,5 +642,18 @@ public static Fraction DivRem(Fraction dividend, Fraction divisor, out Fraction
return new Fraction((long)number, denominator);
}
+
+ #region ISerializable Members
+
+ private Fraction(SerializationInfo info, StreamingContext context)
+ : this(info.GetInt64("n"), info.GetInt64("d")) { }
+
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("n", _numerator);
+ info.AddValue("d", _denominator);
+ }
+
+ #endregion
}
}
View
126 Ckknight.ProjectEuler/FuncExtensions.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Ckknight.ProjectEuler
+{
+ public static class FuncExtensions
+ {
+ public static Func<T, TResult> Memoize<T, TResult>(this Func<T, TResult> func)
+ {
+ if (func == null)
+ {
+ throw new ArgumentNullException("func");
+ }
+
+ var cache = new Dictionary<T, TResult>();
+
+ return t =>
+ {
+ TResult result;
+ if (!cache.TryGetValue(t, out result))
+ {
+ cache[t] = result = func(t);
+ }
+ return result;
+ };
+ }
+
+ public static Func<T1, T2, TResult> Memoize<T1, T2, TResult>(this Func<T1, T2, TResult> func)
+ {
+ if (func == null)
+ {
+ throw new ArgumentNullException("func");
+ }
+
+ var cache = new Dictionary<T1, Dictionary<T2, TResult>>();
+
+ return (t1, t2) =>
+ {
+ Dictionary<T2, TResult> cache2;
+ if (!cache.TryGetValue(t1, out cache2))
+ {
+ cache[t1] = cache2 = new Dictionary<T2, TResult>();
+ }
+
+ TResult result;
+ if (!cache2.TryGetValue(t2, out result))
+ {
+ cache2[t2] = result = func(t1, t2);
+ }
+ return result;
+ };
+ }
+
+ public static Func<T1, T2, T3, TResult> Memoize<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func)
+ {
+ if (func == null)
+ {
+ throw new ArgumentNullException("func");
+ }
+
+ var cache = new Dictionary<T1, Dictionary<T2, Dictionary<T3, TResult>>>();
+
+ return (t1, t2, t3) =>
+ {
+ Dictionary<T2, Dictionary<T3, TResult>> cache2;
+ if (!cache.TryGetValue(t1, out cache2))
+ {
+ cache[t1] = cache2 = new Dictionary<T2, Dictionary<T3, TResult>>();
+ }
+
+ Dictionary<T3, TResult> cache3;
+ if (!cache2.TryGetValue(t2, out cache3))
+ {
+ cache2[t2] = cache3 = new Dictionary<T3, TResult>();
+ }
+
+ TResult result;
+ if (!cache3.TryGetValue(t3, out result))
+ {
+ cache3[t3] = result = func(t1, t2, t3);
+ }
+ return result;
+ };
+ }
+
+ public static Func<T1, T2, T3, T4, TResult> Memoize<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> func)
+ {
+ if (func == null)
+ {
+ throw new ArgumentNullException("func");
+ }
+
+ var cache = new Dictionary<T1, Dictionary<T2, Dictionary<T3, Dictionary<T4, TResult>>>>();
+
+ return (t1, t2, t3, t4) =>
+ {
+ Dictionary<T2, Dictionary<T3, Dictionary<T4, TResult>>> cache2;
+ if (!cache.TryGetValue(t1, out cache2))
+ {
+ cache[t1] = cache2 = new Dictionary<T2, Dictionary<T3, Dictionary<T4, TResult>>>();
+ }
+
+ Dictionary<T3, Dictionary<T4, TResult>> cache3;
+ if (!cache2.TryGetValue(t2, out cache3))
+ {
+ cache2[t2] = cache3 = new Dictionary<T3, Dictionary<T4, TResult>>();
+ }
+
+ Dictionary<T4, TResult> cache4;
+ if (!cache3.TryGetValue(t3, out cache4))
+ {
+ cache3[t3] = cache4 = new Dictionary<T4, TResult>();
+ }
+
+ TResult result;
+ if (!cache4.TryGetValue(t4, out result))
+ {
+ cache4[t4] = result = func(t1, t2, t3, t4);
+ }
+ return result;
+ };
+ }
+ }
+}
View
128 Ckknight.ProjectEuler/MathUtilities.cs
@@ -5,6 +5,7 @@
using System.Collections;
using System.Numerics;
using Ckknight.ProjectEuler.Collections;
+using System.Security.Cryptography;
namespace Ckknight.ProjectEuler
{
@@ -121,6 +122,11 @@ public static int[] ToDigits(BigInteger value, bool reverse)
public static long FromDigits(IEnumerable<int> digits)
{
+ return FromDigits(digits, false);
+ }
+
+ public static long FromDigits(IEnumerable<int> digits, bool reverse)
+ {
if (digits == null)
{
throw new ArgumentNullException("digits");
@@ -129,6 +135,11 @@ public static long FromDigits(IEnumerable<int> digits)
long total = 0;
long power = 1;
+ if (reverse)
+ {
+ digits = digits.Reverse();
+ }
+
foreach (int digit in digits)
{
total += digit * power;
@@ -140,6 +151,11 @@ public static long FromDigits(IEnumerable<int> digits)
public static BigInteger FromDigitsToBigInteger(IEnumerable<int> digits)
{
+ return FromDigitsToBigInteger(digits, false);
+ }
+
+ public static BigInteger FromDigitsToBigInteger(IEnumerable<int> digits, bool reverse)
+ {
if (digits == null)
{
throw new ArgumentNullException("digits");
@@ -148,6 +164,11 @@ public static BigInteger FromDigitsToBigInteger(IEnumerable<int> digits)
BigInteger total = 0;
BigInteger power = 1;
+ if (reverse)
+ {
+ digits = digits.Reverse();
+ }
+
foreach (int digit in digits)
{
total += digit * power;
@@ -316,6 +337,103 @@ public static long Pow(long number, long exponent)
return result;
}
+ public static decimal Pow(decimal number, long exponent)
+ {
+ if (number == 0m)
+ {
+ return 0m;
+ }
+ else if (exponent == 0L || number == 1m)
+ {
+ return 1m;
+ }
+ else if (exponent == 1L)
+ {
+ return number;
+ }
+ else if (exponent == 2L)
+ {
+ return number * number;
+ }
+ else if (exponent < 0L)
+ {
+ throw new ArgumentOutOfRangeException("exponent", exponent, "Must be at least 0");
+ }
+ else if (number == -1m)