Skip to content

Commit

Permalink
Solve p14, p15 in C#
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Jul 31, 2024
1 parent fbae5a1 commit a0cf4ad
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ LivInTheLookingGlass’s Project Euler solutions
| | ``gcc``, ``clang`` |br| | | |Cp-Cov| |br| |
| | C++14+ in ``msvc`` | | |CodeQL| |
+------------+-------------------------+--------+-------------------+
| C# | .NET 2+ | 10 | |C#i| |br| |
| C# | .NET 2+ | 12 | |C#i| |br| |
| | | | |Cs-Cov| |br| |
| | | | |CodeQL| |
+------------+-------------------------+--------+-------------------+
Expand Down
8 changes: 5 additions & 3 deletions csharp/Euler.Test/test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public static IEnumerable<object[]> Data()
yield return new object[] { typeof(p0008), false, 23514624000 };
yield return new object[] { typeof(p0009), false, 31875000 };
yield return new object[] { typeof(p0011), false, 70600674 };
yield return new object[] { typeof(p0014), false, 837799 };
yield return new object[] { typeof(p0015), false, 137846528820 };
yield return new object[] { typeof(p0017), false, 21124 };
yield return new object[] { typeof(p0076), true, 190569291 };
yield return new object[] { typeof(p0836), false, "aprilfoolsjoke" };
Expand All @@ -24,9 +26,9 @@ public static IEnumerable<object[]> Data()
[MemberData(nameof(Data))]
public async Task EulerTest_Problem(Type problem, bool isSlow, object expected)
{
IEuler? prob;
prob = (IEuler?)Activator.CreateInstance(problem);
Assert.NotNull(prob);
IEuler? prob = (IEuler?)Activator.CreateInstance(problem);
if (prob is null)
throw new Exception("Unable to construct test object");
Stopwatch sw = Stopwatch.StartNew();
object result = await prob.Answer();
sw.Stop();
Expand Down
86 changes: 86 additions & 0 deletions csharp/Euler/include/math.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;

namespace Euler
{
public static class Mathematics
{
public static ulong Factorial(ulong n)
{
ulong answer = 1;
for (ulong x = 2; x < n; x += 1)
answer *= x;
return answer;
}

public static ulong NChooseR(ulong n, ulong r)
{
if (n < 20)
return Factorial(n) / Factorial(r) / Factorial(n - r);
ulong answer, tmp;
uint i, j;
sbyte[] factors = new sbyte[n + 1];
// collect factors of final number
for (i = 2; i <= n; i += 1)
factors[i] = 1;
// negative factor values indicate need to divide
for (i = 2; i <= r; i += 1)
{
factors[i] -= 1;
}
for (i = 2; i <= n - r; i += 1)
{
factors[i] -= 1;
}
// this loop reduces to prime factors only
for (i = (uint)n; i > 1; i -= 1)
{
for (j = 2; j < i; j += 1)
{
if (i % j == 0)
{
factors[j] += factors[i];
factors[i / j] += factors[i];
factors[i] = 0;
break;
}
}
}
i = j = 2;
answer = 1;
while (i <= n)
{
while (factors[i] > 0)
{
tmp = answer;
answer *= i;
while (answer < tmp && j <= n)
{
while (factors[j] < 0)
{
tmp /= j;
factors[j] += 1;
}
j += 1;
answer = tmp * i;
}
if (answer < tmp)
{
return ulong.MaxValue; // this indicates an overflow
}
factors[i] -= 1;
}
i += 1;
}
while (j <= n)
{
while (factors[j] < 0)
{
answer /= j;
factors[j] += 1;
}
j += 1;
}
return answer;
}
}
}
69 changes: 69 additions & 0 deletions csharp/Euler/p0014.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Project Euler Problem 14
This was easier to do in C# than I would have thought
Problem:
The following iterative sequence is defined for the set of positive integers:
n → n/2 (n is even)
n → 3n + 1 (n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been
proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.
*/
using System;

namespace Euler
{
public class p0014 : IEuler
{
public Task<object> Answer()
{
int biggestSeen = 0;
long biggestIdx = 0;
Dictionary<long, int> cache = new();
for (long x = 1; x < 1000000; x += 1)
{
int result = CollatzLen(x, cache);
if (result > biggestSeen)
{
biggestSeen = result;
biggestIdx = x;
}
}
return Task.FromResult<object>((int)biggestIdx);
}

static int CollatzLen(long n, IDictionary<long, int> cache)
{
if (n == 1)
{
return 0;
}
else if (cache.ContainsKey(n))
{
return cache[n];
}
int result;
if (n % 2 == 0)
{
result = 1 + CollatzLen(n / 2, cache);
}
else
{
result = 2 + CollatzLen((3 * n + 1) / 2, cache);
}
cache.Add(n, result);
return result;
}
}
}
28 changes: 28 additions & 0 deletions csharp/Euler/p0015.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Project Euler Problem 15
Turns out this is easy, if you think sideways a bit
You can only go down or right. If we say right=1, then you can only have 20 1s, since otherwise you go off the grid.
You also can't have fewer than 20 1s, since then you go off the grid the other way. This means you can look at it as a
bit string, and the number of 40-bit strings with 20 1s is 40c20.
Problem:
Starting in the top left corner of a 2×2 grid, and only being able to move to the right and down, there are exactly 6
routes to the bottom right corner.
How many such routes are there through a 20×20 grid?
*/
using System;

namespace Euler
{
public class p0015 : IEuler
{
public Task<object> Answer()
{
return Task.FromResult<object>((long)Mathematics.NChooseR(40, 20));
}
}
}
16 changes: 16 additions & 0 deletions docs/csharp/p0014.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
C# Implementation of Problem 14
===============================

View source code `here on GitHub! <https://github.com/LivInTheLookingGlass/Euler/blob/master/csharp/Euler/p0014.cs>`_

.. csharp:namespace:: Euler
.. csharp:class:: p0014
.. csharp:inherits:: Euler.IEuler
.. csharp:method:: Task<object> Answer()
.. literalinclude:: ../../csharp/Euler/p0014.cs
:language: csharp
:linenos:
16 changes: 16 additions & 0 deletions docs/csharp/p0015.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
C# Implementation of Problem 14
===============================

View source code `here on GitHub! <https://github.com/LivInTheLookingGlass/Euler/blob/master/csharp/Euler/p0014.cs>`_

.. csharp:namespace:: Euler
.. csharp:class:: p0014
.. csharp:inherits:: Euler.IEuler
.. csharp:method:: Task<object> Answer()
.. literalinclude:: ../../csharp/Euler/p0014.cs
:language: csharp
:linenos:
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ Key:
+-----------+------------+------------+------------+------------+------------+------------+
|:prob:`13` |:c-d:`0013` | | | |:py-d:`0013`|:rs-d:`0013`|
+-----------+------------+------------+------------+------------+------------+------------+
|:prob:`14` |:c-d:`0014` |:cp-d:`0014`| |:js-d:`0014`|:py-d:`0014`|:rs-d:`0014`|
|:prob:`14` |:c-d:`0014` |:cp-d:`0014`|:cs-d:`0014`|:js-d:`0014`|:py-d:`0014`|:rs-d:`0014`|
+-----------+------------+------------+------------+------------+------------+------------+
|:prob:`15` |:c-d:`0015` |:cp-d:`0015`| | |:py-d:`0015`|:rs-d:`0015`|
|:prob:`15` |:c-d:`0015` |:cp-d:`0015`|:cs-d:`0015`| |:py-d:`0015`|:rs-d:`0015`|
+-----------+------------+------------+------------+------------+------------+------------+
|:prob:`16` |:c-d:`0016` | | | |:py-d:`0016`| |
+-----------+------------+------------+------------+------------+------------+------------+
Expand Down

0 comments on commit a0cf4ad

Please sign in to comment.