Two element subset using c# - c#

I am trying to generate a 2-element subset of all the sets in the code.
Eg. if the list contains {1,2,3,4}, 2-element subsets will be {1,2},{1,3},{1,4},{2,3},{2,4},{3,4}.
I am stuck with the logic and cannot go further. Any help will be appreciated.
class Program
{
static List<SortedSet<string>> _items = new List<SortedSet<string>>();
static SortedSet<string> set = new SortedSet<string>();
static void Main(string[] args)
{
int i, j, a, b;
string k;
Console.WriteLine("\n Enter the number of set to be used: ");
i = Convert.ToInt32(Console.ReadLine());
for ( j = 1; j <= i; j++)
{
SortedSet<string> set = new SortedSet<string>();
do
{
Console.WriteLine("Enter first element in set {0}:", j);
k = Console.ReadLine();
if (k != "stop")
set.Add(k);
} while (k != "stop");
_items.Add(set);
}
}
public void DisplayTwoElementSets(List<string> set)
{
foreach (string item in set)
{
GenerateTwoElementSet(setNumber);
}
}
private void GenerateTwoElementSet(int setNumber)
{
SortedSet<string> originalSet = _items[setNumber];
List<SortedSet<string>> twoItemSets = new List<SortedSet<string();
foreach (string item in originalSet)
{
Console.WriteLine(item);
}
}

I'm assuming that the part you are stuck at is the Console.WriteLine(item); spot near the bottom of your code.
Your goal is to create a list of unique pair combinations across a range of values. The simplest way is to use two nested for loops, where the inner loop's index value is dependent on the outer loop's index value.
You can store these sets in Lists or Sets, but the type that will probably be the most appropriate would be the Tuple. A Tuple holds exactly the number of values you specify (in this case, 2) and maintains their order in properties with the naming scheme Item1, Item2, Item3, etc.
(Also note that you are declaring this method within the same class that holds your Main method, so for the sake of sanity, it is best to declare this as static.)
private static List<Tuple<int, int>> GenerateTwoElementSet(int setNumber)
{
List<Tuple<int, int>> set = new List<Tuple<int, int>>();
for (int i = 1; i <= setNumber; i++)
{
for (int j = i + 1; j <= setNumber; j++)
{
set.Add(new Tuple<int, int>(i, j));
}
}
return set;
}
You can get the values from the set like so:
var set = GenerateTwoElementSet(4);
foreach (var tuple in set)
{
Console.WriteLine("{" + tuple.Item1 + "," + tuple.Item2 +"}");
}
// Outputs the following:
// {1,2}
// {1,3}
// {1,4}
// {2,3}
// {2,4}
// {3,4}
EDIT: If you want to make pairs out of an existing list rather than a range of numbers, the logic is still the same. You just use the numbers from the above method as indices for your list.
private static List<Tuple<string, string>> GenerateTwoElementSetFromList(List<string> list)
{
List<Tuple<string, string>> set = new List<Tuple<string, string>>();
for (int i = 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
set.Add(new Tuple<string, string>(list[i], list[j]));
}
}
return set;
}
And you use it like so:
List<string> list = new List<string>
{
"apple",
"pear",
"orange",
"plum"
};
var set = GenerateTwoElementSetFromList(list);
foreach (var tuple in set)
{
Console.WriteLine("{" + tuple.Item1 + "," + tuple.Item2 +"}");
}
// Outputs the following:
// {apple,pear}
// {apple,orange}
// {apple,plum}
// {pear,orange}
// {pear,plum}
// {orange,plum}

Related

List.Add function adds reference to the object or adds its value in the list

I have a program to print all possible combinations from a string array. The printing is done fine on the screen. However, When I add the same to a list, all list members reflect the last generated combination. So, I am not sure what is happening. Please see the code below.
class Program
{
static List<string[]> list = new List<string[]>();
static void combinationUtil(string[] arr, string[] data,
int start, int end,
int index, int r)
{
// Current combination is
// ready to be printed,
// print it
if (index == r)
{
list.Add(data);
for (int j = 0; j < r; j++)
{
Console.Write(data[j] + " ");
}
Console.WriteLine("");
return;
}
// replace index with all
// possible elements. The
// condition "end-i+1 >=
// r-index" makes sure that
// including one element
// at index will make a
// combination with remaining
// elements at remaining positions
for (int i = start; i <= end &&
end - i + 1 >= r - index; i++)
{
data[index] = arr[i];
combinationUtil(arr, data, i + 1,
end, index + 1, r);
}
}
// The main function that prints
// all combinations of size r
// in arr[] of size n. This
// function mainly uses combinationUtil()
static void printCombination(string[] arr,
int n, int r)
{
// A temporary array to store
// all combination one by one
string[] data = new string[r];
// Print all combination
// using temprary array 'data[]'
combinationUtil(arr, data, 0,
n - 1, 0, r);
}
// Driver Code
static public void Main()
{
string[] arr = { "string-1", "string-2", "string-3", "string-4" };
int r = 2;
int n = arr.Length;
printCombination(arr, n, r);
foreach (var item in list)
{
Console.WriteLine(item[0]+" "+item[1]);
}
}
}
Following is the output
I found a way to do this. But, I am not sure if this is the only and best way to do this. If you have any other way of doing this better, please answer. Following is how I did this.
list.Add(new string[2] { data[0], data[1] });
Here is a solution using List. Note the string[] uniquePair = new string[2]; prior to each list.Add().
class Program
{
static List<string[]> list = new List<string[]>();
// Driver Code
static public void Main()
{
string[] arr = { "string-1", "string-2", "string-3", "string-4" };
int r = 2;
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
string[] uniquePair = new string[2];
uniquePair[0] = arr[i];
uniquePair[1] = arr[j];
list.Add(uniquePair);
}
}
foreach (string[] pair in list)
{
Console.WriteLine($"{ pair[0] } + { pair[1] }");
}
Console.ReadKey(true);
}
}
Output:
string-1 + string-2
string-1 + string-3
string-1 + string-4
string-2 + string-3
string-2 + string-4
string-3 + string-4

C# How to manipulate a list to build words from different chars?

I'm writing a program that takes several letters, builds words from them and return words that make sense that can be found in a word bank (like the english dictionary).
First i started with two for loops that take a letter and add to it all the other letters in ascending order: If i give (A, D, B, H) the output would be: AD, ADB, ADBH, DA, DAB, DABH etc.
var scrambledWords = new List<string>();
for (int i = 0; i < buildingMaterial.Count; i++)
{
firstBuildUp = buildingMaterial[i];
for (int j = 1; j < buildingMaterial.Count; j++)
{
if (buildingMaterial[j] == buildingMaterial[i])
continue;
firstBuildUp += buildingMaterial[j];
scrambledWords.Add(firstBuildUp);
}
}
Now i'm trying to figure out what is the best way to get all the other combinations of those letters.
Is it with more for loops but with different conditions in the condition parentheses?
Is it by creating new list for each letter and manipulate each list individually and then combining them together?
Is it by using Linq?
I am trying with more for loops with different conditions but wondering if its the best way achieving my goal.
What you are looking for is all the possible subsets of a set, or better said, the PowerSet of a set. Yo can have an extensions method to find power sets:
public static class ListExtensions
{
public static List<List<T>> PowerSet<T>(this List<T> set)
{
var n = set.Count;
var powerSetCount = 1 << n;
var result = new List<List<T>>();
for (var setMask = 0; setMask < powerSetCount; setMask++)
{
var subset = new List<T>();
for (var i = 0; i < n; i++)
{
if ((setMask & (1 << i)) > 0)
{
subset.Add(set[i]);
}
}
result.Add(subset);
}
return result;
}
}
And then use it like this
static class Program
{
static void Main()
{
var powerSet = "abc".ToList().PowerSet();
foreach (var set in powerSet)
{
// set will be a list of chars, which is equivalent to a string
Console.WriteLine($"{new string(set.ToArray())}");
}
Console.ReadLine();
}
}
The output will be:
a
b
ab
c
ac
bc
abc
Note that the empty set is also part of the PowerSet
Edit:
The string extension version:
public static class StringExtensions
{
public static List<string> PowerSet(this string str)
{
var n = str.Length;
var powerSetCount = 1 << n;
var result = new List<string>();
for (var setMask = 0; setMask < powerSetCount; setMask++)
{
var subset = new StringBuilder();
for (var i = 0; i < n; i++)
{
if ((setMask & (1 << i)) > 0)
{
subset.Append(str[i]);
}
}
result.Add(subset.ToString());
}
return result;
}
}

How to do a job ForEach element of 2d array without For loop?

I need to know How to modify or how to initialize all element of 2d array without For loop?
I mean how to do it using Extension methods or Using LINQ!?
I was trying to do it using "IEnumerable.Cast<>" extension but there is no result!
And I don`t know why?
string[,] m2d = new string[8, 8];
Array.ForEach(m2d.Cast<string>().ToArray(), el => el = "sample1");
There was no result even with for loop...
for (int i = 0; i <= m2d.Cast<string>().ToArray().GetUpperBound(0); i++)
{
m2d.Cast<string>().ToArray()[i] = "sample2";
}
But please forget this for loop!
Just try to do it using one line expression!
like this one which does not work...
m2d.Cast<string>().ToList().ForEach(el => el = "sample3");
Thank you!
It doesn't work because with assignment you just replace value in a collection created by ToList() or ToArray() method with a new one. Because both these methods actually return new collection, your starting array isn't affected by the change you're making.
The most obvious way, of course, is to use two nested for loops. Not sure why you avoid them but If you really want to use ForEach you could enumerate indices of your array's dimensions, and not it's elements, in kind of a functional approach. Something like this:
Enumerable.Range(0, m2d.GetUpperBound(0) + 1).ToList()
.ForEach(i => Enumerable.Range(0, m2d.GetUpperBound(1) + 1).ToList()
.ForEach(j => m2d[i, j] = "sample"));
While #Dmitry's answer pretty much covers why the original attempt has failed and what you should do to rectify, nonetheless, depending on your requirements, you may also want to consider wrapping each item/index in the array into some referential type, that is able to change the original array items:
public class MultiDimensionArrayItemReference<T>
{
private readonly Array _array;
private readonly Int32[] _indices;
public MultiDimensionArrayItemReference(Array array, params Int32[] indices)
{
if (array == null)
throw new ArgumentNullException(paramName: nameof(array));
if (indices == null)
throw new ArgumentNullException(paramName: nameof(indices));
this._array = array;
this._indices = indices;
}
public IReadOnlyCollection<Int32> Indices
{
get
{
return this._indices.ToList().AsReadOnly();
}
}
public T Value
{
get
{
return (T)this._array.GetValue(this._indices);
}
set
{
this._array.SetValue(value, this._indices);
}
}
public override string ToString()
{
return $"[{String.Join(", ", this._indices)}]:{this.Value}";
}
}
public static class MultiDimensionArrayItemReferenceExtensions
{
// That's for the two-dimensional array, but with some effort it can be generalized to support any arrays.
public static IEnumerable<MultiDimensionArrayItemReference<T>> EnumerateReferenceElements<T>(this T[,] array)
{
if (array == null)
throw new ArgumentNullException(paramName: nameof(array));
// Assume zero-based
var rows = array.GetLength(0);
var columns = array.GetLength(1);
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
yield return new MultiDimensionArrayItemReference<T>(
array,
row,
col);
}
}
}
}
...
private static void PrintArray<T>(T[,] array)
{
// Assume zero-based
var rows = array.GetLength(0);
var columns = array.GetLength(1);
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
Console.Write("{0, 7}", array[row, col]);
}
Console.WriteLine();
}
}
...
var array = new [,]
{
{ "a1", "a2" },
{ "b1", "b2" }
};
PrintArray(array);
Console.WriteLine();
var elements = array
.EnumerateReferenceElements()
.ToList();
foreach (var elem in elements)
{
Console.WriteLine(elem);
}
elements.ForEach(
elem =>
elem.Value = elem.Value + "_n");
Console.WriteLine();
PrintArray(array);
It will result in the following output:
a1 a2
b1 b2
[0, 0]:a1
[0, 1]:a2
[1, 0]:b1
[1, 1]:b2
a1_n a2_n
b1_n b2_n
It is not very efficient due to the need to store each item's indices, but still a possibile solution for some rare cases.

Sorting a List<int>

Using C# what is the best way to sort a List numerically?
my list has items 5,7,3 and I would like them sorted 3,5,7. I know some longer ways, but I would imagine linq has a quicker way?
sorry this was end of day, my mind is else where it worked, didn't see it change the first time:(
There's no need for LINQ here, just call Sort:
list.Sort();
Example code:
List<int> list = new List<int> { 5, 7, 3 };
list.Sort();
foreach (int x in list)
{
Console.WriteLine(x);
}
Result:
3
5
7
Keeping it simple is the key.
Try Below.
var values = new int[5,7,3];
values = values.OrderBy(p => p).ToList();
var values = new int[] {5,7,3};
var sortedValues = values.OrderBy(v => v).ToList(); // result 3,5,7
List<int> list = new List<int> { 5, 7, 3 };
list.Sort((x,y)=> y.CompareTo(x));
list.ForEach(action => { Console.Write(action + " "); });
Sort a list of integers descending
class Program
{
private class SortIntDescending : IComparer<int>
{
int IComparer<int>.Compare(int a, int b) //implement Compare
{
if (a > b)
return -1; //normally greater than = 1
if (a < b)
return 1; // normally smaller than = -1
else
return 0; // equal
}
}
static List<int> intlist = new List<int>(); // make a list
static void Main(string[] args)
{
intlist.Add(5); //fill the list with 5 ints
intlist.Add(3);
intlist.Add(5);
intlist.Add(15);
intlist.Add(7);
Console.WriteLine("Unsorted list :");
Printlist(intlist);
Console.WriteLine();
// intlist.Sort(); uses the default Comparer, which is ascending
intlist.Sort(new SortIntDescending()); //sort descending
Console.WriteLine("Sorted descending list :");
Printlist(intlist);
Console.ReadKey(); //wait for keydown
}
static void Printlist(List<int> L)
{
foreach (int i in L) //print on the console
{
Console.WriteLine(i);
}
}
}
Sort list of int descending you could just sort first and reverse
class Program
{
static void Main(string[] args)
{
List<int> myList = new List<int>();
myList.Add(38);
myList.Add(34);
myList.Add(35);
myList.Add(36);
myList.Add(37);
myList.Sort();
myList.Reverse();
myList.ForEach(Console.WriteLine);
}
}
double jhon = 3;
double[] numbers = new double[3];
for (int i = 0; i < 3; i++)
{
numbers[i] = double.Parse(Console.ReadLine());
}
Console.WriteLine("\n");
Array.Sort(numbers);
for (int i = 0; i < 3; i++)
{
Console.WriteLine(numbers[i]);
}
Console.ReadLine();

Check for missing number in sequence

I have an List<int> which contains 1,2,4,7,9 for example.
I have a range from 0 to 10.
Is there a way to determine what numbers are missing in that sequence?
I thought LINQ might provide an option but I can't see one
In the real world my List could contain 100,000 items so performance is key
var list = new List<int>(new[] { 1, 2, 4, 7, 9 });
var result = Enumerable.Range(0, 10).Except(list);
Turn the range you want to check into a HashSet:
public IEnumerable<int> FindMissing(IEnumerable<int> values)
{
HashSet<int> myRange = new HashSet<int>(Enumerable.Range(0,10));
myRange.ExceptWith(values);
return myRange;
}
Will return the values that aren't in values.
Using Unity i have tested two solutions on set of million integers. Looks like using Dictionary and two "for" loops gives better result than Enumerable.Except
FindMissing1 Total time: 0.1420 (Enumerable.Except)
FindMissing2 Total time: 0.0621 (Dictionary and two for loops)
public static class ArrayExtension
{
public static T[] FindMissing1<T>(T[] range, T[] values)
{
List<T> result = Enumerable.Except<T>(range, values).ToList<T>();
return result.ToArray<T>();
}
public static T[] FindMissing2<T>(T[] range, T[] values)
{
List<T> result = new List<T>();
Dictionary<T, T> hash = new Dictionary<T, T>(values.Length);
for (int i = 0; i < values.Length; i++)
hash.Add(values[i], values[i]);
for (int i = 0; i < range.Length; i++)
{
if (!hash.ContainsKey(range[i]))
result.Add(range[i]);
}
return result.ToArray<T>();
}
}
public class ArrayManipulationTest : MonoBehaviour
{
void Start()
{
int rangeLength = 1000000;
int[] range = Enumerable.Range(0, rangeLength).ToArray();
int[] values = new int[rangeLength / 5];
int[] missing;
float start;
float duration;
for (int i = 0; i < rangeLength / 5; i ++)
values[i] = i * 5;
start = Time.realtimeSinceStartup;
missing = ArrayExtension.FindMissing1<int>(range, values);
duration = Time.realtimeSinceStartup - start;
Debug.Log($"FindMissing1 Total time: {duration:0.0000}");
start = Time.realtimeSinceStartup;
missing = ArrayExtension.FindMissing2<int>(range, values);
duration = Time.realtimeSinceStartup - start;
Debug.Log($"FindMissing2 Total time: {duration:0.0000}");
}
}
List<int> selectedNumbers = new List<int>(){8, 5, 3, 12, 2};
int firstNumber = selectedNumbers.OrderBy(i => i).First();
int lastNumber = selectedNumbers.OrderBy(i => i).Last();
List<int> allNumbers = Enumerable.Range(firstNumber, lastNumber - firstNumber + 1).ToList();
List<int> missingNumbers = allNumbers.Except(selectedNumbers).ToList();
foreach (int i in missingNumbers)
{
Response.Write(i);
}
LINQ's Except method would be the most readable. Whether it performs adequately for you or not would be a matter for testing.
E.g.
range.Except(listOfValues);
Edit
Here's the program I used for my mini-benchmark, for others to plug away with:
static void Main()
{
var a = Enumerable.Range(0, 1000000);
var b = new List<int>();
for (int i = 0; i < 1000000; i += 10)
{
b.Add(i);
}
Stopwatch sw = new Stopwatch();
sw.Start();
var c = a.Except(b).ToList();
sw.Stop();
Console.WriteLine("Milliseconds {0}", sw.ElapsedMilliseconds );
sw.Reset();
Console.ReadLine();
}
An alternative method which works in general for any two IEnunumerable<T> where T :IComparable. If the IEnumerables are both sorted, this works in O(1) memory (i.e. there is no creating another ICollection and subtracting, etc.) and in O(n) time.
The use of IEnumerable<IComparable> and GetEnumerator makes this a little less readable, but far more general.
Implementation
/// <summary>
/// <para>For two sorted IEnumerable<T> (superset and subset),</para>
/// <para>returns the values in superset which are not in subset.</para>
/// </summary>
public static IEnumerable<T> CompareSortedEnumerables<T>(IEnumerable<T> superset, IEnumerable<T> subset)
where T : IComparable
{
IEnumerator<T> supersetEnumerator = superset.GetEnumerator();
IEnumerator<T> subsetEnumerator = subset.GetEnumerator();
bool itemsRemainingInSubset = subsetEnumerator.MoveNext();
// handle the case when the first item in subset is less than the first item in superset
T firstInSuperset = superset.First();
while ( itemsRemainingInSubset && supersetEnumerator.Current.CompareTo(subsetEnumerator.Current) >= 0 )
itemsRemainingInSubset = subsetEnumerator.MoveNext();
while ( supersetEnumerator.MoveNext() )
{
int comparison = supersetEnumerator.Current.CompareTo(subsetEnumerator.Current);
if ( !itemsRemainingInSubset || comparison < 0 )
{
yield return supersetEnumerator.Current;
}
else if ( comparison >= 0 )
{
while ( itemsRemainingInSubset && supersetEnumerator.Current.CompareTo(subsetEnumerator.Current) >= 0 )
itemsRemainingInSubset = subsetEnumerator.MoveNext();
}
}
}
Usage
var values = Enumerable.Range(0, 11);
var list = new List<int> { 1, 2, 4, 7, 9 };
var notIncluded = CompareSortedEnumerables(values, list);
If the range is predictable I suggest the following solution:
public static void Main()
{
//set up the expected range
var expectedRange = Enumerable.Range(0, 10);
//set up the current list
var currentList = new List<int> {1, 2, 4, 7, 9};
//get the missing items
var missingItems = expectedRange.Except(currentList);
//print the missing items
foreach (int missingItem in missingItems)
{
Console.WriteLine(missingItem);
}
Console.ReadLine();
}
Regards,
y00daa
This does not use LINQ but it works in linear time.
I assume that input list is sorted.
This takes O(list.Count).
private static IEnumerable<int> get_miss(List<int> list,int length)
{
var miss = new List<int>();
int i =0;
for ( i = 0; i < list.Count - 1; i++)
{
foreach (var item in
Enumerable.Range(list[i] + 1, list[i + 1] - list[i] - 1))
{
yield return item;
}
}
foreach (var item in Enumerable.Range(list[i]+1,length-list[i]))
{
yield return item;
}
}
This should take O(n) where n is length of full range.
static void Main()
{
List<int> identifiers = new List<int>() { 1, 2, 4, 7, 9 };
Stopwatch sw = new Stopwatch();
sw.Start();
List<int> miss = GetMiss(identifiers,150000);
sw.Stop();
Console.WriteLine("{0}",sw.ElapsedMilliseconds);
}
private static List<int> GetMiss(List<int> identifiers,int length)
{
List<int> miss = new List<int>();
int j = 0;
for (int i = 0; i < length; i++)
{
if (i < identifiers[j])
miss.Add(i);
else if (i == identifiers[j])
j++;
if (j == identifiers.Count)
{
miss.AddRange(Enumerable.Range(i + 1, length - i));
break;
}
}
return miss;
}
Ok, really, create a new list which parallels the initial list and run the method Except over it...
I have created a fully linq answer using the Aggregate method instead to find the missings:
var list = new List<int>(new[] { 1, 2, 4, 7, 9 }); // Assumes list is ordered at this point
list.Insert(0, 0); // No error checking, just put in the lowest and highest possibles.
list.Add(10); // For real world processing, put in check and if not represented then add it/them.
var missing = new List<int>(); // Hold any missing values found.
list.Aggregate ((seed, aggr) => // Seed is the previous #, aggr is the current number.
{
var diff = (aggr - seed) -1; // A difference between them indicates missing.
if (diff > 0) // Missing found...put in the missing range.
missing.AddRange(Enumerable.Range((aggr - diff), diff));
return aggr;
});
The missing list has this after the above code has been executed:
3, 5, 6, 8
for a List L a general solution (works in all programming languages) would be simply
L.Count()*(L.Count()+1)/2 - L.Sum();
which returns the expected sum of series minus the actual series.
for a List of size n the missing number is:
n(n+1)/2 - (sum of list numbers)
this method here returns the number of missing elements ,sort the set , add all elements from range 0 to range max , then remove the original elements , then you will have the missing set
int makeArrayConsecutive(int[] statues)
{
Array.Sort(statues);
HashSet<int> set = new HashSet<int>();
for(int i = statues[0]; i< statues[statues.Length -1]; i++)
{
set.Add(i);
}
for (int i = 0; i < statues.Length; i++)
{
set.Remove(statues[i]);
}
var x = set.Count;
return x;
// return set ; // use this if you need the actual elements + change the method return type
}
Create an array of num items
const int numItems = 1000;
bool found[numItems] = new bool[numItems];
List<int> list;
PopulateList(list);
list.ForEach( i => found[i] = true );
// now iterate found for the numbers found
for(int count = 0; i < numItems; ++numItems){
Console.WriteList("Item {0} is {1}", count, found[count] ? "there" : "not there");
}
This method does not use LINQ and works in general for any two IEnunumerable<T> where T :IComparable
public static IEnumerable<T> FindMissing<T>(IEnumerable<T> superset, IEnumerable<T> subset) where T : IComparable
{
bool include = true;
foreach (var i in superset)
{
foreach (var j in subset)
{
include = i.CompareTo(j) == 0;
if (include)
break;
}
if (!include)
yield return i;
}
}
int sum = 0,missingNumber;
int[] arr = { 1,2,3,4,5,6,7,8,9};
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
}
Console.WriteLine("The sum from 1 to 10 is 55");
Console.WriteLine("Sum is :" +sum);
missingNumber = 55 - sum;
Console.WriteLine("Missing Number is :-"+missingNumber);
Console.ReadLine();

Categories