I was solving Project Euler problem 10 and I was able to do so using the Sieve of Eratosthenes, but now I'd like to optimize the code a bit further.
Considering the fact that all prime numbers greater than 3 are of the form 6k+1 or 6k-1 I only set those values in the array as true, but not all numbers of that form will be prime, so I have to sieve through the values and remove the non primes, and my code is as follows:
public static bool[] GeneratePrimes(int bound)
{
bool[] isPrime = new bool[bound];
isPrime[2] = true;
isPrime[3] = true;
// Taking into account that all primes greater than 2 and 3
// Are of the form 6k+1 or 6k-1
for (int k = 6; k < isPrime.Length; k += 6)
{
if (k + 1 < isPrime.Length) isPrime[k + 1] = true;
isPrime[k - 1] = true;
}
// At this point we still have some numbers that aren't prime marked as prime
// So we go over them with a sieve, also we can start at 3 for obvious reasons
for (int i = 3; i * i <= bound; i += 2)
{
if (isPrime[i])
{
// Can this be optimized?
for (int j = i; j * i <= bound; j++)
isPrime[i * j] = false;
}
}
return isPrime;
}
}
So how can I optimize the code that I sieve through less numbers? For example if my number is 5, numbers such as 10,15,20 are already stroked through, but 25 for example isn't so is it possible to only go through values such is 25?
When eliminating multiples of a prime p, you only need to start from p * p. Any multiple of p below that will already have been eliminated as it has a smaller prime factor. This is the reason behind your comments about 5 and 25.
Paul Pritchard has done much work with wheel sieves that extend your 6k±1 idea to larger prime wheels. Google for "pritchard wheel sieve" or look at my blog to get started.
My goal is to implement a (simple) check digit alglorithm as described Here
My implemantion is the following but I am not sure if it is optimal:
private int CheckDigit(string SevenDecimal)
{
///Get UPC check digit of a 7-digit URI
///Add odd and multiply by 3 =Odds
///Add even =Evens
///Add Odds+Evens=sum
///Check digit is the number that makes Sum divisble by 10
int Odds = 0;
int Evens = 0;
int sum = 0;
int index = 0;
foreach (char digit in SevenDecimal)
{
index++;
int Digit = int.Parse(digit.ToString());
if (index % 2 == 0)
{
Evens +=Digit;
}
else
{
Odds +=Digit;
}
}
Odds = Odds * 3;
sum = Odds + Evens;
for (int i = 0; i < 10; i++) ///Brute force way check for better implementation
{
int Localsum;
Localsum = sum + i;
if (Localsum % 10 == 0)
{
return i;
}
}
return -1;//error;
}
My main concern is in the final for loop which as I describe is totallly brute.
Is there a better way to obtaining the check digit?
More precisely which is the best way to solve programmatically, the equation:
(sum+x)%10=0 //solve for x
To find "how much i you have to add to make the last digit of a number a 0", you can subtract from 10:
int checkDigit = (10 - (sum % 10)) % 10;
The second modulo is used for the special case when sum % 10 == 0, because 10 - 0 = 10
You are asking the wrong question. The expression is not one of equivalence thus x is not a value. The solution is that x is an infinite number of values each of which correctly solve the equation. As such you don't really want to solve for x but just check if x is in this solution space. You can check this simply with:
remainder = base - (sum % base)
You can then test if x sums up to the remainder with:
if (x % base === base - (sum % base))
{
// (sum + x) % base = 0 is true
}
Replace base with 10and you'll have it.
I've made a small C# program which calculates prime numbers using the Sieve of Eratosthenes.
long n = 100000;
bool[] p = new bool[n+1];
for(long i=2; i<=n; i++)
{
p[i]=true;
}
for(long i=2; i<=X; i++)
{
for(long j=Y; j<=Z; j++)
{
p[i*j]=false;
}
}
for(long i=0; i<=n; i++)
{
if(p[i])
{
Console.Write(" "+i);
}
}
Console.ReadKey(true);
My question is: which X, Y and Z should I choose to make my program as efficient and economical as possible?
Of course we can just take:
X = n
Y = 2
Z = n
But then the program won't be very efficient.
It seems we can take:
X = Math.Sqrt(n)
Y = i
Z = n/i
And apparently the first 100 primes that the program gives are all correct.
There are several optimisations that can be applied without making the program overly complicated.
you can start the crossing out at j = i (effectively i * i instead of 2 * i) since all lower multiples of i have already been crossed out
you can save some work by leaving all even numbers out of the array (remembering to produce the prime 2 out of thin air when needed); hence array cell k represents the odd integer 2 * k + 1
you can make things faster by turning repeated multiplication (i * j) into iterated addition (k += i); instead of looping over j in the inner loop you loop (k = i * i; k <= N; k += i)
in some cases it can be advantageous to initialise the array with 0 (false) and set cells to 1 (true) for composites; its meaning is thus 'is_composite' instead of 'is_prime'
Harvesting all the low-hanging fruit, the loops thus become (in C++, but C# should be sort of similar):
uint32_t max_factor_bit = uint32_t(sqrt(double(n))) >> 1;
uint32_t max_bit = n >> 1;
for (uint32_t i = 3 >> 1; i <= max_factor_bit; ++i)
{
if (composite[i]) continue;
uint32_t n = (i << 1) + 1;
uint32_t k = (n * n) >> 1;
for ( ; k <= max_bit; k += n)
{
composite[k] = true;
}
}
Regarding the computation of max_factor there are some caveats where the compiler can bite you, for larger values of n. There's a topic for that on Code Review.
A further, easy optimisation is to represent the bitmap as an array of bytes, with each byte standing for eight odd integers. For setting bit k in byte array a you would do a[k / CHAR_BIT] |= (1 << (k % CHAR_BIT)) where CHAR_BIT is the number of bits in a byte. However, such bit trickery is normally wrapped into an inline function to keep the code clean. E.g. in C++ I tell the compiler how to generate such functions using a template like this:
template<typename word_t>
inline
void set_bit (word_t *p, uint32_t index)
{
enum { BITS_PER_WORD = sizeof(word_t) * CHAR_BIT };
// we can trust the compiler to use masking and shifting instead of division; we cannot do that
// ourselves without having the log2 which cannot easily be computed as a constexpr
p[index / BITS_PER_WORD] |= word_t(1) << (index % BITS_PER_WORD);
}
This allows me to say set_bit(a, k) for any type of array - byte, integer, whatever - without having to write special code or use invocations; it's basically a type-safe equivalent to the old C-style macros. I'm not certain whether something similar is possible in C#. There is, however, the C# type BitArray where all that stuff is already done for you under the hood.
On pastebin there's a small demo .cpp for the segmented Sieve of Eratosthenes, where two further optimisations are applied: presieving by small integers, and sieving in small, cache friendly blocks so that the full range of 32-bit integers can be sieved in 2 seconds flat. This could give you some inspiration...
When doing the Sieve of Eratosthenes, memory savings easily translate to speed gains because the algorithm is memory-intensive and it tends to stride all over the memory instead of accessing it locally. That's why space savings due to compact representation (only odd integers, packed bits - i.e. BitArray) and localisation of access (by sieving in small blocks instead of the whole array in one go) can speed up the code by one or more orders of magnitude, without making the code significantly more complicated.
It is possible to go far beyond the easy optimisations mentioned here, but that tends to make the code increasingly complicated. One word that often occurs in this context is the 'wheel', which can save a further 50% of memory space. The wiki has an explanation of wheels here, and in a sense the odds-only sieve is already using a 'modulo 2 wheel'. Conversely, a wheel is the extension of the odds-only idea to dropping further small primes from the array, like 3 and 5 in the famous 'mod 30' wheel with modulus 2 * 3 * 5. That wheel effectively stuffs 30 integers into one 8-bit byte.
Here's a runnable rendition of the above code in C#:
static uint max_factor32 (double n)
{
double r = System.Math.Sqrt(n);
if (r < uint.MaxValue)
{
uint r32 = (uint)r;
return r32 - ((ulong)r32 * r32 > n ? 1u : 0u);
}
return uint.MaxValue;
}
static void sieve32 (System.Collections.BitArray odd_composites)
{
uint max_bit = (uint)odd_composites.Length - 1;
uint max_factor_bit = max_factor32((max_bit << 1) + 1) >> 1;
for (uint i = 3 >> 1; i <= max_factor_bit; ++i)
{
if (odd_composites[(int)i]) continue;
uint p = (i << 1) + 1; // the prime represented by bit i
uint k = (p * p) >> 1; // starting point for striding through the array
for ( ; k <= max_bit; k += p)
{
odd_composites[(int)k] = true;
}
}
}
static int Main (string[] args)
{
int n = 100000000;
System.Console.WriteLine("Hello, Eratosthenes! Sieving up to {0}...", n);
System.Collections.BitArray odd_composites = new System.Collections.BitArray(n >> 1);
sieve32(odd_composites);
uint cnt = 1;
ulong sum = 2;
for (int i = 1; i < odd_composites.Length; ++i)
{
if (odd_composites[i]) continue;
uint prime = ((uint)i << 1) + 1;
cnt += 1;
sum += prime;
}
System.Console.WriteLine("\n{0} primes, sum {1}", cnt, sum);
return 0;
}
This does 10^8 in about a second, but for higher values of n it gets slow. If you want to do faster then you have to employ sieving in small, cache-sized blocks.
I have the following problem (from ProjectEuler.net - Problem 14)
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.
I used:
static int road (int n)
{
int road = 0;
while (n != 1)
{
if (n % 2 == 0)
n = n / 2;
else
n = 3 * n + 1;
road++;
}
return road;
}
static void Main(string[] args)
{
int max = 0, num = 0;
for (int i = 1; i < 1000000; i++)
{
if (road(i) > max)
{
max = road(i);
num = i;
}
}
Console.WriteLine(num);
}
But no output is printed.
(I'm not going to give you a complete solution since Project Euler is intended to make you think, not us who already solved the problems.)
Try figuring out how large the values in your chain are going to be and keep in mind the limits for integral types.
function problem14(){
function r(p,n){
return cl(p)>cl(n)?p:n;
}
function c(n){
return n%2===0?n/2:3*n+1;
}
function cl(n){
var _a = 1;
var _n = n;
while(_n !== 1){
_a++;
_n = c(_n);
}
return _a;
}
var b = [];
var m = 20;
var i = 500000;
while(i < 1000000){
var _n = cl(i);
if(_n>m){
b.push(i);
m = _n;
}
i++;
}
return b.reduce(r);
}
Here is my js code.
It is not that "nothing is output", it is just running very long. If you change the upper bound of the for-loop to 100000, you will see that pretty quickly you get output. The reason it runs very long is that you use unchecked integers and you don't get an overflowexception where you should want one. Break after a few seconds an you'll see a negative n.
Try the following , i.e. with the checked keyword, it will illustrate what I mean:
// will now throw OverflowException with large n
checked
{
int road = 0;
while (n != 1)
{
if (n%2 == 0)
n = n/2;
else
n = 3*n + 1;
road++;
}
return road;
}
First, note that you are calling the road() function twice per iteration, which is a waste of processing time (and for a 'function with side effects', could have unwanted consequences).
Secondly, due to integer overflow, you can't get an answer - the value 113383, for example, ends up cycling around the same 20 or so numbers
-122, -61, -182, -91, -272, -136, -68, -34, -17, -50, -25, -74, -37, -110, -55, ,-164, -82, -41, -122
Oops!
I have been hearing a lot about Project Euler so I thought I solve one of the problems in C#. The problem as stated on the website is as follows:
If we list all the natural numbers
below 10 that are multiples of 3 or 5,
we get 3, 5, 6 and 9. The sum of these
multiples is 23.
Find the sum of all the multiples of 3
or 5 below 1000.
I wrote my code as follows:
class EulerProblem1
{
public static void Main()
{
var totalNum = 1000;
var counter = 1;
var sum = 0;
while (counter < totalNum)
{
if (DivisibleByThreeOrFive(counter))
sum += counter;
counter++;
}
Console.WriteLine("Total Sum: {0}", sum);
Console.ReadKey();
}
private static bool DivisibleByThreeOrFive(int counter)
{
return ((counter % 3 == 0) || (counter % 5 == 0));
}
}
It will be great to get some ideas on alternate implementations with less verbosity/cleaner syntax and better optimizations. The ideas may vary from quick and dirty to bringing out the cannon to annihilate the mosquito. The purpose is to explore the depths of computer science while trying to improve this particularly trivial code snippet.
Thanks
Updated to not double count numbers that are multiples of both 3 and 5:
int EulerProblem(int totalNum)
{
int a = (totalNum-1)/3;
int b = (totalNum-1)/5;
int c = (totalNum-1)/15;
int d = a*(a+1)/2;
int e = b*(b+1)/2;
int f = c*(c+1)/2;
return 3*d + 5*e - 15*f;
}
With LINQ (updated as suggested in comments)
static void Main(string[] args)
{
var total = Enumerable.Range(0,1000)
.Where(counter => (counter%3 == 0) || (counter%5 == 0))
.Sum();
Console.WriteLine(total);
Console.ReadKey();
}
Here's a transliteration of my original F# solution into C#. Edited: It's basically mbeckish's solution as a loop rather than a function (and I remove the double count). I like mbeckish's better.
static int Euler1 ()
{
int sum = 0;
for (int i=3; i<1000; i+=3) sum+=i;
for (int i=5; i<1000; i+=5) sum+=i;
for (int i=15; i<1000; i+=15) sum-=i;
return sum;
}
Here's the original:
let euler1 d0 d1 n =
(seq {d0..d0..n} |> Seq.sum) +
(seq {d1..d1..n} |> Seq.sum) -
(seq {d0*d1..d0*d1..n} |> Seq.sum)
let result = euler1 3 5 (1000-1)
I haven't written any Java in a while, but this should solve it in constant time with little overhead:
public class EulerProblem1
{
private static final int EULER1 = 233168;
// Equal to the sum of all natural numbers less than 1000
// which are multiples of 3 or 5, inclusive.
public static void main(String[] args)
{
System.out.println(EULER1);
}
}
EDIT: Here's a C implementation, if every instruction counts:
#define STDOUT 1
#define OUT_LENGTH 8
int main (int argc, char **argv)
{
const char out[OUT_LENGTH] = "233168\n";
write(STDOUT, out, OUT_LENGTH);
}
Notes:
There's no error handling on the call to write. If true robustness is needed, a more sophisticated error handling strategy must be employed. Whether the added complexity is worth greater reliability depends on the needs of the user.
If you have memory constraints, you may be able to save a byte by using a straight char array rather than a string terminated by a superfluous null character. In practice, however, out would almost certainly be padded to 8 bytes anyway.
Although the declaration of the out variable could be avoided by placing the string inline in the write call, any real compiler willoptimize away the declaration.
The write syscall is used in preference to puts or similar to avoid the additional overhead. Theoretically, you could invoke the system call directly, perhaps saving a few cycles, but this would raise significant portability issues. Your mileage may vary regarding whether this is an acceptable tradeoff.
Refactoring #mbeckish's very clever solution:
public int eulerProblem(int max) {
int t1 = f(max, 3);
int t2 = f(max, 5);
int t3 = f(max, 3 * 5);
return t1 + t2 - t3;
}
private int f(int max, int n) {
int a = (max - 1) / n;
return n * a * (a + 1) / 2;
}
That's basically the same way I did that problem. I know there were other solutions (probably more efficient ones too) on the forums for project-euler.
Once you input your answer going back to the question gives you the option to go to the forum for that problem. You may want to look there!
The code in DivisibleByThreeOrFive would be slightly faster if you would state it as follows:
return ((counter % 3 == 0) || (counter % 5 == 0));
And if you do not want to rely on the compiler to inline the function call, you could do this yourself by putting this code into the Main routine.
You can come up with a closed form solution for this. The trick is to look for patterns. Try listing out the terms in the sum up to say ten, or twenty and then using algebra to group them. By making appropriate substitutions you can generalize that to numbers other than ten. Just be careful about edge cases.
Try this, in C. It's constant time, and there's only one division (two if the compiler doesn't optimize the div/mod, which it should). I'm sure it's possible to make it a bit more obvious, but this should work.
It basically divides the sum into two parts. The greater part (for N >= 15) is a simple quadratic function that divides N into exact blocks of 15. The lesser part is the last bit that doesn't fit into a block. The latter bit is messier, but there are only a few possibilities, so a LUT will solve it in no time.
const unsigned long N = 1000 - 1;
const unsigned long q = N / 15;
const unsigned long r = N % 15;
const unsigned long rc = N - r;
unsigned long sum = ((q * 105 + 15) * q) >> 1;
switch (r) {
case 3 : sum += 3 + 1*rc ; break;
case 4 : sum += 3 + 1*rc ; break;
case 5 : sum += 8 + 2*rc ; break;
case 6 : sum += 14 + 3*rc ; break;
case 7 : sum += 14 + 3*rc ; break;
case 8 : sum += 14 + 3*rc ; break;
case 9 : sum += 23 + 4*rc ; break;
case 10 : sum += 33 + 5*rc ; break;
case 11 : sum += 33 + 5*rc ; break;
case 12 : sum += 45 + 6*rc ; break;
case 13 : sum += 45 + 6*rc ; break;
case 14 : sum += 45 + 6*rc ; break;
}
You can do something like this:
Func<int,int> Euler = total=>
new List<int>() {3,5}
.Select(m => ((int) (total-1) / m) * m * (((int) (total-1) / m) + 1) / 2)
.Aggregate( (T, m) => T+=m);
You still have the double counting problem. I'll think about this a little more.
Edit:
Here is a working (if slightly inelegant) solution in LINQ:
var li = new List<int>() { 3, 5 };
Func<int, int, int> Summation = (total, m) =>
((int) (total-1) / m) * m * (((int) (total-1) / m) + 1) / 2;
Func<int,int> Euler = total=>
li
.Select(m => Summation(total, m))
.Aggregate((T, m) => T+=m)
- Summation(total, li.Aggregate((T, m) => T*=m));
Can any of you guys improve on this?
Explanation:
Remember the summation formula for a linear progression is n(n+1)/2. In the first case where you have multiples of 3,5 < 10, you want Sum(3+6+9,5). Setting total=10, you make a sequence of the integers 1 .. (int) (total-1)/3, and then sum the sequence and multiply by 3. You can easily see that we're just setting n=(int) (total-1)/3, then using the summation formula and multiplying by 3. A little algebra gives us the formula for the Summation functor.
I like technielogys idea, here's my idea of a modification
static int Euler1 ()
{
int sum = 0;
for (int i=3; i<1000; i+=3)
{
if (i % 5 == 0) continue;
sum+=i;
}
for (int i=5; i<1000; i+=5) sum+=i;
return sum;
}
Though also comes to mind is maybe a minor heuristic, does this make any improvement?
static int Euler1 ()
{
int sum = 0;
for (int i=3; i<1000; i+=3)
{
if (i % 5 == 0) continue;
sum+=i;
}
for (int i=5; i<250; i+=5)
{
sum+=i;
}
for (int i=250; i<500; i+=5)
{
sum+=i;
sum+=i*2;
sum+=(i*2)+5;
}
return sum;
}
Your approach is brute force apprach, The time complexity of the following approach is O(1), Here we
are dividing the given (number-1) by 3, 5 and 15, and store in countNumOf3,countNumOf5, countNumOf15.
Now we can say that 3 will make AP, within the range of given (number-1) with difference of 3.
suppose you are given number is 16, then
3=> 3, 6, 9, 12, 15= sum1=>45
5=> 5, 10, 15 sum2=> 30
15=> 15 => sum3=15
Add sum= sum1 and sum2
Here 15 is multiple of 3 and 5 so remove sum3 form sum, this will be your answer. **sum=sum-
sum3** please check link of my solution on http://ideone.com/beXsam]
import java.util.*;
class Multiplesof3And5 {
public static void main(String [] args){
Scanner scan=new Scanner(System.in);
int num=scan.nextInt();
System.out.println(getSum(num));
}
public static long getSum(int n){
int countNumOf3=(n-1)/3;//
int countNumOf5=(n-1)/5;
int countNumOf15=(n-1)/15;
long sum=0;
sum=sumOfAP(3,countNumOf3,3)+sumOfAP(5,countNumOf5,5)-sumOfAP(15,countNumOf15,15);
return sum;
}
public static int sumOfAP(int a, int n, int d){
return (n*(2*a +(n -1)*d))/2;
}
}
new List<int>{3,5}.SelectMany(n =>Enumerable.Range(1,999/n).Select(i=>i*n))
.Distinct()
.Sum()
[Update] (In response to the comment asking to explain this algorothm)
This builds a flattened list of multiples for each base value (3 and 5 in this case), then removes duplicates (e.g where a multiple is divisible, in this case, by 3*5 =15) and then sums the remaining values. (Also this is easily generalisable for having more than two base values IMHO compared to any of the other solutions I have seen here.)