C# - Prime Engine (Generation, Primality, Factorization)











up vote
0
down vote

favorite












I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



Interfaces



public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}


Implementation



public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;

public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}

private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;

if (IsPrime(low))
{
_primeCollection.Add(low);
}

if (IsPrime(high))
{
_primeCollection.Add(high);
}

_indexFactor += 1;
_maxChecked = high;
}

private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}

public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}

private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}

private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}

private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}

private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}

public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}

public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;

while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}

if (value != 1)
{
yield return value;
}
}

public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}








share


























    up vote
    0
    down vote

    favorite












    I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



    I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



    I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



    I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



    Interfaces



    public interface IPrimeGenerator
    {
    IEnumerable<long> PrimesUntilValue(long value);
    IEnumerable<long> PrimesUntilCount(int count);
    }

    public interface IPrimeGenerator
    {
    IEnumerable<long> PrimesUntilValue(long value);
    IEnumerable<long> PrimesUntilCount(int count);
    }

    public interface IPrimeFactorizer
    {
    IEnumerable<long> PrimeFactors(long value);
    IEnumerable<long> UniquePrimeFactors(long value);
    }


    Implementation



    public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
    {
    private readonly ICollection<long> _primeCollection;
    private long _indexFactor;
    private long _maxChecked;

    public PrimeEngine()
    {
    _primeCollection = new Collection<long> {2, 3};
    _indexFactor = 1;
    _maxChecked = 3;
    }

    private void CheckNextPossiblePrimeDoublet()
    {
    var low = 6 * _indexFactor - 1;
    var high = low + 2;

    if (IsPrime(low))
    {
    _primeCollection.Add(low);
    }

    if (IsPrime(high))
    {
    _primeCollection.Add(high);
    }

    _indexFactor += 1;
    _maxChecked = high;
    }

    private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
    {
    FillPrimesUntilRoot(value);
    return PrimesUntilRoot(value);
    }

    public bool IsPrime(long value)
    {
    var primePool = GetPossibleSmallerPrimeFactors(value);
    return primePool.All(prime => value % prime != 0);
    }

    private void FillPrimesUntilValue(long value)
    {
    while (_maxChecked < value)
    {
    CheckNextPossiblePrimeDoublet();
    }
    }

    private void FillPrimesUntilCount(int count)
    {
    while (_primeCollection.Count < count)
    {
    CheckNextPossiblePrimeDoublet();
    }
    }

    private static long FloorOfRoot(long value)
    {
    return (long) Math.Floor(Math.Sqrt(value));
    }

    private void FillPrimesUntilRoot(long value)
    {
    FillPrimesUntilValue(FloorOfRoot(value));
    }

    public IEnumerable<long> PrimesUntilValue(long value)
    {
    FillPrimesUntilValue(value);
    return _primeCollection.TakeWhile(prime => prime <= value);
    }

    public IEnumerable<long> PrimesUntilCount(int count)
    {
    FillPrimesUntilCount(count);
    return _primeCollection.Take(count);
    }

    public IEnumerable<long> PrimesUntilRoot(long value)
    {
    return PrimesUntilValue(FloorOfRoot(value));
    }

    public IEnumerable<long> PrimeFactors(long value)
    {
    FillPrimesUntilRoot(value);
    foreach (var prime in PrimesUntilRoot(value))
    {
    if (prime > value) break;

    while (value % prime == 0)
    {
    yield return prime;
    value /= prime;
    }
    }

    if (value != 1)
    {
    yield return value;
    }
    }

    public IEnumerable<long> UniquePrimeFactors(long value)
    {
    return PrimeFactors(value).Distinct();
    }
    }








    share
























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



      I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



      I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



      I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



      Interfaces



      public interface IPrimeGenerator
      {
      IEnumerable<long> PrimesUntilValue(long value);
      IEnumerable<long> PrimesUntilCount(int count);
      }

      public interface IPrimeGenerator
      {
      IEnumerable<long> PrimesUntilValue(long value);
      IEnumerable<long> PrimesUntilCount(int count);
      }

      public interface IPrimeFactorizer
      {
      IEnumerable<long> PrimeFactors(long value);
      IEnumerable<long> UniquePrimeFactors(long value);
      }


      Implementation



      public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
      {
      private readonly ICollection<long> _primeCollection;
      private long _indexFactor;
      private long _maxChecked;

      public PrimeEngine()
      {
      _primeCollection = new Collection<long> {2, 3};
      _indexFactor = 1;
      _maxChecked = 3;
      }

      private void CheckNextPossiblePrimeDoublet()
      {
      var low = 6 * _indexFactor - 1;
      var high = low + 2;

      if (IsPrime(low))
      {
      _primeCollection.Add(low);
      }

      if (IsPrime(high))
      {
      _primeCollection.Add(high);
      }

      _indexFactor += 1;
      _maxChecked = high;
      }

      private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
      {
      FillPrimesUntilRoot(value);
      return PrimesUntilRoot(value);
      }

      public bool IsPrime(long value)
      {
      var primePool = GetPossibleSmallerPrimeFactors(value);
      return primePool.All(prime => value % prime != 0);
      }

      private void FillPrimesUntilValue(long value)
      {
      while (_maxChecked < value)
      {
      CheckNextPossiblePrimeDoublet();
      }
      }

      private void FillPrimesUntilCount(int count)
      {
      while (_primeCollection.Count < count)
      {
      CheckNextPossiblePrimeDoublet();
      }
      }

      private static long FloorOfRoot(long value)
      {
      return (long) Math.Floor(Math.Sqrt(value));
      }

      private void FillPrimesUntilRoot(long value)
      {
      FillPrimesUntilValue(FloorOfRoot(value));
      }

      public IEnumerable<long> PrimesUntilValue(long value)
      {
      FillPrimesUntilValue(value);
      return _primeCollection.TakeWhile(prime => prime <= value);
      }

      public IEnumerable<long> PrimesUntilCount(int count)
      {
      FillPrimesUntilCount(count);
      return _primeCollection.Take(count);
      }

      public IEnumerable<long> PrimesUntilRoot(long value)
      {
      return PrimesUntilValue(FloorOfRoot(value));
      }

      public IEnumerable<long> PrimeFactors(long value)
      {
      FillPrimesUntilRoot(value);
      foreach (var prime in PrimesUntilRoot(value))
      {
      if (prime > value) break;

      while (value % prime == 0)
      {
      yield return prime;
      value /= prime;
      }
      }

      if (value != 1)
      {
      yield return value;
      }
      }

      public IEnumerable<long> UniquePrimeFactors(long value)
      {
      return PrimeFactors(value).Distinct();
      }
      }








      share













      I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



      I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



      I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



      I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



      Interfaces



      public interface IPrimeGenerator
      {
      IEnumerable<long> PrimesUntilValue(long value);
      IEnumerable<long> PrimesUntilCount(int count);
      }

      public interface IPrimeGenerator
      {
      IEnumerable<long> PrimesUntilValue(long value);
      IEnumerable<long> PrimesUntilCount(int count);
      }

      public interface IPrimeFactorizer
      {
      IEnumerable<long> PrimeFactors(long value);
      IEnumerable<long> UniquePrimeFactors(long value);
      }


      Implementation



      public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
      {
      private readonly ICollection<long> _primeCollection;
      private long _indexFactor;
      private long _maxChecked;

      public PrimeEngine()
      {
      _primeCollection = new Collection<long> {2, 3};
      _indexFactor = 1;
      _maxChecked = 3;
      }

      private void CheckNextPossiblePrimeDoublet()
      {
      var low = 6 * _indexFactor - 1;
      var high = low + 2;

      if (IsPrime(low))
      {
      _primeCollection.Add(low);
      }

      if (IsPrime(high))
      {
      _primeCollection.Add(high);
      }

      _indexFactor += 1;
      _maxChecked = high;
      }

      private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
      {
      FillPrimesUntilRoot(value);
      return PrimesUntilRoot(value);
      }

      public bool IsPrime(long value)
      {
      var primePool = GetPossibleSmallerPrimeFactors(value);
      return primePool.All(prime => value % prime != 0);
      }

      private void FillPrimesUntilValue(long value)
      {
      while (_maxChecked < value)
      {
      CheckNextPossiblePrimeDoublet();
      }
      }

      private void FillPrimesUntilCount(int count)
      {
      while (_primeCollection.Count < count)
      {
      CheckNextPossiblePrimeDoublet();
      }
      }

      private static long FloorOfRoot(long value)
      {
      return (long) Math.Floor(Math.Sqrt(value));
      }

      private void FillPrimesUntilRoot(long value)
      {
      FillPrimesUntilValue(FloorOfRoot(value));
      }

      public IEnumerable<long> PrimesUntilValue(long value)
      {
      FillPrimesUntilValue(value);
      return _primeCollection.TakeWhile(prime => prime <= value);
      }

      public IEnumerable<long> PrimesUntilCount(int count)
      {
      FillPrimesUntilCount(count);
      return _primeCollection.Take(count);
      }

      public IEnumerable<long> PrimesUntilRoot(long value)
      {
      return PrimesUntilValue(FloorOfRoot(value));
      }

      public IEnumerable<long> PrimeFactors(long value)
      {
      FillPrimesUntilRoot(value);
      foreach (var prime in PrimesUntilRoot(value))
      {
      if (prime > value) break;

      while (value % prime == 0)
      {
      yield return prime;
      value /= prime;
      }
      }

      if (value != 1)
      {
      yield return value;
      }
      }

      public IEnumerable<long> UniquePrimeFactors(long value)
      {
      return PrimeFactors(value).Distinct();
      }
      }






      c# beginner primes





      share












      share










      share



      share










      asked 4 mins ago









      Jared Goguen

      777312




      777312



























          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208424%2fc-prime-engine-generation-primality-factorization%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208424%2fc-prime-engine-generation-primality-factorization%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Costa Masnaga

          Fotorealismo

          Sidney Franklin