Resetting lists in c# - c#

Following are two pieces of code I used to compute power sets of elements in a list
code 1)
public static List<List<int>> getCpower(List<int> list)
{
var result = new List<List<int>>();
for (int i = 0; i < (1 << list.Count); i++)
{
var sublist = new List<int>();
for (int j = 0; j < list.Count; j++)
{ if ((i & (1 << j)) != 0)
{ sublist.Add(list[j]);
}
}
result.Add(sublist);
}
return result;
}
code 2)
public static List<List<int>> getCpower(List<int> list)
{
var result = new List<List<int>>();var sublist = new List<int>();
for (int i = 0; i < (1 << list.Count); i++)
{
sublist.Clear();sublist.TrimExcess();
for (int j = 0; j < list.Count; j++)
{ if ((i & (1 << j)) != 0)
{ sublist.Add(list[j]);
}
}
result.Add(sublist);
}
return result;
}
The first code used a new statement and if i try to find out powersets of list with count 30 then OutOfMemoryException arises.So to save memory i used Clear() and TrimExcess() to get the list as if it were initialized using a new statement in code2. But these two codes return different results. I do not get why is this happening. Please help.
Are the two following two pieces not doing the same thing
for(....)
{
var sublist = new List<int>();
for(......)
{
//some code
}
}
and
var sublist = new List<int>();
for(.....)
{
sublist.Clear();sublist.TrimExcess();
for(.... )
{
//some code
}
}

In your second code, you only have a single nested list - you're adding several references referring to the same sublist, which is pointless.
Have you considered that maybe the reason you're running out of space with your first code is because you're fundamentally trying to hold too much data in memory at a time?
You could consider returning an IEnumerable<List<int>> like this:
public static IEnumerable<List<int>> getCpower(List<int> list)
{
for (int i = 0; i < (1 << list.Count); i++)
{
var sublist = new List<int>();
for (int j = 0; j < list.Count; j++)
{ if ((i & (1 << j)) != 0)
{
sublist.Add(list[j]);
}
}
yield return sublist;
}
}
This will now be lazily evaluated - so you could iterate over the top-level sequence, but unless the lists are retained by the caller, you'll only have a single list in memory at a time.

In the second piece of code you are clearing the list of results. This alters the outcome of your algorithm. You are throwing away your results because you are reusing the same list instance for all iterations.

In the second code example, you only ever have a single sublist instance. That same instance is cleared and added to the list again every time you loop through. Here's an example to help you understand:
var sublist = new List<int> { 1, 2, 3 };
var result = new List<List<int>> { sublist };
//result[0] is now {1, 2, 3}
sublist.Clear();
//result[0] is now {}
result.Add(sublist);
//result[0], result[1], and sublist are the same instance

Related

C# Pascal Triangle Code doesn't work - Logic correct

I've been trying to learn more about C#, and so I was doing a little practicing with Lists:
static void Main()
{
List<List<int>> a = new List<List<int>>();
List<int> temp = new List<int>();
temp.Add(1);
a.Add(temp);
for (int i = 0; i < 9; i++)
{
temp.Clear();
temp.Add(1);
for (int q = 0; q < a[i].Count-1; q++)
{
temp.Add(a[i][q] + a[i][q+1]);
}
temp.Add(1);
a.Add(temp);
}
foreach (var i in a[8])
Console.Write(i + " ");
Console.WriteLine();
}
I converted this to C++, and it works perfectly. However, in C#, a[i].Count is always 1. Even though after the first loop the size must be 2.
My only guess is that there's some major difference between C++'s Vector and C#'s List that I've apparently missed. Any ideas?
Here's the C++ code which works:
int main()
{
std::vector<std::vector<int>> a;
std::vector<int> b;
b.push_back(1);
a.push_back(b);
for (int i = 0; i < 9; i++)
{
b.clear();
b.push_back(1);
for (int q = 0; q < a[i].size()-1; q++)
{
b.push_back(a[i][q] + a[i][q+1]);
}
b.push_back(1);
a.push_back(b);
}
for (auto i : a[8])
{
std::cout << i << ' ';
}
}
Output for C++ Code:
1 8 28 56 70 56 28 8 1
Output For C# Code:
1 1
Any help is appreciated, thanks!
Look at your C# code a.Add(temp);. This temp variable is a reference type, so it will always add the same memory object.
To fix that, you can use LINQ to solve it:
a.Add(temp.ToList());. ToList() will generate a new object with different memory.
I have modified your code slightly, the main difference to not is, C# there are mainly 2
kind of types, one is a reference type and one is a value type.
List is a reference type.
In your code, you always clearing and adding numbers to the temp list.
that always points to the same object, so when you clear in the nth row, it's also clearing all the rows before it.
List<List<int>> a = new List<List<int>>();
a.Add(new List<int> { 1 });
for (int i = 0; i < 9; i++)
{
List<int> temp = new List<int>();
temp.Add(1);
for (int q = 0; q < a[i].Count - 1; q++)
{
temp.Add(a[i][q] + a[i][q + 1]);
}
temp.Add(1);
a.Add(temp);
}
foreach (var row in a)
{
foreach (var col in row)
{
Console.Write(col + " ");
}
Console.WriteLine();
}
Console.ReadKey();

how to clear Hackerank Dynamic array Runtime error?

I have done the coding and my few test cases got passed but the test case 2 and few more did not pass. When I ran the same code in local, I got the desired result but on HackerRank, it shows Runtime error.
Here is the question - https://www.hackerrank.com/challenges/dynamic-array/problem
Here is my solution:-
public static List dynamicArray(int n, List> queries) {
List<List<int>> seqList = new List<List<int>>();
for (int j = 0; j < n ; j++)
{
seqList.Insert(j, new List<int>(n-1)) ;
}
List<int> seqList2 = new List<int>();
int lastAnswer = 0;
int index;
for (int i = 0; i < queries.Count ; i++)
{
index = ((queries[i][1] ^ lastAnswer) % n);
if (queries[i][0] == 1)
{
seqList[index].Add(Convert.ToInt32(queries[i][2]));
}
else
{
int value = queries[i][2] % seqList[index].Count ;
lastAnswer = seqList[index][value];
Console.WriteLine(lastAnswer);
seqList2.Add(lastAnswer);
}
}
A runtime error on Hackerrank can be because of uninitialized variables or because of trying to access an element in an array which is not there (ArgumentOutOfRangeException)
I'm guessing in your case because of the latter.

C# Losing values in a nested List

I'm incurring a really weird problem with my Nested List of int (List<List<int>>). At some point after I put over 1 million list's in it they all loose they're values i.e they have 0 elements in them .. Really weird right? I suspected that I'm putting too much list's in it. However I putted an if statement that will check if the nested list length is exactly 1 million and added a break point in it. It ended up that exceeding the nested list capability wasn't the case, it's something that completely messes with my head. I will post the code here so I can try to explain
//it will iterate 8^8 times - 16.7 million times
private static List<List<int>> minMinatRed = new List<List<int>>();
private static List<List<int>> minMinataKolona = new List<List<int>>();
var tempHodove = new List<Tuple<bool, int[]>>();
int novMinatRed = red;
int novaMinataKolona = kolona;
for (int i = 0; i < numberOfVariations; i++)
{
tempHodove.Clear();
var hodove = UpdateList(novMinatRed, novaMinataKolona);
int x = i;
for (int j = 0; j < size; ++j)
{
result[j] = tempArr[x % size];
x /= size;
}
for (int k = result.Length - 1; k >= 0; k--)
{
tempHodove.Add(hodove[result[k]]);
}
bool trueValue = tempHodove.Any(c => c.Item1);
while (trueValue)
{
foreach (var hod in tempHodove.Where(hod => hod.Item1))
{
novMinatRed += hod.Item2[0];
novaMinataKolona += hod.Item2[1];
minatRed.Add(novMinatRed);
minataKolona.Add(novaMinataKolona);
count++;
break;
}
if (novMinatRed == kraenRed && novaMinataKolona == krainaKolona)
{
if (minCount > count)
{
minCount = count;
}
minMinatRed.Add(minatRed);
minMinataKolona.Add(minataKolona);
}
hodove = UpdateList(novMinatRed, novaMinataKolona);
tempHodove.Clear();
for (int k = result.Length - 1; k >= 0; k--)
{
tempHodove.Add(hodove[result[k]]);
}
trueValue = tempHodove.Any(c => c.Item1);
}
if (minMinatRed.Count == 1000000)
{
}
minataKolona.Clear();
minatRed.Clear();
count = 0;
novMinatRed = nachalenRed;
novaMinataKolona = nachalnaKolona;
}
The problem is in the minMinatRed and minMinataKolona list's as you can see there is only place where I add some values in them :
if (novMinatRed == kraenRed && novaMinataKolona == krainaKolona)
{
if (minCount > count)
{
minCount = count;
}
minMinatRed.Add(minatRed); //here
minMinataKolona.Add(minataKolona); //and here
}
Well once the break point is triggered in the :
if (minMinatRed.Count == 1000000){ }
I started checking what's going on.I found out that once the code reaches this point :
minataKolona.Clear();
minatRed.Clear();
It doesn't only wipes the minatRed values but it also erases the minMinatRed values, same goes for minataKolona and minMinataKolona..
Also once it goes back into the loop and add's some values to minatRed and minataKolona it also add's the same values to the nested list's more specifically here :
foreach (var hod in tempHodove.Where(hod => hod.Item1))
{
novMinatRed += hod.Item2[0];
novaMinataKolona += hod.Item2[1];
minatRed.Add(novMinatRed); //here
minataKolona.Add(novaMinataKolona); //and here
count++;
break;
}
Now since we previously wiped all the values from minatRed it will obviously have nothing in it and once we add 1 item to it, it has 1 item in it (lol).. now the thing is that it also adds this exact 1 item into EVERY single one of the List's in the minMinatRed nested list i.e all the 1 million lists have length 1 and also just 1 duplicate variable in them. That's what I was able to find about my current problem, however I have no clue why this is happening or how can I fix it. I have also read some question and answer's written by Mystical who's a StackOverFlow user too. Where they discussed branch predictions, I'm not sure if that's my case but it might be something related. Any suggestions and explanations are welcome. English is not my native language..
Update 1 forgot to include initialization of minataKolona and minatRed && numberOfVariations
private static readonly List<int> minatRed = new List<int>();
private static readonly List<int> minataKolona = new List<int>();
private static readonly double numberOfVariations = Math.Pow(size, size);
Update 2 Include the UpdateList method
private static List<Tuple<bool, int[]>> UpdateList(int red, int kolona)
{
var vsichkiHodove = new List<Tuple<bool, int[]>>()
{
new Tuple<bool, int[]>(Nadqsno(red, 1) && Napred(kolona, 2), new[]
{
+1,
+2
}),
new Tuple<bool, int[]>(Nadqsno(red, 2) && Napred(kolona, 1), new[]
{
+2,
+1
}),
new Tuple<bool, int[]>(Nalqvo(red, 1) && Napred(kolona, 2), new[]
{
-1,
+2
}),
new Tuple<bool, int[]>(Nalqvo(red, 2) && Napred(kolona, 1), new[]
{
-2,
+1
}),
new Tuple<bool, int[]>(Nadqsno(red, 2) && Nazad(kolona, 1), new[]
{
+2,
-1
}),
new Tuple<bool, int[]>(Nalqvo(red, 2) && Nazad(kolona, 1), new[]
{
-2,
-1
}),
new Tuple<bool, int[]>(Nadqsno(red, 1) && Nazad(kolona, 2), new[]
{
+1,
-2
}),
new Tuple<bool, int[]>(Nalqvo(red, 1) && Nazad(kolona, 2), new[]
{
-1,
-2
}),
};
return vsichkiHodove;
}
The problem is List<T> is a type by reference, therefore, when you add the lists minatRed and minataKolona to minMinatRed and minMinataKolona respectively, you're not creating a new (cloned) list.
All lists in minMinatRed (minMinataKolona) points to the same one: minatRed (minataKolona), so when you clear minatRed (or minataKolona), all lists in minMinatRed (or minMinataKolona) are cleared too, since actually are the same list.
You can solve this declaring minatRed and minataKolona inside the for loop:
for (int i = 0; i < numberOfVariations; i++)
{
var minatRed = new List<int>();
var minataKolona = new List<int>();
...
And of course you can't empty the lists:
//minataKolona.Clear(); Comment this lines or just remove it
//minatRed.Clear(); Comment this lines or just remove it
I agree with Arturo. Normally the code would look something like code below. I can't tell from your code where the equivalent to newRow (novMinatRed) is ever being cleared.
List<List<int>> minMinatRed = new List<List<int>>();
for (int i = 0; i < 10; i++)
{
List<int> newRow = new List<int>();
minMinatRed.Add(newRow);
for (int j = 0; j < 10; j++)
{
newRow.Add(j);
}
}

Iterate every combination of two elements in HashSet

How could I iterate through each combination of two elements in a HashSet once?
foreach (var elt1 in hashSet) {
foreach (var elt2 in hashSet) {
...
}
}
This would iterate the combinations of two but would iterate each combination TWICE. I'd like to do it once.
I think it's easy to do in Python. Is there any way to do it in C#?
Sample:
input hashSet: { 1, 2, 3, 4 }
iterate through: (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)
There is no built-in method to do this in C#. Since HashSet<T> is not indexed *, you cannot do it with two loops either.
If this is a one-time deal, the simplest solution is to make two nested loops on the results of ToList() or ToArray(), like this:
var items = hashSet.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
}
}
If you are looking for something reusable, make an extension method on IEnumerable<T> that produces all pairs:
static IEnumerable<Tuple<T,T>> MakeAllPairs<T>(this IEnumerable<T> data) {
var items = data.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
yield return Tuple.Create(a, b);
}
}
}
Now you can iterate your pairs in a single loop:
foreach (var pair in hashSet.MakeAllPairs()) {
Console.WriteLine("{0} {1}", pair.Item1, pair.Item2);
}
* Technically, you could use ElementAt<T>(int) extension from Enumerable, but that would be very slow on large sets.
I misread the question originally. This is a new answer
This is what you want (if working index-based is an option). Explanation is below
string[] myArray = GetArray();
for (int i = 0; i < myArray.Length - 1; i++)
{
var element1 = myArray[i];
for(int j = i + 1; j < myArray.Length; j++)
{
var element2 = myArray[j];
Console.WriteLine("{0} {1}", element1, element2);
}
}
Explanation: Assume the following array:
Apple, Banana, Coconut, Zucchini
When i = 0 (Apple), j will be 1 (Banana), then 2 (Coconut), then 3 (Zucchini)
When i = 1 (Banana), j will be 2 (Coconut), then 3 (Zucchini).
And so on...
Basically, you are making sure element j is always ahead of element i. This means you've effectively removed half of the possibilities (where j would be before i), which is what you wanted.
Note: if you want to use sets of equal elements (Apple + Apple), the second for loop needs to change to:
for(int j = i; j < myArray.Length; j++) //notice j = i instead of i + 1
You can work with indexes directly on the HashSet.
Try this:
int int1, int2;
HashSet<int> hs = new HashSet<int>();
hs.Add(1);
hs.Add(2);
hs.Add(3);
for (int i = 0; i < hs.Count-1; i++) {
int1 = hs.ElementAt<int>(i);
for (int j = i + 1; j < hs.Count; j++)
{
int2 = hs.ElementAt<int>(j);
}
}
To return all permutations (viz (1,2) and (2,1)), you can cross join the set with itself using SelectMany:
var hashSet = new HashSet<int>{1,2,3,4,5,6,7,8};
foreach (var elt in hashSet.SelectMany(
x => hashSet.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}
Edit: If you just want the unique combinations (viz (1,2) but not (2,1)) then just add a filter only larger values during the cross join:
var hashSet = new HashSet<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
foreach (var elt in hashSet.SelectMany(
x => hashSet.Where(y => y >= x)
.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}

How to code for dynamic for-loop levels?

My problem is like this:
I have several lists need to be permuted, but the list numbers are unknowable. And every element numbers in every list are also unknowable. Sicne I would like to traverse all list element combination, like 1) pick A from list 1, A from list 2, A from list 3; 2) ick A from list 1, A from list 2, B from list 3 ... for ALL permutation.
I use nested for-loop to traverse, like if I have two lists, then:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
// Do sth
}
}
If I have three lists, then:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
for (int k = 0; k < list[2].EnergyParameters.ListEnergyLevelCandidates.Count; k++)
{
// Do sth
}
}
}
Because the list numbers are unknowable, so the nest numbers are unknowable, which means, I don't know how many levels of for-loop needs to be written.
Under this kind of circumstance, how can I write code for dynamic for-loop levels? I don't want to write 10 loops for 10 lists.
In case you do not know how many lists there are, you do not write nested loops: instead, you write recursion. At each level of the invocation you loop a single list, like this:
void AllCombos(List<string>[] lists, int level, string[] current) {
if (level == lists.Length) {
// Do somthing; items of current[] contain elements of the combination
} else {
foreach (var s in lists[level]) {
current[level] = s;
AllCombos(lists, level+1, current);
}
}
}
Call AllCombos as follows:
var lists = new List<string>[10];
for (int i = 0 ; i != 10 ; i++) {
lists[i] = PopulateMyList(i);
}
string[] current = new string[lists.Length];
AllCombos(lists, 0, current);

Categories