Skip to content

Commit

Permalink
Solve p7, p10 in C#; make primes generic
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Aug 30, 2024
1 parent 0544747 commit 58ceee8
Show file tree
Hide file tree
Showing 12 changed files with 193 additions and 34 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Olivia's Project Euler Solutions
| | C++14+ in: |msvc| [1]_ | | |CodeQL| |br| |
| | |br| Browser [3]_ | | |Cp-lint| |
+------------+----------------------------+--------+-------------------+
| C# | .NET 2+ | 19 | |C#i| |br| |
| C# | .NET 2+ | 21 | |C#i| |br| |
| | | | |Cs-Cov| |br| |
| | | | |CodeQL| |br| |
| | | | |C#-lint| |
Expand Down
10 changes: 6 additions & 4 deletions csharp/Euler.Test/test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ public static IEnumerable<object[]> Data()
yield return new object[] { typeof(p0003), false, Utilities.GetAnswer(3) };
yield return new object[] { typeof(p0004), false, Utilities.GetAnswer(4) };
yield return new object[] { typeof(p0006), false, Utilities.GetAnswer(6) };
yield return new object[] { typeof(p0007), false, Utilities.GetAnswer(7) };
yield return new object[] { typeof(p0008), false, Utilities.GetAnswer(8) };
yield return new object[] { typeof(p0009), false, Utilities.GetAnswer(9) };
yield return new object[] { typeof(p0010), false, Utilities.GetAnswer(10) };
yield return new object[] { typeof(p0011), false, Utilities.GetAnswer(11) };
yield return new object[] { typeof(p0013), false, Utilities.GetAnswer(13) };
yield return new object[] { typeof(p0014), false, Utilities.GetAnswer(14) };
Expand Down Expand Up @@ -65,7 +67,7 @@ public void EulerTest_Prime_Primes()
List<long> results = new() {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29
};
var comparison = Prime.Primes().GetEnumerator();
var comparison = Prime.Primes<long>().GetEnumerator();
for (byte i = 0; i < results.Count; i += 1)
{
long expected = results[i];
Expand All @@ -80,11 +82,11 @@ public void EulerTest_Prime_PrimeFactors()
List<long> candidates = new() {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29
};
foreach (long x in candidates)
foreach (long x in candidates)
{
foreach (long y in candidates)
foreach (long y in candidates)
{
List<long> result = new(Prime.PrimeFactors(x * y));
List<long> result = new(Prime.PrimeFactors<long>(x * y));
Assert.Contains(x, result);
Assert.Contains(y, result);
}
Expand Down
80 changes: 55 additions & 25 deletions csharp/Euler/include/prime.cs
Original file line number Diff line number Diff line change
@@ -1,61 +1,83 @@
using System;
using System.Collections.Generic;

namespace Euler
{
public static class Prime
{
private static long lastCached = 0;
private static List<long> cache = new();
private static readonly Dictionary<Type, (dynamic LastCached, List<dynamic> Cache)> Caches = new();

public static IEnumerable<long> Primes(long? stop = null)
public static IEnumerable<T> Primes<T>(T? stop = null) where T : struct
{
if (stop is null)
foreach (dynamic p in _Primes(stop))
{
foreach (var p in cache)
yield return (T) p;
}
}

private static IEnumerable<dynamic> _Primes(dynamic? stop = null)
{
Type type = stop != null ? stop.GetType() : typeof(long);
if (!Caches.TryGetValue(type, out var cacheData))
{
cacheData = (LastCached: (dynamic)0, Cache: new List<dynamic>());
Caches[type] = cacheData;
}
(dynamic lastCached, List<dynamic> cache) = cacheData;

// Yield cached values
if (stop == null)
{
foreach (dynamic p in cache)
{
yield return p;
}
}
else
{
foreach (var p in cache)
foreach (dynamic p in cache)
{
if (p < stop)
yield return p;
else
break;
}
}
if (stop is not null && lastCached > stop)

// Generate new primes
if (stop != null && lastCached > stop)
yield break;
foreach (var p in ModifiedEratosthenes())

foreach (dynamic p in ModifiedEratosthenes())
{
if (p <= lastCached)
continue;
if (stop is not null && p > stop)
if (stop != null && p > stop)
break;

cache.Add(p);
lastCached = p;
Caches[type] = (lastCached, cache);
yield return p;
}
}

private static IEnumerable<long> ModifiedEratosthenes()
private static IEnumerable<dynamic> ModifiedEratosthenes()
{
yield return 2;
yield return 3;
yield return 5;
yield return 7;
Dictionary<long, long> sieve = new();
var sieve = new Dictionary<dynamic, dynamic>();
var recurse = ModifiedEratosthenes().GetEnumerator();
recurse.MoveNext();
recurse.MoveNext();
long prime = recurse.Current;
dynamic prime = recurse.Current;
if (prime != 3)
throw new Exception();
long primeSquared = prime * prime;
long step = 2;
for (long candidate = 9; ; candidate += 2)
dynamic primeSquared = prime * prime;
dynamic step = 2;
for (dynamic candidate = 9; ; candidate += 2)
{
if (sieve.ContainsKey(candidate))
{
Expand All @@ -74,7 +96,7 @@ private static IEnumerable<long> ModifiedEratosthenes()
prime = recurse.Current;
primeSquared = prime * prime;
}
long tc = candidate;
dynamic tc = candidate;
do
{
tc += step;
Expand All @@ -83,7 +105,15 @@ private static IEnumerable<long> ModifiedEratosthenes()
}
}

public static IEnumerable<long> PrimeFactors(long n)
public static IEnumerable<T> PrimeFactors<T>(T n) where T : struct
{
foreach (dynamic f in _PrimeFactors(n))
{
yield return (T) f;
}
}

private static IEnumerable<dynamic> _PrimeFactors(dynamic n)
{
if (n < 0)
{
Expand All @@ -96,10 +126,10 @@ public static IEnumerable<long> PrimeFactors(long n)
}
else
{
long root = (long)Math.Ceiling(Math.Sqrt(n));
foreach (long factor in Primes())
dynamic root = (dynamic)Math.Ceiling(Math.Sqrt((double)n));
foreach (dynamic factor in _Primes())
{
long modulo = n % factor;
dynamic modulo = n % factor;
if (modulo == 0)
{
do
Expand All @@ -108,7 +138,7 @@ public static IEnumerable<long> PrimeFactors(long n)
n /= factor;
modulo = n % factor;
} while (modulo == 0);
root = (long)Math.Ceiling(Math.Sqrt(n));
root = (dynamic)Math.Ceiling(Math.Sqrt((double)n));
}
if (n <= 1)
break;
Expand All @@ -121,21 +151,21 @@ public static IEnumerable<long> PrimeFactors(long n)
}
}

public static long isComposite(long n)
public static dynamic IsComposite(dynamic n)
{
var factors = PrimeFactors(n).GetEnumerator();
factors.MoveNext();
long first = factors.Current;
dynamic first = factors.Current;
if (first == n)
return 0;
return first;
}

public static bool isPrime(long n)
public static bool IsPrime(dynamic n)
{
if (n < 2)
return false;
return isComposite(n) == 0;
return IsComposite(n) == 0;
}
}
}
29 changes: 29 additions & 0 deletions csharp/Euler/p0007.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
Project Euler Problem 7
Problem:
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that
the 6th prime is 13.
What is the 10 001st prime number?
*/
using System;

namespace Euler
{
public class p0007 : IEuler
{
public object Answer()
{
int i = 0;
foreach (long p in Prime.Primes<long>())
{
if (i == 10000)
return (int)p;
i++;
}
return -1;
}
}
}
21 changes: 21 additions & 0 deletions csharp/Euler/p0010.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Project Euler Problem 10
Problem:
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
*/
using System;

namespace Euler
{
public class p0010 : IEuler
{
public object Answer()
{
return Enumerable.Sum(Prime.Primes<long>(2000000));
}
}
}
2 changes: 1 addition & 1 deletion csharp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ clean:
.PHONY: test
test: ../LICENSE
ifneq ($(NOT_TERMUX),0)
@dotnet test --nologo $(cov_args)
@dotnet test --nologo -l "console;verbosity=normal" $(cov_args)
endif

.PHONY: test_%
Expand Down
2 changes: 2 additions & 0 deletions csharp/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,10 @@ Problems Solved
- ☒ `3 <./Euler/p0003.cs>`__
- ☒ `4 <./Euler/p0004.cs>`__
- ☒ `6 <./Euler/p0006.cs>`__
- ☒ `7 <./Euler/p0007.cs>`__
- ☒ `8 <./Euler/p0008.cs>`__
- ☒ `9 <./Euler/p0009.cs>`__
- ☒ `10 <./Euler/p0010.cs>`__
- ☒ `11 <./Euler/p0011.cs>`__
- ☒ `13 <./Euler/p0013.cs>`__
- ☒ `14 <./Euler/p0014.cs>`__
Expand Down
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ Problems Solved
+-----------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`6` |:c-d:`0006` |:cp-d:`0006`|:cs-d:`0006`|:ja-d:`0006`|:js-d:`0006`|:py-d:`0006`|:rs-d:`0006`|
+-----------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`7` |:c-d:`0007` | | | |:js-d:`0007`|:py-d:`0007`|:rs-d:`0007`|
|:prob:`7` |:c-d:`0007` | |:cs-d:`0007`| |:js-d:`0007`|:py-d:`0007`|:rs-d:`0007`|
+-----------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`8` |:c-d:`0008` |:cp-d:`0008`|:cs-d:`0008`|:ja-d:`0008`|:js-d:`0008`|:py-d:`0008`|:rs-d:`0008`|
+-----------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`9` |:c-d:`0009` |:cp-d:`0009`|:cs-d:`0009`|:ja-d:`0009`|:js-d:`0009`|:py-d:`0009`|:rs-d:`0009`|
+-----------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`10` |:c-d:`0010` | | | |:js-d:`0010`|:py-d:`0010`|:rs-d:`0010`|
|:prob:`10` |:c-d:`0010` | |:cs-d:`0010`| |:js-d:`0010`|:py-d:`0010`|:rs-d:`0010`|
+-----------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`11` |:c-d:`0011` |:cp-d:`0011`|:cs-d:`0011`|:ja-d:`0011`|:js-d:`0011`|:py-d:`0011`|:rs-d:`0011`|
+-----------+------------+------------+------------+------------+------------+------------+------------+
Expand Down
39 changes: 39 additions & 0 deletions docs/src/csharp/lib/prime.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
prime.cs
========

View source code :source:`csharp/include/prime.cs`

Includes
--------

.. csharp:namespace:: Euler
.. csharp:class:: Prime
.. csharp:method:: static IEnumerable<T> Primes<T>(T? stop = null)
This function implements the `Sieve of Eratosthenes <https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes>`_. In general,
it will iterate over all of the prime numbers. You can also provide an optional ``stop`` argument, which will force
it to not yield any numbers above that limit. Below is a gif (courtesy of Wikipedia) that demonstrates the principle
of the sieve.

.. image:: https://upload.wikimedia.org/wikipedia/commons/9/94/Animation_Sieve_of_Eratosth.gif
:alt: Any animated example of the Sieve of Eratosthenes

.. csharp:method:: static IEnumerable<T> PrimeFactors<T>(T n)
This function will iterate over all the prime factors of a number, as well as ``-1`` and ``0`` if relevant.

.. csharp:method:: static dynamic isComposite(long n)
Returns ``0`` if the number is prime, and the smallest prime factor otherwise.

.. csharp:method:: static bool isPrime(dynamic n)
Returns ``true`` if the number is prime, and ``false`` otherwise.

.. literalinclude:: ../../../../csharp/Euler/include/prime.cs
:language: csharp
:linenos:

.. tags:: csharp-iterator, prime-number
2 changes: 1 addition & 1 deletion docs/src/csharp/p0003.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ View source code :source:`csharp/Euler/p0003.cs`
:language: csharp
:linenos:

.. tags:: fibonacci-number, divisibility
.. tags:: prime-number, factorization, csharp-iterator
18 changes: 18 additions & 0 deletions docs/src/csharp/p0007.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
C# Implementation of Problem 7
==============================

View source code :source:`csharp/Euler/p0007.cs`

.. csharp:namespace:: Euler
.. csharp:class:: p0007
.. csharp:inherits:: Euler.IEuler
.. csharp:method:: object Answer()
.. literalinclude:: ../../../csharp/Euler/p0007.cs
:language: csharp
:linenos:

.. tags:: prime-number, csharp-iterator
18 changes: 18 additions & 0 deletions docs/src/csharp/p0010.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
C# Implementation of Problem 10
===============================

View source code :source:`csharp/Euler/p0010.cs`

.. csharp:namespace:: Euler
.. csharp:class:: p0010
.. csharp:inherits:: Euler.IEuler
.. csharp:method:: object Answer()
.. literalinclude:: ../../../csharp/Euler/p0010.cs
:language: csharp
:linenos:

.. tags:: prime-number, csharp-iterator

0 comments on commit 58ceee8

Please sign in to comment.