I'm having some trouble with this problem in Project Euler.
Here's what the question asks:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Find the sum of all the even-valued terms in the sequence which do not exceed four million.
My code so far: EDITED WITH NEW CODE THAT STILL DOESN'T WORK.
static void Main(string[] args)
{
int a = 1;
int b = 2;
int Container = 0;
int Sum = 0;
while (b < 4000000)
{
if (a % 2 == 0)
{
Container += a;
}
Sum = a + b;
a = b;
b = Sum;
}
Container += b;
Console.WriteLine(Container.ToString());
Console.ReadLine();
}
One of the fun feature in C# is the "yield" keyword, which is very useful for this kind of thing:
IEnumerable<int> Fibonacci()
{
int n1 = 0;
int n2 = 1;
yield return 1;
while (true)
{
int n = n1 + n2;
n1 = n2;
n2 = n;
yield return n;
}
}
long result=0;
foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i => i % 2 == 0))
{
result+=i;
}
Console.WriteLine(result);
The "traditional" recursive Fibonacci implementation is problematic here because it throws away all the work done along the way to the last requested term. You would have to call such a function over and over in a loop, which would duplicate a lot of work, or you could start with that implementation and add an argument to the recursive function to build up the desired sum result as the final fibonacci term is calculated. I like this much better, because it's still a general purpose fibonacci sequence at the core, rather than one you had to re-write or specialize.
Another approach is to use events (delegates) in a traditional implementation to call a separate method as each term is completed, but as I still like the iterator method better I'll leave the delegate option as an exercise for the reader.
Your problem is not that your code contains a bug; your problem is that your code contains a bug and you don't know how to find it. Solve the second problem first, and then you won't need to ask us when you have a bug, you'll be able to find it yourself.
Learning how to find bugs is hard and takes a lot of practice. Here's how I would approach this problem.
I'd start by simplifying the problem down to something I could do myself. Instead of "what's the sum of the even fib numbers that do not exceed four million?" I'd ask "what's the sum of the even fib numbers that do not exceed 40?" That's easy to work out by hand -- 2 + 8 + 34 = 44.
Now run your program in a debugger, stepping through each line, and see where things go wrong. Does your program actually add up 2, 8 and 34? And if so, does it get the correct result?
int sum = 2;
for(int f1 = 1, f2 = 2, f3 = 0; !((f3 = (f1 + f2)) > 4000000); f1 = f2, f2 = f3)
sum += f3 * (~f3 & 1);
I think the question is written to say that you would add all the even numbers together while the numbers in the sequence don't exceed four million, meaning you would add 3,999,992.
You're checking both a and b on every iteration. So that means you're double counting almost everything.
Edit:
Ok, I see your update. This is pretty basic debugging, and you should really learn to try it yourself. Think about what the values of a and b are when your loop condition stops being true.
Joel, I wrote a very some similiar code; I'm posting it anyways:
static IEnumerable<int> Fibonacci(int maximum)
{
int auxiliar = 0;
int previous = 0;
int current = 1;
while (current < maximum)
{
auxiliar = previous;
previous = current;
current = auxiliar + current;
yield return current;
}
}
Console.WriteLine(Fibonacci(4000000).Where(number => number % 2 == 0).Sum());
The trickier way:
//1: Allow declaring of recursive functions
private delegate Func<T, R> FuncRec<T, R>(FuncRec<T, R> f);
static Func<T, R> RecFunction<T, R>(Func<Func<T, R>, Func<T, R>> f)
{
FuncRec<T, R> funcRec = r => t => f(r(r))(t);
return funcRec(funcRec);
}
//Define the factorial function
public static readonly Func<ulong, ulong> Fibonacci
= RecFunction<UInt64, UInt64>(fib => n =>
(n == 1 || n == 0)
? n
: fib(n - 1) + fib(n - 2));
//Make a "continous" version
static IEnumerable<ulong> ContinousFibonacci()
{
ulong count = 0;
while(true)
{
ulong n = Fibonacci(count);
count++;
yield return n;
}
}
//Linq result
static void Main(string[] args)
{
ulong result = ContinousFibonacci()
.TakeWhile(r => r < 4000000)
.Where(IsEven)
.Aggregate<ulong, ulong>(0,(current, s) => (s + current));
Console.WriteLine(result);
Console.ReadLine();
}
///The Functional-Style method of allowing one to create recursive functions such as above was made by Bart De Smet. See http://bartdesmet.net/blogs/bart/archive/2009/11/08/jumping-the-trampoline-in-c-stack-friendly-recursion.aspx
Here's a nice way to find Fibonnaci numbers.
IEnumerable<BigInteger> Fibs()
{
for(BigInteger a = 0,b = 1;;b = a + (a = b))
yield return b;
}
// count(user input) of Fibonacci numbers
int[] array = new int[20];
array[0] = 0;
array[1] = 1;
Console.WriteLine(array[0] + "\n" + array[1]);
for (int i = 2; i < 20; i++)
{
array[i] = array[i - 1] + array[i - 2];
Console.WriteLine(array[i]);
}
Related
I am fairly new to C# and I am currently working on some problems to help build my skills.
Question:
Given two integers a and b, which can be positive or negative, find the sum of all the numbers between including them too and return it. If the two numbers are equal, return a or b.
My code:
using System;
public class Sum
{
public int GetSum(int a, int b)
{
var list;
list.AddRange(Enumerable.range(a,b));
for(var i=0; i <= list.length; i++);
var sum;
sum = sum + i;
return sum;
}
}
Also, if I'm doing a bad practice let me know.
If you're not required to use a loop, I'd probably use Gauß:
The sum of all integers from 1 to n is n*(n+1)/2.
The sum of all integers between a and b is equal to the sum of all integers from 1 to b minus the sum of all integers from 1 to a-1.
That said, the formula is
public static int GetSum(int a, int b) {
return (b*(b+1) - (a-1)*a) / 2;
}
Edit: this formula assumes a < b. If necessary, perform a check and throw an exception, or swap variables if you are alright with saying "the sum of all integers from 11 to 10 is 21":
public static int GetSum(int a, int b) {
if (a < b) {
return (b*(b+1) - (a-1)*a) / 2;
} else if (a == b) {
return a;
} else {
throw new ArgumentException($"{nameof(a)} must be less than or equal to {nameof(b)}.").
}
}
Instead of the traditional for loop solution, you can use (firstNumber + lastNumber)*totalNumbers/2 formula to get the sum of every number between two ranges.
public static int GetSumBetweenTwoRanges(int firstNumber, int lastNumber){
return (firstNumber + lastNumber)*totalNumbers/2;
}
public int GetSum(int a, int b)
{
return Enumerable.Range(a, b-a+1).Sum();
}
which is essentially doing the same as
public int GetSum2(int a, int b)
{
int sum = 0;
foreach (var element in Enumerable.Range(a, b - a + 1))
{
sum += element;
}
return sum;
}
Tips
With 2 methods:
CreatedData from 2 args
Do work
private IEnumerable<int> CreateData(int a,int b)
{
// Get min and max to loop
int min= 0, max= 0;
if (a < b)
{
min = a;
max = b;
}
else if (b < a)
{
min = b;
max = a;
}
for (int i = min; i <= max; i++)
{
yield return i;
}
}
private int CalcSum(int a, int b) // Your target
{
List<int> lst = CreateData(a, b).ToList();
if (lst.Count == 1) // This means: a = b
return a;
return lst.Sum();
}
I think the idea here is to break down the problem and write some code to resolve it.
In order to determine all the numbers within a range - we first must determine the range boundaries. In English we would describe it as:
Given two numbers a and b assert which the largest(upperBound) and the lowest(lowerBound).
Loop from the lowest to the largest(inclusive) and add all the values.
If a and b are equal return either.
By using my description above I would translate from English into code Eg:
Please note I have put the equality check prior anything else. As per return early optimization, if indeed they are equal, why bother doing any other check - just return a or b.
if (a == b)
{
//they are the same so it doesnt matter which one we return
return a;
}
if (a < b)
{
lowerBound = a;
upperBound = b;
}
else if (a > b)
{
lowerBound = b;
upperBound = a;
}
Now that we know their state we can describe the code the loop as:
//loop from lower to upper bound inclusive
for (int i = lowerBound; i <= upperBound; i++)
Please note the i <= upperBound less or equal too will enforce that the upper bound is included in the sum.
Putting it all together we have the following:
public static int GetSum(int a, int b)
{
int result = 0;
int lowerBound = 0;
int upperBound = 0;
if (a == b)
{
//they are the same so it doesnt matter which one we return
return a;
}
if (a < b)
{
lowerBound = a;
upperBound = b;
}
else if (a > b)
{
lowerBound = b;
upperBound = a;
}
//loop from lower to upper bound inclusive
for (int i = lowerBound; i <= upperBound; i++)
{
result += i;
}
return result;
}
static void Main(string[] args)
{
Console.WriteLine(GetSum(5, -7));
Console.ReadLine();
}
In the above example the code return -13 = (-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5)
Many solutions can be adopted here in order to resolve, what I have tried to expose here is the capability to think of a design/solution before writing any actual code.
In time that will come as a second nature to any developer.
Your code does not compile. This being said, let me analyse your code:
C# is case sensitive. Therefore you must write Enumerable.Range, not Enumerable.range.
The second parameter of Enumerable.Range is a count, not the upper limit. So you would have to write
Enumerable.Range(a, b - a + 1)
You add this range to a list. This is not necessary. You could directly loop over this range with
foreach (int i in Enumerable.Range(a, b - a + 1)) { ... }
You don't initialize the list. You should write
var list = new List<int>();
List has no length property. It has a Count property. (An array would have a Length property.)
A list index goes from 0 to list.Count - 1! This means that you should write i < list.Count (not <=) in the for-loop.
It is not necessary to use a list or an Enumerable.Range at all. Simply write
for (int i = a; i <= b; i++) { ... }
and sum up i directly.
In the for loop, you write var i=0;. This is not wrong; however, the var keyword has been introduced to avoid writing complex type names twice as in List<string[]> words = new List<string[]>();. You can write var words = new List<string[]>();. You must use var when you create anonymous types like in var a = new { Name = "Test", Count = 5 };, because this type has no name in C#. For an int type I simply would write int instead of var. In fact it is a good practice to do this for all primitive types like int, string, bool etc.
Your loop is empty, because you terminated it with a semicolon (;). for only considers the next statement as being part of the loop body. That would be var sum; if you dropped this ;. Drop this ; and instead enclose all the statements of the loop body in curly braces { }. This is called a compound statement. return sum; comes after the right curly brace.
var sum; does not compile, as C# cannot infer the type of the variable (the same is true for var list;). Either write int sum; or var sum = 0 to let C# infer the type from the initialization expression (= 0).
sum is not initialized. In C#, local variables are not automatically initialized.
sum must be declared and initialized before the loop, otherwise it will be initialized to its initial value at each loop, instead of retaining the sum calculated so far. Also, its scope will be limited to the loop body and not be visible in the return statement. Before the loop write: int sum = 0;.
You are summing up the loop variable i instead of the intended value at this list position. If still using this list, you would have to write sum = sum + list[i];, which you can simplify to sum += list[i];.
This is my suggestion for a GetSum method:
public int GetSum(int a, int b)
{
int sum = 0;
for (int i = a; i <= b; i++) {
sum += i;
}
return sum;
}
Is it a bad practice to sum up the numbers like this?
You are learning C# and therefore it is a good practice to write algorithms like this one. It also works well for small ranges and is easy to understand. You could also print the intermediate results.
If, however, you need to sum up large ranges, this algorithm does not scale well, as it will spend a lot of time in the loop. In this case, better use the formula described by #LWChris. Disadvantage: it requires some math knowledge.
public static int GetSum(int a, int b)
{
return (b * (b + 1) - (a - 1) * a) / 2;
}
Enumerable.range(a,b) just adds a second, entirely unessesary loop to the whole job. So you can skip that.
And acutally it seems to run counter to your stated goal. Stated Goal is to sume up everything between a and b. But range produces a and all numbers up to a+b+1. It does not what you expected it to do.
The real solution seems rather simple, atually:
public int GetSum(int a, int b)
{
if(a == b)
return a;
int sum = 0;
for(int i = a; i <=b; i++){
sum = sum + i;
}
return sum;
}
As usual, off-by-one-errors are reserved.
As for your code, you got two mistakes:
Your forloop does nothing, because you added a semicolon: for(var i=0; i <= list.length; i++);
Even if it did anything, the sum only exists inside the loop.
{
var sum;
sum = sum + i;
}
return sum;
It must be defined outside of it.
You also did not define the case if a is larger then b.
I am writing the algorithm which is choosing a subset (of k elements) from a set (of n elements).
I have accomplished the task with a success. It works fine for small numbers.
I have tested it for n=6, k=3 and n=10, k=5.
The problem is starting now, when I need to use it for huge numbers.
Sometimes I would need to use it for let's say n = 96000000 and k = 3000.
To simply testing a bit, lets focus on example for n = 786432 and k = 1000. Then there is 461946653375201 such a possibilities. As the third parameters to my function there is rank number, so the number for particular unique subset. Let's try few random, for example 3264832 works fine (gave me subset of different numbers), but for 4619466533201 the one number (in subset) is repeated several times, what is wrong. It must be set as well subset based on unique numbers !
Question is to make it works correct and what is the problem ? The numbers are too big even for ulong ?
If you have any question feel free to ask.
Here is my code:
public static ulong BinomialCoefficient(ulong N, ulong K)
{
ulong result = 1;
for (ulong i = 1; i <= K; i++)
{
result *= N - (K - i);
result /= i;
}
return result;
}
public static ulong[] ChooseSubsetByRank(ulong sizeOfSet, ulong sizeOfSubset, ulong rank)
{
ulong[] resultingSubset = new ulong[sizeOfSubset];
ulong x = sizeOfSet;
for (ulong i = sizeOfSubset; i > 0; i--)
{
while (BinomialCoefficient(x, i) > rank)
x--;
resultingSubset[i - 1] = x + 1;
rank = BinomialCoefficient(x + 1, i) - rank - 1;
}
return resultingSubset;
}
And below is the run code. To test it you may change the third argument at the line below.
ulong[] arrayTest = Logic.ChooseSubsetByRank(786432, 1000, 4619466533201);
string test = "";
for (int i = 0; i < arrayTest.Length; i++)
test = test + arrayTest[i].ToString() + " ";
System.Windows.MessageBox.Show(" " + test);
No hope. You can not.
As says spender: use BigInteger.
Your calculation is false (probably if you calculate with ulong which is very very limited for this).
C786432,1000 is in reality :
6033573926325594551531868873570215053708823770889227136141180206574788891075585715726697576999866930083212017993760483485644855730323214507786127283118515758667219335061769573572969492263411636472559059114372691043787225874459276616360823293108500929182830806831624098080982165637186175635880811026388564912224747148201420203796293941118006753515861022396665706095036252893420240334110487119413634294555065166398219767688578556791918697815341165100213662715943043737412038535358818942960435634721564898425752479874494445989953267768476995289375942620219089503401832797819758809124329657724691573254079810257990856068363592549560111914326820802223343980843357174727643299789438961341403866942005159819587812937265119974334351031505150775547311257835039161258554849609865661574816771511161168033768782419369241858323336341530982042093999410402417064838718686064312965836862249598770142918659708106482935266574067985412321680292750817019104479650736141502332606724302400412461373311881584020963297279437835819666355490804970115983436645628460688679416826680621378132834857452816232982148238532837600398378710514758276529410600324271797090502818444825427753513255984828515472462706714900697194261105881768124169338072607942675219899630246822298950117323544399023453603528517829390771915103036173961755955159422806483076370762068538902803552244794986362728794573306025683866038470793703513935653987744702277137020842862116544300481688519625708115843299275718747596961899491910480897148955406962985269341341630460910287516984534632412940751629513018144947978952932944251585462754004392953272268819217751573575925319332190435744062763990089885732157684342450873180307735549083984647582210698121884513785762578827079077499321224628231353083451055184483182777799031632857810808269286112679457384588431986459863394440578400765094557059628627207887510198427517980206661794055812198263391603552022883118047415972254211592143706127815985486692600870607976623561998434373091244295356784708997235625422777415209304056464924341151878262503587256198384142718049855042621519149038523177569828231641690393173865902883254477356340730939905543154540746759842093744184723706019384873683467974667731206411977863548104488741332797192887789005759777716153901423692511142309333333044144404295842596379993363263619514077277847401673508888691303190564956937240904605718333403477875735125913053605250218671009674129773564325959311930556006735185907557691220793718745513911096043358579428288852312401862707347174079157233572972231584221683511928548130771207729971476262436947167805862489722247791944393249804177227081889352572247647101767728277149206844417712380170809760442471306983505977784517425621794122861839031329562074224252476256692950187473655698688314932344304325068076491419731413851641058957149245827761363536463550636030779009703117216843500031930755136735771022162481784531500378393390581558695370099627488825651248884473844195719258621451229987520317542943566297340698028466818937335976792343382788134518740623993664131802576690485505420542865842569675333314900726976825951448445467650748963731221593412649796639395685018463040431779020656159571608044184646177251839940386267422657877801967082672251079906237183824765375906939480520508656199566649638083679757430680818796170362008227564859519761936618260089868694546582873807181452115865272320
I ran across this problem here on stackoverflow:
"I'm having some trouble with this problem in Project Euler.
Here's what the question asks:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... Find the sum of all the even-valued terms in the sequence which do not exceed four million."
The top answer was this(which does not compile for me in VS2010...why?):
IEnumerable<int> Fibonacci()
{
int n1 = 0;
int n2 = 1;
yield return 1;
while (true)
{
int n = n1 + n2;
n1 = n2;
n2 = n;
yield return n;
}
}
long result=0;
foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i % 2 == 0))
{
result+=i;
}
Console.WriteLine(result);
I decided to try it for myself before looking for an answer and came up with this(please tell me why or why not this is a good or bad way of solving this problem):
I wrote it in a class because I could add much more to the class in the future than just solving a single Fibonacci problem.
class Fibonacci
{
private int prevNum1 = 1;
private int prevNum2 = 2;
private int sum = 0;
public int GetSum(int min, int max)
{
prevNum1 = min;
prevNum2 = prevNum1 + prevNum1;
if (prevNum1 % 2 == 0)
{
sum += prevNum1;
}
if (prevNum2 % 2 == 0)
{
sum += prevNum2;
}
int fNum = 0;
while (prevNum2 <= max)
{
fNum = prevNum1 + prevNum2;
if (fNum % 2 == 0)
{
//is an even number...add to total
sum += fNum;
}
prevNum1 = prevNum2;
prevNum2 = fNum;
}
return sum;
}
}
Fibonacci Fib = new Fibonacci();
int sum = Fib.GetSum(1, 4000000);
Console.WriteLine("Sum of all even Fibonacci numbers 1-4,000,000 = {0}", sum);
Again, I'm looking for an answer as to why this is a good or bad way to solve this problem. Also why the first solution does not compile. I'm a beginning programmer and trying to learn. Thanks!
With this it must compile:
foreach (int i in Fibonacci().TakeWhile(i => i < 4000000).Where(i => i % 2 == 0))
{
result += i;
}
The problem why the code didn't compile was bad lambda expression, it was:
.Where(i % 2 == 0)
but must be
.Where(i => i % 2 == 0)
The code doesn't compile because of this line:
foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i % 2 == 0))
First of all, .Where() is an extension method (google it) that can be called over a collection (like an IEnumerable of integers in this example). It returns another collection containing any elements that satisfy some condition.
Notice the argument to .Where() is an expression producing a boolean value, true or false..
i % 2 == 0
.Where() does not take a bool as an argument, in this case the appropriate argument is of the type
Func<int,bool>
Which basically means a function that has an int as argument and returns bool. You can define these quite simply
// defines a function taking an int, returning true if that int is even
Func<int,bool> foo = i => i % 2 == 0
So the correct way to use .Where() in this case would be
foreach (int i in Fibonacci().TakeWhile(i => i<4000000).Where(i => i % 2 == 0))
So you can see that .Where() takes the function we supply it and applies it to each number, returning a collection of numbers that are even.
There's some other magic happening with the yield keyword, feel free to google this, but it's more of an advanced topic.
I'm quite new to programming in C#, and thought that attempting the Euler Problems would be a good idea as a starting foundation. However, I have gotten to a point where I can't seem to get the correct answer for Problem 2.
"Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms."
My code is this:
int i = 1;
int j = 2;
int sum = 0;
while (i < 4000000)
{
if (i < j)
{
i += j;
if (i % 2 == 0)
{
sum += i;
}
}
else
{
j += i;
if (j % 2 == 0)
{
sum += j;
}
}
}
MessageBox.Show("The answer is " + sum);
Basically, I think that I am only getting the last two even numbers of the sequence and adding them - but I don't know how to get all of the even numbers of the sequence and add them. Could someone please help me, whilst trying to progress from my starting point?
P.S. - If there are any really bad layout choices, do say as eliminating these now will help me to become a better programmer in the future :)
Thanks a lot in advance.
I just logged in into my Project Euler account, to see the correct answer. As others say, you forgot to add the initial term 2, but otherwise your code is OK (the correct answer is what your code outputs + 2), so well done!
It is pretty confusing though, I think it would look way clearer if you'd use 3 variables, something like:
int first = 1;
int second = 1;
int newTerm = 0;
int sum = 0;
while (newTerm <= 4000000)
{
newTerm = first + second;
if (newTerm % 2 == 0)
{
sum += newTerm;
}
first = second;
second = newTerm;
}
MessageBox.Show("The answer is " + sum);
You need to set the initial value of sum to 2, as you are not including that in your sum with the current code.
Also, although it may be less efficient memory-usage-wise, I would probably write the code something like this because IMO it's much more readable:
var fibonacci = new List<int>();
fibonacci.Add(1);
fibonacci.Add(2);
var curIndex = 1;
while(fibonacci[curIndex] + fibonacci[curIndex - 1] <= 4000000) {
fibonacci.Add(fibonacci[curIndex] + fibonacci[curIndex - 1]);
curIndex++;
}
var sum = fibonacci.Where(x => x % 2 == 0).Sum();
Use an array fib to store the sequence. Its easier to code and debug. At every iteration, you just need to check if the value is even.
fib[i] = fib[i - 1] + fib[i - 2];
if (fib[i] > 4000000) break;
if (fib[i] % 2 == 0) sum += fib[i];
I've solved this a few years ago, so I don't remember how I did it exactly, but I do have access to the forums talking about it. A few hints and an outright solution. The numbers repeat in a pattern. two odds followed by an even. So you could skip numbers without necessarily doing the modulus operation.
A proposed C# solution is
long sum = 0, i0, i1 = 1, i2 = 2;
do
{
sum += i2;
for (int i = 0; i < 3; i++)
{
i0 = i1;
i1 = i2;
i2 = i1 + i0;
}
} while (i2 < 4000000);
Your code is a bit ugly, since you're alternating between i and j. There is a much easier way to calculate fibonacci numbers by using three variables and keeping their meaning the same all the time.
One related bug is that you only check the end condition on every second iteration and in the wrong place. But you are lucky that the cutoff fit your bug(the number that went over the limit was odd), so this is not your problem.
Another bug is that you check with < instead of <=, but since there is no fibonacci number equal to the cutoff this doesn't cause your problem.
It's not an int overflow either.
What remains is that you forgot to look at the first two elements of the sequence. Only one of which is even, so you need to add 2 to your result.
int sum = 0; => int sum = 2;
Personally I'd write one function that returns the infinite fibonacci sequence and then filter and sum with Linq. Fibonacci().TakeWhile(i=> i<=4000000).Where(i=>i%2==0).Sum()
I used a class to represent a FibonacciNumber, which i think makes the code more readable.
public class FibonacciNumber
{
private readonly int first;
private readonly int second;
public FibonacciNumber()
{
this.first = 0;
this.second = 1;
}
private FibonacciNumber(int first, int second)
{
this.first = first;
this.second = second;
}
public int Number
{
get { return first + second; }
}
public FibonacciNumber Next
{
get
{
return new FibonacciNumber(this.second, this.Number);
}
}
public bool IsMultipleOf2
{
get { return (this.Number % 2 == 0); }
}
}
Perhaps it's a step too far but the end result is a function which reads quite nicely IMHO:
var current = new FibonacciNumber();
var result = 0;
while (current.Number <= max)
{
if (current.IsMultipleOf2)
result += current.Number;
current = current.Next;
}
return result;
However it's not going to be as efficient as the other solutions which aren't newing up classes in a while loop. Depends on your requirements I guess, for me I just wanted to solve the problem and move on to the next one.
Hi i have solved this question, check it if its right.
My code is,
#include<iostream.h>
#include<conio.h>
class euler2
{
unsigned long long int a;
public:
void evensum();
};
void euler2::evensum()
{
a=4000000;
unsigned long long int i;
unsigned long long int u;
unsigned long long int initial=0;
unsigned long long int initial1=1;
unsigned long long int sum=0;
for(i=1;i<=a;i++)
{
u=initial+initial1;
initial=initial1;
initial1=u;
if(u%2==0)
{
sum=sum+u;
}
}
cout<<"sum of even fibonacci numbers upto 400000 is"<<sum;
}
void main()
{
euler2 a;
clrscr();
a.evensum();
getch();
}
Here's my implementation:
public static int evenFibonachi(int n)
{
int EvenSum = 2, firstElem = 1, SecondElem = 2, SumElem=0;
while (SumElem <= n)
{
swich(ref firstElem, ref SecondElem, ref SumElem);
if (SumElem % 2 == 0)
EvenSum += SumElem;
}
return EvenSum;
}
private static void swich(ref int firstElem, ref int secondElem, ref int SumElem)
{
int temp = firstElem;
firstElem = secondElem;
secondElem += temp;
SumElem = firstElem + secondElem;
}
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.)