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.
Related
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
When running the following code I end up getting negative values. I am only using positive numbers so I am really confused. I have tried to see if this negative number was a return code but there dose not seem to be any codes that return this as a number.
public static int fib(int n)
{
int a = 0;
int b = 1;
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = temp + b;
}
return b;
}
static void Main(string[] args)
{
int n = 0;
bool Run = true;
while (Run == true)
{
n = fib(n + 1);
Console.WriteLine(n);
}
}
Here are the results when the code is run:
1
2
3
5
13
610
-121099088
1
You're just seeing integer overflow. You're trying to compute fib(610) which is way more than an Int32 can hold - and when you add two large integers together, you'll get a negative number.
If you build it in "checked" mode, an exception will be thrown instead - or you can do it just for the one expression you need:
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = checked(temp + b);
}
See MSDN for more on checked arithmetic.
This is the result of an integer overflow and the use of twos' complement to represent integers.
In C#, the default is not to check for integer overflows. If you do change to a checked context, you will get an exception.
Either use a checked context, use uint or even ulong - you need to ensure you are using a data type that can hold the values you are calculating.
Your code is computing the 'nth' Fibonacci number, but it's getting it's 'n' from the previous calculation. My guess is that the 610th Fibonacci number is overflowing int. Use unsigned uint or ulong if you want to continue using this logic. Otherwise, you need to modify how you're determining 'n' for your Fibonacci calculation.
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;
}
The method should work like Math.Max(), but take 3 or more int parameters.
You could use Enumerable.Max:
new [] { 1, 2, 3 }.Max();
Well, you can just call it twice:
int max3 = Math.Max(x, Math.Max(y, z));
If you find yourself doing this a lot, you could always write your own helper method... I would be happy enough seeing this in my code base once, but not regularly.
(Note that this is likely to be more efficient than Andrew's LINQ-based answer - but obviously the more elements you have the more appealing the LINQ approach is.)
EDIT: A "best of both worlds" approach might be to have a custom set of methods either way:
public static class MoreMath
{
// This method only exists for consistency, so you can *always* call
// MoreMath.Max instead of alternating between MoreMath.Max and Math.Max
// depending on your argument count.
public static int Max(int x, int y)
{
return Math.Max(x, y);
}
public static int Max(int x, int y, int z)
{
// Or inline it as x < y ? (y < z ? z : y) : (x < z ? z : x);
// Time it before micro-optimizing though!
return Math.Max(x, Math.Max(y, z));
}
public static int Max(int w, int x, int y, int z)
{
return Math.Max(w, Math.Max(x, Math.Max(y, z)));
}
public static int Max(params int[] values)
{
return Enumerable.Max(values);
}
}
That way you can write MoreMath.Max(1, 2, 3) or MoreMath.Max(1, 2, 3, 4) without the overhead of array creation, but still write MoreMath.Max(1, 2, 3, 4, 5, 6) for nice readable and consistent code when you don't mind the overhead.
I personally find that more readable than the explicit array creation of the LINQ approach.
Linq has a Max function.
If you have an IEnumerable<int> you can call this directly, but if you require these in separate parameters you could create a function like this:
using System.Linq;
...
static int Max(params int[] numbers)
{
return numbers.Max();
}
Then you could call it like this: max(1, 6, 2), it allows for an arbitrary number of parameters.
As generic
public static T Min<T>(params T[] values) {
return values.Min();
}
public static T Max<T>(params T[] values) {
return values.Max();
}
off topic but here is the formula for middle value.. just in case someone is looking for it
Math.Min(Math.Min(Math.Max(x,y), Math.Max(y,z)), Math.Max(x,z));
Let's assume that You have a List<int> intList = new List<int>{1,2,3} if You want to get a max value You could do
int maxValue = intList.Max();
Maximum element value in priceValues[] is maxPriceValues :
double[] priceValues = new double[3];
priceValues [0] = 1;
priceValues [1] = 2;
priceValues [2] = 3;
double maxPriceValues = priceValues.Max();
If, for whatever reason (e.g. Space Engineers API), System.array has no definition for Max nor do you have access to Enumerable, a solution for Max of n values is:
public int Max(int[] values) {
if(values.Length < 1) {
return 0;
}
if(values.Length < 2) {
return values[0];
}
if(values.Length < 3) {
return Math.Max(values[0], values[1]);
}
int runningMax = values[0];
for(int i=1; i<values.Length - 1; i++) {
runningMax = Math.Max(runningMax, values[i]);
}
return runningMax;
}
You could try this code:
private float GetBrightestColor(float r, float g, float b) {
if (r > g && r > b) {
return r;
} else if (g > r && g > b) {
return g;
} else if (b > r && b > g) {
return b;
}
}
This function takes an array of integers. (I completely understand #Jon Skeet's complaint about sending arrays.)
It's probably a bit overkill.
public static int GetMax(int[] array) // must be a array of ints
{
int current_greatest_value = array[0]; // initializes it
for (int i = 1; i <= array.Length; i++)
{
// compare current number against next number
if (i+1 <= array.Length-1) // prevent "index outside bounds of array" error below with array[i+1]
{
// array[i+1] exists
if (array[i] < array[i+1] || array[i] <= current_greatest_value)
{
// current val is less than next, and less than the current greatest val, so go to next iteration
continue;
}
} else
{
// array[i+1] doesn't exist, we are at the last element
if (array[i] > current_greatest_value)
{
// current iteration val is greater than current_greatest_value
current_greatest_value = array[i];
}
break; // next for loop i index will be invalid
}
// if it gets here, current val is greater than next, so for now assign that value to greatest_value
current_greatest_value = array[i];
}
return current_greatest_value;
}
Then call the function :
int highest_val = GetMax (new[] { 1,6,2,72727275,2323});
// highest_val = 72727275
You can use if and else if method for three values but it would be much easier if you call call twice Math.Max method like this
Console.WriteLine("Largest of three: " + Math.Max(num1, Math.Max(num2, num3)));
Console.WriteLine("Lowest of three: " + Math.Min(num1, Math.Min(num2, num3)));
If you don't want to repeatedly calling the Max function, can do like this
new List<int>() { A, B, C, D, X, Y, Z }.Max()
in case you need sorting as well:
var side = new double[] {5,3,4}
Array.Sort(side);
//side[2] is a maximum
as an another variant:
T[] GetMax<T>(int number, List<T> source, T minVal)
{
T[] results = new T[number];
for (int i = 0; i < number; i++)
{
results[i] = minVal;
}
var curMin = minVal;
foreach (var e in source)
{
int resComp = Comparer.DefaultInvariant.Compare(curMin, e);
if (resComp < 0)
{
int minIndex = Array.IndexOf(results, curMin);
results[minIndex] = e;
curMin = results.Min();
}
}
return results;
}
var source = new int[] { 5, 5, 1, 2, 4, 3 }.ToList();
var result = GetMax(3, source, int.MinValue);
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]);
}