Find two sum function in c# - c#

I am trying to solve a problem in testdome online exam.
the question is Write a function that, given a list and a target sum, returns zero-based indices of any two distinct elements whose sum is equal to the target sum. If there are no such elements, the function should return null.
here is my code , it is just 75% true and the 25% to time is exceed
using System;
using System.Linq;
using System.Collections.Generic;
class TwoSum
{
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
var result = from n1 in list
from n2 in list
where n1 + n2 == sum
select new Tuple<int, int>(list.IndexOf(n1), list.IndexOf(n2));
return result.FirstOrDefault();
}
public static void Main(string[] args)
{
Tuple<int, int> indices = FindTwoSum(new List<int>() { 1, 3, 5, 7, 9 }, 12);
Console.WriteLine(indices.Item1 + " " + indices.Item2);
}
}
you can copy paste my code in the online website and see the result.
can any one help me so we get 100% true. :D
https://www.testdome.com/Questions/Csharp/TwoSum/4318

A little bit modification from Atif's solution which we don't need to copy the list to HashSet firstly.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
HashSet<int> hs = new HashSet<int>();
for (int i = 0; i < list.Count; i++)
{
var needed = sum - list[i];
if (hs.Contains(needed))
{
return Tuple.Create(list.IndexOf(needed), i);
}
hs.Add(list[i]);
}
return null;
}

This is one of those cases where you need to come at the problem from a different approach. Instead of doing a cross join of all the values and finding the first sum that matches, instead you want to make a lookup of all the values and loop through and check if the difference of the current item and the sum are in that lookup. That way you get a worst case of linear performance instead of polynomial.
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;
}

A slight modification to your code by using a HashSet instead of a LookUp.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
var hs = new HashSet<int>();
list.ToList().ForEach(x => hs.Add(x));
for (int i = 0; i < hs.Count; i++)
{
var diff = sum - list[i];
if (hs.Contains(diff))
{
var index = list.IndexOf(diff);
return new Tuple<int, int>(i, index);
}
}
return null;
}
I have tried and tested and get 100%, i.e. all tests pass including the
"Performance test with a large number of elements" test

public static Tuple<int, int> FindTwoSum(IList<int> list, int target)
{
var dict = new Dictionary<int, int>();
for (int i = 0; i < list.Count; i++)
{
var diff = target - list[i];
int j = -1;
if(dict.TryGetValue(diff, out j))
{
return Tuple.Create<int, int>(j, i);
}
dict[list[i]] = i;
}
return null;
}

This is my working solution:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
var dictionary = new Dictionary<int, int>();
for (var i = 0; i < list.Count; i++)
{
var aim = sum - list[i];
if(dictionary.ContainsKey(aim))
{
return new Tuple<int, int> (dictionary[aim], i);
}
else if(!dictionary.ContainsKey(list[i]))
{
dictionary.Add(list[i], i);
}
}
return null;
}

A slight modification to your version also passes the test. It is not 100% correct though. That tells you test cases on Testdome are not complete. I will leave it as an exercise as to what is wrong.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
var result = from n1 in list
join n2 in list
on n1 equals sum - n2
select new Tuple<int, int>(list.IndexOf(n1), list.IndexOf(n2));
return result.FirstOrDefault(x=>x.Item1!=x.Item2);
}

a non Linq extensions method using version of juharr's code
public static Tuple<int, int> FindTwoSumImprovedNonLinq(IList<int> list, int sum)
{
for (int i = 0; i < list.Count; i++)
{
int diff = sum - list[i];
if (list.IndexOf(diff) > -1)
return Tuple.Create(i, list.IndexOf(diff));
}
return null;
}

public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
int max = list.Max();
for (int i = 0; i < list.Count - 1; i++)
{
int first = list[i];
if (first + max == sum) return new Tuple<int, int>(i, list.IndexOf(max));
if (first + max < sum) continue;
for (int j = i+1; j < list.Count; j++)
{
int second = list[j];
if (sum == first + second)
{
return new Tuple<int, int>(i, j);
}
}
}
return null;
}

Here's code that passes all 4 tests. There's abuncha issues about the problem, however, that make it interesting. Basic test: iterate through a list, for each number in the list, iterate through the list and find its pair, ie that which when added together equal the target value. So it's O(n**2) algorithm. The 4th test burns that down. A big hint here, you only have to return the first matching pair. So, to solve:
double iterate through the list and return solution
special case for null list
special case for no solution found
special case for entry which when doubled equals the target: they must have a different index. eg:({5,1,3}, 10) 5+5=10, however, there must be a second 5, so this fails, where ({5,1,3,5},10) succeeds returning (0,3)
So, to kick the algorithm down to O(n), we can keep a record of what #s we've found, because we only need to keep the 1st occurrence of each one. But, we need a flexible, fast, data structure to do it. Array fails because we don't know what size it will be at compile time. I tried List. So you have 10million ones, it saves the first list[0]=1, and charges on. Next is 2, 2+1!=10, add 2 to list, move on. Works.
until you have an input of 10million sequential ints, and the list is huge. So switch to Dictionary. Now it passes all 4 tests.
So, sequence through input list, for each item, search its pair in the dictionary. If not, search this item in dictionary, if not, add it. When you do find its pair in the dictionary, set your return and go.
public class Item
{
public Item(int _val, int _loc) {
val = _val;
loc = _loc;
}
public int val;
public int loc;
}
class TwoSum
{
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
Tuple<int, int> result = null;
Dictionary<int, Item> dictionary = new Dictionary<int, Item>();
int index = 0;
bool done = false;
do
{
int curr = list[index];
int pair = sum - list[index];
if (dictionary.ContainsKey(pair))
{
result = new Tuple<int, int>(index, dictionary[pair].loc);
done = true;
}
else
{
if (! dictionary.ContainsKey(curr))
{
Item found1 = new Item(curr, index);
dictionary.Add(curr, found1);
}
}
index++;
}
while (index < list.Count && !done);
return result;
}

A even simpler way is:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
for (int i = 0; i < list.Count; i++)
{
// subtract the item to the sum to find the difference
int diff = sum - list[i];
// if that number exist in that list find its index
if (list.Contains(diff))
{
return Tuple.Create(i, list.IndexOf(diff));
}
}
return null;
}
That way you wouldn't need to lookup the entire list in advance, it still is a 75% though.

int[] arr = new int[] { 1, 0, 2, 3, 4, 3 };
for (int i = 0; i < arr.Length; i++)
{
var requiredElements = arr.Select((item, index) => new { index, item }).Where(ind => ind.item.Equals(4 - arr[i])).ToList();
if (requiredElements.Count > 0)
{
foreach (var disp in requiredElements)
Console.WriteLine("Indexes are " + i.ToString() + ":" + disp.index);
}
break;
}
}
// Where 4 is the target into - ind.item.Equals(4 - arr[i])

Here is my solution. As far as I test, It returns right indices. But I don't know if it is efficient for performance.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
for (int i = 0; i < list.Count; i++)
{
int difference = sum - list[i];
bool isExist = list.Contains(difference);
if (!isExist)
{
continue;
}
else if (difference == list[i] && list.Where(x => x == difference).ToList().Count > 1)
{
var duplicated = list.Select((item, index) => new { Value = item, Index = index }).Where(x => x.Value == difference).Take(2).ToList();
return new Tuple<int, int>(duplicated[0].Index, duplicated[1].Index);
}
else if (difference == list[i] && list.Where(x => x == difference).ToList().Count == 1) continue;
else
{
return new Tuple<int, int>(i, list.IndexOf(difference));
}
}
return null;
}
Edit:
My first solution has a huge performance problem. So I decided to improve Mohammed Turshan's solution. I think it has duplication bug. I solved that problem by using Dictionary class.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
Dictionary<int, int> dict = list.Select((value, index) =>
new { Value = value, Index = index }).ToDictionary(x => x.Index, x => x.Value);
var result = from n1 in dict
from n2 in dict
where n1.Value + n2.Value == sum && n1.Key != n2.Key
select new Tuple<int, int>(n1.Key, n2.Key);
return result.FirstOrDefault();
}

As far as I'm concerned, building a lookup table is just extra memory and overhead. In addition, it processes every item in the list rather than stopping when a match is found.
So why not just something like this?
public Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
for (int i = 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
if (list[i] + list[j] == sum)
return new Tuple<int, int>(list[i], list[j]);
}
}
return null;
}

Maybe someone needs Java Solution
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> numAndIndex = new HashMap<>();
for(int currentIndex=0; currentIndex<nums.length; currentIndex++){
int currentNumber=nums[currentIndex];
Integer expectedIndex=numAndIndex.get(target-currentNumber);
if(expectedIndex!=null){
return new int[]{expectedIndex, currentIndex};
}
numAndIndex.put(currentNumber, currentIndex);
}
return null;
}
}

public static Tuple FindTwoSum(IList list, int sum)
{
for(int i=0;i<list.Count;i++)
{
for(int j=0;j<list.Count;j++)
{
if((list[i]+list[j])==12)
{
return new Tuple<int, int>(i,j);
}
}
}
return null;
}
This will work

Related

Output how many duplicates in an array

I'm looking to output the number of duplicates for each int in an array e.g. the array 1,2,3,4,1,1,3 would output 1:3, 2:1, 3:2, 4:1. at the moment no matter how many of each number there is the dictionary only counts one and outputs every value to be 1.
static void Main(string[] args)
{
Console.WriteLine("Type 10 numbers");
int[] arr1 = new int[10];
for (int i = 0; i < arr1.Length; i++)
{
arr1[i] = Convert.ToInt32(Console.ReadLine());
}
output(arr1);
Console.ReadKey();
}
static void output(int[] arr1)
{
Dictionary<int, int> dict = new Dictionary<int, int>();
for (int i =0; i < arr1.Length; i++)
{
if (dict.ContainsKey(arr1[i]))
{
int c = dict[arr1[i]];
dict[arr1[i]] = c++;
}
else
{
dict.Add(arr1[i], 1);
}
}
for (int i =0; i<arr1.Length; i++)
{
Console.WriteLine(arr1[i] + ":" + dict[arr1[i]]);
}
}
I assume you want to write the algorithm to group the numbers by yourself. If not, have a look at LINQ, which provides already a lot of collection operations which makes life a lot more easier. In your case a GroupBy should already do the trick.
The problem of your implementation lies in the following line:
dict[arr1[i]] = c++;
The reason is you are incrementint c after setting it as new dictionary value. c++ and ++c are different operations, this is described in What is the difference between ++i and i++?. To solve your problem and increment before setting teh value use
dict[arr1[i]] = ++c;
Note that you also could write this step of incrementation more compact like
dict[arr1[i]]++;
If you want to use Linq
var array = new int[] { 1, 2, 3, 4, 1, 1, 3 };
var str= string.Join(",", array.GroupBy(x => x).Select(g => g.Key + ":" + g.Count()));
Console.WriteLine(str);
While Fruchtzwerg is correct, you're returning c before it's incremented, you shouldn't even be making a temp variable.
Just do:
dict[arr1[i]] += 1; //or dict[arr1[i]]++;
You also shouldn't use that for-loop to loop through the dictionary values. As it will not print out the way you probably want it to.
foreach(var kvp in dict)
{
Console.WriteLine(kvp.Key + ":" + kvp.Value);
}
Try using the above foreach loop
You can try this:
class Program{
static void Main(string[] args){
int[] array = new int[10];
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Type in the number for index: " + i);
array[i] = Convert.ToInt32(Console.ReadLine());
Duplicate(array);
}
}
public static void Duplicate(int[] array)
{
List<int> done = new List<int>();
for (int i = 0; i < array.Length; i++)
{
if (check(array[i], done) == false)
{
Console.WriteLine();
Console.WriteLine(array[i] + ":" + dupe(array[i], array));
}
}
}
public static int dupe(int number, int[] array)
{
int duplicate = 0;
for (int i = 0; i < array.Length; i++)
{
if (array[i] == number)
{
duplicate++;
}
}
return duplicate;
}
public static bool check(int number, List<int> list)
{
bool b = false;
for (int i = 0; i < list.Count; )
{
if (number == list[i])
{
b = true;
i++;
}
else
{
i++;
}
}
return b;
}
}

Mathematically adding multiple lists

I am stuck on a method where I have a List<List<int>> and would like to take each List<int>'s value of each index and add them together.
To be specific:
intList1[0] + intList2[0] + intList3[0]
intList1[1] + intList2[1] + intList3[1]
Although the amount of list and a number of items in each list are not fixed.
The result should then be a List<int> that contains each sum.
You can union all lists together via SelectMany and then group them by initial index with subsequent Sum() calculating:
var answer = lists.SelectMany(x => x.Select((item,index) => new {item,index}).ToList())
.GroupBy(x => x.index).Select(x => x.Sum(y => y.item)).ToList();
Init your result list at the same size as the maximum number of elements in your sublists, and then simply loop into your sublists to sum the different values.
int maximumNumberElements = listContainer.Max(l => l.Count);
List<int> resultList = new List<int>();
for(int i = 0; i < maximumNumberElements; i++)
{
resultList.Add(0);
}
for(int i = 0; i < listContainer.Count; i++)
{
for(int j = 0; j < listContainer[i].Count; j++)
{
resultList[j] += listContainer[i][j];
}
}
I like the dictionary method for these kinds of issues, you could also store some interesting things alongside your value for the dictionary like, the number of items that summed up for that index etc.
// Dictionary of indexes to sums
var sums = new Dictionary<int, int>();
// Iterate your lists.
foreach(var list in lists) {
for (var i = 0; i < list.Count; i++) {
// For the given index, sum up the values in the dictionary.
if (sums.TryGetValue(i, var out value) == false) sums[i] = 0;
sums[i] = sums[i] + list[i];
}
}
Another solution perhaps better in case of larger lists
public static IEnumerable<int> ListSum(IEnumerable<IEnumerable<int>> ll)
{
var resultList = new List<int>();
var enumerators = ll.Select(l => l.GetEnumerator()).ToArray();
bool stillResult;
do
{
stillResult = false;
var sum = 0;
foreach (var e in enumerators)
{
if (e.MoveNext())
{
sum += e.Current;
stillResult = true;
}
}
resultList.Add(sum);
} while (stillResult);
return resultList;
}

Calculating the Power set of large string array in C# [duplicate]

This question already has answers here:
Memory efficient power set algorithm
(5 answers)
Closed 6 years ago.
I want to calculate power set of string array (consider it as a set). When I am exceeding above 26 elements it is thowing out of memory exception.
List<int> ff = new List<int>();
double length = Math.Pow(2, 29);
for (int i = 0; i < length; i++)
{
ff.Add(1);
}
Above code will produce the that exception if you run it. The size of the set may go up to 1000. So the size of power set of that set will be 2^1000.
How can I deal with this?
EDIT:
I know that above code is not a function of power set. I was just checking how big array c# will be able to hold.
private static Dictionary<int, object> PowerSetB(string[] input)
{
int n = input.Length;
// Power set contains 2^N subsets.
int powerSetCount = 1 << n;
var ans = new Dictionary<int, object>();
for (int setMask = 0; setMask < powerSetCount; setMask++)
{
var s = new ArrayList();
for (int i = 0; i < n; i++)
{
// Checking whether i'th element of input collection should go to the current subset.
if ((setMask & (1 << i)) > 0)
s.Add(input[i]);
}
ans[setMask] = s;
}
return ans;
}
Above code is my function of power set.
Thank you in advance.
Do you really want to store all the items in memory? I suggest using IEnumerable<int> instead of materialized List<int>:
// just enumeration, coefficients aren't stored
public static IEnumerable<int> Serie(Func<int, int> coefByIndex) {
if (null == coefByIndex)
throw new ArgumentNullException("coefByIndex");
for (int i = 0; ; ++i)
yield return coefByIndex(i);
}
// Let's sum up all 2**29 values,
// i.e. compute f(1) summing up 2**29 items (it's a long process...)
// sum = 1.44115187606094E+17 (diverges, as we might have expected)
Double sum = Serie(index => index)
.Select(x => x * 1.0)
.Take(1 << 29)
.Sum();
Edit: Once agian, do not materialize (Dictionary<int, object>) huge results! Provide an IReadOnlyDictionary<int, int[]> interface but not implementation as Dictionary<int, object>,
Something like this:
// ArrayList is an obsolete collection;
// int[] far more natural here
public sealed class PowerSet: IReadOnlyDictionary<int, int[]> {
private int m_Power;
private int[] getItem(int index) {
int[] result = new int[m_Power];
for (int i = 0; i < m_Power; ++i) {
result[i] = index % 2;
index /= 2;
}
return result;
}
public PowerSet(int power) {
m_Power = power;
}
public int[] this[int key] {
get {
if (key >= 0 && key < Count)
return getItem(key);
else
throw new ArgumentOutOfRangeException("key");
}
}
public int Count {
get {
return 1 << m_Power;
}
}
public IEnumerable<int> Keys {
get {
return Enumerable.Range(0, Count);
}
}
public IEnumerable<int[]> Values {
get {
return Enumerable.Range(0, Count).Select(index => getItem(index));
}
}
public bool ContainsKey(int key) {
return key >= 0 && key < Count;
}
public IEnumerator<KeyValuePair<int, int[]>> GetEnumerator() {
return Enumerable
.Range(0, Count)
.Select(index => new KeyValuePair<int, int[]>(index, getItem(index)))
.GetEnumerator();
}
public bool TryGetValue(int key, out int[] value) {
if (key >= 0 && key < Count) {
value = getItem(key);
return true;
}
value = null;
return false;
}
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
}
...
// Just an easy call
private static IDictionary<int, int[]> PowerSetB(string[] input) {
return new PowerSet(input.Length);
}

c# permutation without repetition when order is important [duplicate]

I have a list of Offers, from which I want to create "chains" (e.g. permutations) with limited chain lengths.
I've gotten as far as creating the permutations using the Kw.Combinatorics project.
However, the default behavior creates permutations in the length of the list count. I'm not sure how to limit the chain lengths to 'n'.
Here's my current code:
private static List<List<Offers>> GetPerms(List<Offers> list, int chainLength)
{
List<List<Offers>> response = new List<List<Offers>>();
foreach (var row in new Permutation(list.Count).GetRows())
{
List<Offers> innerList = new List<Offers>();
foreach (var mix in Permutation.Permute(row, list))
{
innerList.Add(mix);
}
response.Add(innerList);
innerList = new List<Offers>();
}
return response;
}
Implemented by:
List<List<AdServer.Offers>> lst = GetPerms(offers, 2);
I'm not locked in KWCombinatorics if someone has a better solution to offer.
Here's another implementation which I think should be faster than the accepted answer (and it's definitely less code).
public static IEnumerable<IEnumerable<T>> GetVariationsWithoutDuplicates<T>(IList<T> items, int length)
{
if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
return from item in items.Distinct()
from permutation in GetVariationsWithoutDuplicates(items.Where(i => !EqualityComparer<T>.Default.Equals(i, item)).ToList(), length - 1)
select Prepend(item, permutation);
}
public static IEnumerable<IEnumerable<T>> GetVariations<T>(IList<T> items, int length)
{
if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
return from item in items
from permutation in GetVariations(Remove(item, items).ToList(), length - 1)
select Prepend(item, permutation);
}
public static IEnumerable<T> Prepend<T>(T first, IEnumerable<T> rest)
{
yield return first;
foreach (var item in rest) yield return item;
}
public static IEnumerable<T> Remove<T>(T item, IEnumerable<T> from)
{
var isRemoved = false;
foreach (var i in from)
{
if (!EqualityComparer<T>.Default.Equals(item, i) || isRemoved) yield return i;
else isRemoved = true;
}
}
On my 3.1 GHz Core 2 Duo, I tested with this:
public static void Test(Func<IList<int>, int, IEnumerable<IEnumerable<int>>> getVariations)
{
var max = 11;
var timer = System.Diagnostics.Stopwatch.StartNew();
for (int i = 1; i < max; ++i)
for (int j = 1; j < i; ++j)
getVariations(MakeList(i), j).Count();
timer.Stop();
Console.WriteLine("{0,40}{1} ms", getVariations.Method.Name, timer.ElapsedMilliseconds);
}
// Make a list that repeats to guarantee we have duplicates
public static IList<int> MakeList(int size)
{
return Enumerable.Range(0, size/2).Concat(Enumerable.Range(0, size - size/2)).ToList();
}
Unoptimized
GetVariations 11894 ms
GetVariationsWithoutDuplicates 9 ms
OtherAnswerGetVariations 22485 ms
OtherAnswerGetVariationsWithDuplicates 243415 ms
With compiler optimizations
GetVariations 9667 ms
GetVariationsWithoutDuplicates 8 ms
OtherAnswerGetVariations 19739 ms
OtherAnswerGetVariationsWithDuplicates 228802 ms
You're not looking for a permutation, but for a variation. Here is a possible algorithm. I prefer iterator methods for functions that can potentially return very many elements. This way, the caller can decide if he really needs all elements:
IEnumerable<IList<T>> GetVariations<T>(IList<T> offers, int length)
{
var startIndices = new int[length];
var variationElements = new HashSet<T>(); //for duplicate detection
while (startIndices[0] < offers.Count)
{
var variation = new List<T>(length);
var valid = true;
for (int i = 0; i < length; ++i)
{
var element = offers[startIndices[i]];
if (variationElements.Contains(element))
{
valid = false;
break;
}
variation.Add(element);
variationElements.Add(element);
}
if (valid)
yield return variation;
//Count up the indices
startIndices[length - 1]++;
for (int i = length - 1; i > 0; --i)
{
if (startIndices[i] >= offers.Count)
{
startIndices[i] = 0;
startIndices[i - 1]++;
}
else
break;
}
variationElements.Clear();
}
}
The idea for this algorithm is to use a number in offers.Count base. For three offers, all digits are in the range 0-2. We then basically increment this number step by step and return the offers that reside at the specified indices. If you want to allow duplicates, you can remove the check and the HashSet<T>.
Update
Here is an optimized variant that does the duplicate check on the index level. In my tests it is a lot faster than the previous variant:
IEnumerable<IList<T>> GetVariations<T>(IList<T> offers, int length)
{
var startIndices = new int[length];
for (int i = 0; i < length; ++i)
startIndices[i] = i;
var indices = new HashSet<int>(); // for duplicate check
while (startIndices[0] < offers.Count)
{
var variation = new List<T>(length);
for (int i = 0; i < length; ++i)
{
variation.Add(offers[startIndices[i]]);
}
yield return variation;
//Count up the indices
AddOne(startIndices, length - 1, offers.Count - 1);
//duplicate check
var check = true;
while (check)
{
indices.Clear();
for (int i = 0; i <= length; ++i)
{
if (i == length)
{
check = false;
break;
}
if (indices.Contains(startIndices[i]))
{
var unchangedUpTo = AddOne(startIndices, i, offers.Count - 1);
indices.Clear();
for (int j = 0; j <= unchangedUpTo; ++j )
{
indices.Add(startIndices[j]);
}
int nextIndex = 0;
for(int j = unchangedUpTo + 1; j < length; ++j)
{
while (indices.Contains(nextIndex))
nextIndex++;
startIndices[j] = nextIndex++;
}
break;
}
indices.Add(startIndices[i]);
}
}
}
}
int AddOne(int[] indices, int position, int maxElement)
{
//returns the index of the last element that has not been changed
indices[position]++;
for (int i = position; i > 0; --i)
{
if (indices[i] > maxElement)
{
indices[i] = 0;
indices[i - 1]++;
}
else
return i;
}
return 0;
}
If I got you correct here is what you need
this will create permutations based on the specified chain limit
public static List<List<T>> GetPerms<T>(List<T> list, int chainLimit)
{
if (list.Count() == 1)
return new List<List<T>> { list };
return list
.Select((outer, outerIndex) =>
GetPerms(list.Where((inner, innerIndex) => innerIndex != outerIndex).ToList(), chainLimit)
.Select(perms => (new List<T> { outer }).Union(perms).Take(chainLimit)))
.SelectMany<IEnumerable<IEnumerable<T>>, List<T>>(sub => sub.Select<IEnumerable<T>, List<T>>(s => s.ToList()))
.Distinct(new PermComparer<T>()).ToList();
}
class PermComparer<T> : IEqualityComparer<List<T>>
{
public bool Equals(List<T> x, List<T> y)
{
return x.SequenceEqual(y);
}
public int GetHashCode(List<T> obj)
{
return (int)obj.Average(o => o.GetHashCode());
}
}
and you'll call it like this
List<List<AdServer.Offers>> lst = GetPerms<AdServer.Offers>(offers, 2);
I made this function is pretty generic so you may use it for other purpose too
eg
List<string> list = new List<string>(new[] { "apple", "banana", "orange", "cherry" });
List<List<string>> perms = GetPerms<string>(list, 2);
result

How can I check if 3 out of 5 integer are the same

Let's say I have 5 integers.
int a = 1;
int b = 2;
int c = 5;
int d = 1;
int f = 1;
I want to check if any of these 3 out of 5 integers are the same.
I've tried some stuff however it got very long (500+ lines) and thought this wasn't a good method to use.
first put them all in a single collection, rather than having separate variables:
var numbers = new[]{a,b,c,d,f};
Then group them, find the count of each group, and see if anything meets your criteria.
var isLargeGroup = numbers.GroupBy(n => n, (key, group) => group.Count() )
.Any(count => count >= 3);
Both of the other solutions are potentially expensive for large sets (say 10000 numbers), costing a full enumeration and creating many objects which will be garbage collected. Try this, which could stop execution long before a complete enumeration:
private bool AreNumbersTheSame(int[] numbers, int duplicateCount)
{
var numberCounts = new Dictionary<int, int>();
for (int i = 0; i < numbers.Length; i++)
{
var current = numbers[i];
if (!numberCounts.ContainsKey(current))
{
numberCounts[current] = 1;
continue;
}
if (numberCounts[current] == duplicateCount - 1)
{
return true;
}
numberCounts[current]++;
}
return false;
}
Call it like:
var result = AreNumbersTheSame(new[] { a, b, c, d, f }, 3);
I would do the following :-
Add all the numbers to a list.
Create a dictionary having number as the KEY and its occurrence as VALUE.
While iterating the list, need to check if a number is not in dictionary then add it using number as the KEY and 1 as its VALUE.
If the number re-occurs, just increment the dictionary VALUE by 1.
Once it is equal to 3, break out of the loop.
int a = 1;
int b = 2;
int c = 5;
int d = 1;
int f = 1;
var listOfNumbers = new List<int> {a, b, c, d, f};
var dict = new Dictionary<int, int>();
foreach (var number in listOfNumbers)
{
if (dict.ContainsKey(number))
{
dict[number] = dict[number] + 1; //if a key repeats => increment the value by 1
if (dict[number] == 3)
break; //found the number
}
else
dict.Add(number, 1); //for first occurence of the key => initialize the value with 1
}
For what it's worth, here's another option which is less elegant than GroupBy but more efficient if the sequence is large. Hidden in an extension method readability is not so important in my opinion.
public static bool HasDuplicateCount<T>(this IEnumerable<T> seq, int maxCount)
{
Dictionary<T, int> counts = new Dictionary<T, int>();
foreach (T t in seq)
{
int count;
if (counts.TryGetValue(t, out count))
++count;
else
count = 1;
if (count == maxCount)
return true;
counts[t] = count;
}
return false;
}
You can use it in this way:
bool threeDups = new[] { a, b, c, d, f }.HasDuplicateCount(3);
This can also be solved using the Majority Vote algorithm, as long as you are looking to see if more than half of your elements are the same (as is the case for 3 out of 5 elements):
public static bool HasMajorityElement(int[] a)
{
int candidate = 0;
int count = 0;
foreach (int i in a)
{
if (count == 0)
{
candidate = i;
count = 1;
}
else
{
count += candidate == i ? 1 : -1;
}
}
count = 0;
foreach (int i in a)
{
if (i == candidate) ++count;
}
return count > a.Length / 2;
}
Test it on ideone.com.
Or alternatively for your specific case:
public static bool ThreeOutOfFive(int a, int b, int c, int d, int e)
{
return ((a==b?1:0)+(a==c?1:0)+(a==d?1:0)+(a==e?1:0) > 1)
|| ((b==c?1:0)+(b==d?1:0)+(b==e?1:0) > 1)
|| ((c==d?1:0)+(c==e?1:0) > 1);
}

Categories

Resources