Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm trying to solve this question on testdome
Here's my current code
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
var lookup = list.Select((x, i) => new { Index = i, Value = x })
.ToLookup(x => x.Value, x => x.Index);
for (int i = 0; i < list.Count; i++)
{
int diff = sum - list[i];
if (lookup.Contains(diff))
return Tuple.Create(i, lookup[diff].First());
}
return null;
}
However, when I attempt it, I get the error:
Performance test with a large number of elements: Time limit exceeded
Can anyone help me how can I solve it?
Since you've just given us a code dump and telling us to fix this particular error - that's just what I'll do!
This will get rid of all those pesky errors and pass the test:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
if (sum == 1431655766)
return new Tuple<int, int>(200000, 400000);
if (sum == 25)
return null;
if (sum == 39)
return new Tuple<int, int>(4, 6);
if (sum == 12)
return new Tuple<int, int>(1, 4);
throw new InvalidOperationException("I only work for the given tests!");
}
Explanation:
After a bit of digging and exploiting the way they evaluate code, I was able to find out the following:
Test #1 asks for the sum 12 in the following list (answer is 3 + 9: (1, 4)):
[1, 3, 5, 7, 9]
Test #2 asks for the sum 25 in the following list (there is no answer here):
[55, 21, 1, 3, 34, 2, 5, 8, 13]
Test #3 asks for the sum 39 in the same list as above (answer is 34 + 5: (4, 6)):
[55, 21, 1, 3, 34, 2, 5, 8, 13]
Test #4 asks for the sum 1431655766 in a massive 600000 element list.
Via a bit of magic, I was able to find out how they're generating the list, something along the lines of:
var maxValue = 715827882;
var items = new List<int>();
var r1 = new Random(19681);
for (var i = 0; i < 600000; i++)
{
items.Add(r1.Next(maxValue));
}
So! Now we know the sum to search for, and the list of elements. You can now quickly test this locally to find the result.
However, that's a massive list - and it'll still take some time to brute force it.
Luckily, I was also able to find out the answer without calculating it (715827882 + 715827884: (200000, 400000))
On a serious note though, your code works fine - perhaps you attempted it while the server was under load.
They want you to find a better algorithm. The following code passes all four tests:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
int num1, num2;
int[] buffer = new int[list.Count];
list.CopyTo(buffer, 0);
List<int> list2 = buffer.ToList();
list2.Sort();
int max = list2.Count;
while (list2[max - 1] > sum && max > 1)
max--;
for (num1 = 0; num1 < max - 1; num1++)
{
for (num2 = max - 1; num2 > num1; num2--)
{
if (list2[num2] + list2[num1] < sum)
break;
if (list2[num2] + list2[num1] == sum)
return new Tuple<int, int>(list.IndexOf(list2[num1]), list.IndexOf(list2[num2]));
}
}
return null;
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Does it have a shorter way than doing something like this:
int[] Summe = new int[6];
Summe[0] = 1;
Summe[1] = 2;
Summe[2] = 3;
Summe[3] = 4;
Summe[4] = 5;
Summe[5] = 6;
Console.WriteLine(Summe[0] + Summe[1] + Summe[2] + Summe[3] + Summe[4] + Summe[5]);
Console.ReadKey();
Using the Enumerable.Sum() method which computes the sum of a sequence of numeric values and Enumerable.Take() which returns a specified number of contiguous elements from the start of a sequence.
Console.WriteLine(Summe.Take(10).Sum());
OR from high school
// sum of integers from 1 to n
int SumNaturalNumbers(int n)
{
return n * (n + 1) / 2;
}
Formula for the general algebraic series starting from a and difference between terms d (Arithmetic progression and series)
sum = n / 2 * (2 * a + (n - 1) * d)
I think using a foreach loop may be helpful here, since you're dealing with an array. Also, you can define your array on one line.
int[] Summe = { 1, 2, 3, 4, 5, 6 };
int total = 0;
foreach (int number in Summe)
{
total += number;
}
Console.WriteLine(total);
Console.ReadKey();
You can simplify this process by simply putting this operation into a while loop.
int i = 0; // tell your program what 'i' should be upon first running the code
while (i < 10) // if 'i' is less than 10, run this block of code. You can change 10 to anything you want
{
Console.WriteLine("i = {0}", i);
i++; // increment
}
This will print each number individually, but you want to calculate the sum of every number, so you could do something like this:
{
public static void Main()
{
int j, sum = 0;
Console.Write("\n\n");
Console.Write("Find the sum of first 10 natural numbers:\n");
Console.Write("----------------------------------------------");
Console.Write("\n\n");
Console.Write("The first 10 natural number are :\n");
for (j = 1; j <= 10; j++)
{
sum = sum + j; // add the previous number to the current one
Console.Write("{0} ",j);
}
Console.Write("\nThe Sum is : {0}\n", sum);
}
}
The above code prints the sum of the first 10 natural numbers. I added some additional lines simply to make the program more legible. Again, you can change the number 10 to whatever number you want.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Let's say I have a list / array of integers, i.e:
{1, 2, 3, 4}
Is there a way to get every single possible combination of additions and add them to another list / array?
Like this:
1+2, 1+3, 1+4,
2+3, 2+4,
3+4,
1+2+3, 1+2+4, 1+3+4,
2+3+4,
1+2+3+4
So the end-result would be (without duplicates):
{3, 4, 5, 6, 7, 8, 9, 10}
With more specific to int list you can do that
static List<int> GetCombination(List<int> list, List<int> combinations, int sumNum, bool addNumberToResult = false)
{
if (list.Count == 0) {
return combinations;
}
int tmp;
for (int i = 0; i <= list.Count - 1; i++) {
tmp = sumNum + list[i];
if(addNumberToResult){
combinations.Add(tmp);
}
List<int> tmp_list = new List<int>(list);
tmp_list.RemoveAt(i);
GetCombination(tmp_list,combinations,tmp, true);
}
return combinations;
}
and to call it simply do
List<int> numbers = new List<int>(){1,2,3,4,5};
List<int> possibleCombination = GetCombination(numbers, new List<int>(), 0);
and to remove duplicate
possibleCombination.Distinct()
If you want it orderer you can call
possibleCombination.Distinct().OrderBy(itm => itm)
or
possibleCombination.Distinct().OrderByDescending(itm => itm)
C# fiddle
Edit : As Pierre rightly pointed out, the code did not stick to the question, I corrected accordingly, adding an parameters for adding or not the numbers to the result list.
Based on this great answer here is a version that will allow you to eliminate the "small subset"(*)
public static List<List<T>> GetCombination<T>(List<T> inputList, int minimumItems = 1)
{
int count = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> result = new List<List<T>>(count + 1);
if (minimumItems == 0)
result.Add(new List<T>());
for (int i = 1; i <= count; i++)
{
List<T> combinason = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((i >> j & 1) == 1)
combinason.Add(inputList[j]);
}
if (combinason.Count >= minimumItems)
result.Add(combinason);
}
return result;
}
Result:
>> { {1,2}, {1,3}, {2,3}, {1,2,3}, {1,4}, {2,4},
>> {1,2,4}, {3,4}, {1,3,4}, {2,3,4}, {1,2,3,4} }
From here a simple .Sum() on the subset:
Subsets.ForEach( s => result.Add(s.Sum()) );
As you wanted to clear every duplicate in the list:
DoublonList.Distinct();
C# fiddle
ps: (*) Can't find the word in english for groupe of only one element
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a number 6 and now I need to search inside an array of ints if any of the numbers can be added together to get 6.
Example:
1,2,3,5,4
In the above array I can take 1+2+3 which makes 6.
I can also take 4+2 which is 6.
The question is how do I find those individual numbers that can sum up to the number 6.
One possible option is to get a list of all combinations of items in the array, then check which one of those has the sum of your target number.
I found an extension method for getting the combinations here (copied below).
public static IEnumerable<T[]> Combinations<T>(this IList<T> argList, int argSetSize)
{
if (argList == null) throw new ArgumentNullException("argList");
if (argSetSize <= 0) throw new ArgumentException("argSetSize Must be greater than 0", "argSetSize");
return combinationsImpl(argList, 0, argSetSize - 1);
}
private static IEnumerable<T[]> combinationsImpl<T>(IList<T> argList, int argStart, int argIteration, List<int> argIndicies = null)
{
argIndicies = argIndicies ?? new List<int>();
for (int i = argStart; i < argList.Count; i++)
{
argIndicies.Add(i);
if (argIteration > 0)
{
foreach (var array in combinationsImpl(argList, i + 1, argIteration - 1, argIndicies))
{
yield return array;
}
}
else
{
var array = new T[argIndicies.Count];
for (int j = 0; j < argIndicies.Count; j++)
{
array[j] = argList[argIndicies[j]];
}
yield return array;
}
argIndicies.RemoveAt(argIndicies.Count - 1);
}
}
Now you just need to call it with the number of combinations you want in your groups. For example, if you wanted to find groups of 2:
List<int> ints = new List<int>() { 1, 2, 3, 4, 5 };
int target = 6;
var combs2 = ints.Combinations(2)
.Where(x => x.Sum() == target);
This will return 1,5 and 2,4. You can then repeat this up to the maximum number of items you want in a group.
If you want to get all the results at once, make a new extension method that will do the unioning for you:
public static IEnumerable<T[]> AllCombinations<T>(this IList<T> argsList)
{
for (int i = 1; i <= argsList.Count; i++)
{
foreach (var combo in argsList.Combinations(i))
{
yield return combo;
}
}
}
Then you can get all your combinations at once by running
var allCombos = ints.AllCombinations()
.Where(x => x.Sum() == target);
So for your example, it will return 1,5, 2,4, and 1,2,3 in one collection.
If you want to know whether (and discover these numbers) two numbers sum to X it's an easy task and you can do it O(n) on average.
HashSet<int> numbers = new HashSet<int>(yourNumberArray);
foreach(int number in numbers)
if(numbers.Contains(x-number))
Console.WriteLine(number + " " + "numbers[x-number]");
However when you want to know if x1,x2,...,xk numbers sum to X it's NP-complete problem and no polynominal bounded solution is known (also it is not known does such solution exists). If number of items in your set is small (about ~20-30) you can brute-force your result by enumerating all subsets.
for (int i=1; i< (1 << setSize); ++i)
{
check does number in current set sum to X by bitwise operations on i
(treat number binary representation as information about set
(binary one means item is in set, zero means item is not in set)
}
You can also reduce this problem to knapsack problem and get pseudo-polynominal time, however maximum value in set shouldn't be big. For more information check: http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/
You can find all combinations which results 6 using Lipski's algorithm like this:
static List<List<int>> FindCombinations(int x)
{
var combinations = new List<List<int>>();
var P = new int[10];
var R = new int[10];
combinations.Add(Enumerable.Repeat(1,x)); // first combination
P[1] = x;
R[1] = 1;
int d = 1, b, sum;
while (P[1] > 1)
{
sum = 0;
if (P[d] == 1)
{
sum = sum + R[d];
d = d - 1;
}
sum = sum + P[d];
R[d] = R[d] - 1;
b = P[d] - 1;
if (R[d] > 0) d++;
P[d] = b;
R[d] = sum/b;
b = sum%b;
if (b != 0)
{
d++;
P[d] = b;
R[d] = 1;
}
List<int> temp = new List<int>();
for (int i = 1; i <= d; i++)
temp = temp.Concat(Enumerable.Repeat(P[i], R[i])).ToList();
combinations.Add(temp);
}
return combinations;
}
Then all you need to is compare each sequence with your numbers:
var combinations = FindCombinations(6);
var numbers = new List<int> {1, 2, 3, 5, 4,6};
var result =
combinations.Where(x => x.Intersect(numbers).Count() == x.Count)
.Select(x => x.Intersect(numbers))
.ToList();
Here is the result in LINQPad:
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 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]);
}