I want to make a simple program (lottery numbers generator) that takes numbers within a specific range and shuffles them "n" number of times, after each shuffle it selects one random number and moves it from the list of a given range to a new list, and does this for "n" number of times (until it selects specific amount of numbers, 7 to be exact). I have found an algorithm that does exactly that (an extension method or shuffling generic lists). But I'm not that into programming and I have a problem with displaying the results (the list with the drawn numbers) to a TextBox or Label, however I have got it to work with a MessageBox. But with TextBox/Label I get the error "The name * does not exist in current context". I've googled for a solution but no help what so ever.
Here's the code:
private void button1_Click(object sender, EventArgs e)
{
List<int> numbers;
numbers = Enumerable.Range(1, 39).ToList();
numbers.Shuffle();
}
private void brojevi_TextChanged(object sender, EventArgs e)
{
}
}
}
/// <summary>
/// Class for shuffling lists
/// </summary>
/// <typeparam name="T">The type of list to shuffle</typeparam>
public static class ListShufflerExtensionMethods
{
//for getting random values
private static Random _rnd = new Random();
/// <summary>
/// Shuffles the contents of a list
/// </summary>
/// <typeparam name="T">The type of the list to sort</typeparam>
/// <param name="listToShuffle">The list to shuffle</param>
/// <param name="numberOfTimesToShuffle">How many times to shuffle the list, by default this is 5 times</param>
public static void Shuffle<T>(this List<T> listToShuffle, int numberOfTimesToShuffle = 7)
{
//make a new list of the wanted type
List<T> newList = new List<T>();
//for each time we want to shuffle
for (int i = 0; i < numberOfTimesToShuffle; i++)
{
//while there are still items in our list
while (listToShuffle.Count >= 33)
{
//get a random number within the list
int index = _rnd.Next(listToShuffle.Count);
//add the item at that position to the new list
newList.Add(listToShuffle[index]);
//and remove it from the old list
listToShuffle.RemoveAt(index);
}
//then copy all the items back in the old list again
listToShuffle.AddRange(newList);
//display contents of a list
string line = string.Join(",", newList.ToArray());
brojevi.Text = line;
//and clear the new list
//to make ready for next shuffling
newList.Clear();
break;
}
}
}
}
The problem is that brojevi (either TextBox or Label) isn't defined in the scope of the extension method, it is a Control so it should be defined in your Form. So, when you shuffle your numbers, put them in the TextBox during the execution of the button1_Click event handler
Remove the lines:
string line = string.Join(",", newList.ToArray());
brojevi.Text = line;
EDIT:
You could change the extension method like this to return the string of drawn items or list of drawn items. Lets go for the list because you might want to use the numbers for other things. Also, I don't see the point in shuffling 7 times because you will be able to see only last shuffling. Therefore I think that one is enough. Check the code:
public static List<T> Shuffle<T>(this List<T> listToShuffle)
{
//make a new list of the wanted type
List<T> newList = new List<T>();
//while there are still items in our list
while (listToShuffle.Count >= 33)
{
//get a random number within the list
int index = _rnd.Next(listToShuffle.Count);
//add the item at that position to the new list
newList.Add(listToShuffle[index]);
//and remove it from the old list
listToShuffle.RemoveAt(index);
}
//then copy all the items back in the old list again
listToShuffle.AddRange(newList);
return newList;
}
And in button1_Click1 event handler we can have:
List<int> numbers;
numbers = Enumerable.Range(1, 39).ToList();
List<int> drawnNumbers = numbers.Shuffle();
string line = string.Join(",", drawnNumbers.ToArray());
brojevi.Text = line;
ListShufflerExtensionMethods doesn't know about your textbox (brojevi) because it's out of scope. You could restructure and make Shuffle return a value, then set the value of the textbox' text in callers scope.
Related
Note: There is quite a bit of text here but its additional information that may or may not be required. If I don't include this, then responders ask for more information or make suggestions for approaches that may not work, due to my entire implementation. If there is a better way to structure this so that all information is available, please let me know the best way to provide this supporting information. The gist is that I am trying to is here:
I am building a program that will read files and determine an organization (internal org code) to associate each file to, based on a predefined list of orgs and how often each org shows up in the file. The basic premise and current manual solution is:
Manual Process
Receive files in an unusual but overall consistent data format.
Each file has data pertaining to an organization's transactions (inbound and outbound types)
Each row in the file represents a single transaction; however, the fields are not always in the same order.
Goal is to determine which org "owns" the transactions (the entire file will be associated with this org at the end)
To be determined as the transaction "owner", the org in question must show up the same amount of times on each row (e.g. if Org1 shows up twice on Row 1 and once on Row 2, it can't be our Org due to inconsistency).
Nearly 100% of the time, the correctly associated Org has the highest frequency in the file, consistent across every row checked so programming this will give us a 99% solution. We can refine it further, if needed, once these rules are implemented
So far in my project, I have implemented a class with the following members:
My class thus far (summary of all logic at this point):
Properties/fields
_orgArray - list of orgs to look for in each file
_orgLength - length of org code (used for iterating over character in file line and creating a buffer of specified length to check if buffer value contains org)
Methods
GetDictIntersects - accepts two dictionaries and returns a dictionary containing keys and values that exist in both input dictionaries
GetLinesFromFile - iterator that reads a file and yields a single lines from the file each iteration
GetOrgCounts - accepts a line of text (returned from GetLinesFromFile) and returns a dictionary containing each Org and its count of occurrences in the line of text
ReduceOrgArray - accepts a two dictionaries containing Org Counts (returned by GetOrgCounts) as well as an array of Orgs. Returns a new array of orgs having removed any entries that did not have consistencies amongst them (using GetDictIntersects) as well as any orgs that did not have any values > 0 (indicating no occurrences in lines of text)
What the DetermineOrg method should do
To determine an Org for each file, I'm working on a method named DetermineOrg. My goal is to utilize the above methods and properties to
starts with org array containing all potential orgs
iterates the specified file (using GetLinesFromFile)
reduces org array by removing orgs that don't meet criteria on each line by comparing the current line's org counts (returned from GetOrgCounts) with the previous line's org counts (using GetDictIntersects and ReduceOrgArray)
Once file is iterated, if only a single Org remains in array, that is the return value
If multiple Orgs remain, Org with highest count is returned. If there is a tie, then Org (that tied with Max count) that shows up first in _orgArray is the return value
However, I can't seem to figure out the logic of how structure this so that I can recursively implement this. My code for the method alone in question (in case you don't want the entire class) is below. Hopefully someone can point out what I'm doing incorrectly and point me in the right direction:
Stuck on this method:
/// <summary>
/// Determine the appropriate organization for specified file
/// Recursively apply the following business rules:
/// <list type="number">
/// <item>Initial run uses all Orgs</item>
/// <item>Get Org Counts for each org on a line-by-line basis</item>
/// <item>Compare each line's Org Counts with the previous line's Org Counts, removing any orgs from potential org list that do not have same counts on both lines</item>
/// <item>After entire file has been read, determine a single Org by identifying which Org has the most occurences (highest value in dict)</item>
/// <item>In case of ties, class member org array lists order of precedence. Org with lowest index takes precedence.</item>
/// </list>
/// </summary>
/// <param name="filePath"><c>string</c> - file to be processed</param>
/// <param name="numLines"><c>int</c>:
/// Number of lines to be read from file in order to determine associated org.
/// Value less than 1 indicates to read the entire file.
/// Default value is -1 (read entire file to determine associated org).
/// </param>
/// <param name="orgArray"><c>string[]</c> representing potential orgs that file may be associated with</param>
/// <param name="streamReader"><c>StreamReader</c> stream to specified file (read-only)</param>
/// <param name="prevOrgCounts"><c>int</c> representing Org Counts for previous line of text</param>
/// <returns><c>string</c> - represents org that file is associated with</returns>
public static string DetermineOrg(string filePath, int numLines = -1, string[] orgArray = null, IEnumerable<string> streamReader = null, Dictionary<string, int> prevOrgCounts = null)
{
// base condition - no streamreader exists yet
if (streamReader == null)
{
streamReader = GetLinesFromFile(filePath, numLines);
// if no orgArray value is set, then use class member as starting value
if (orgArray == null)
{
orgArray = _orgArray;
}
}
else
{
// get org counts from iterator
foreach (string line in streamReader)
{
Dictionary<string, int> currentOrgCounts = GetOrgCounts(line, orgArray);
// if we have previous and current counts, then get reduce orgs
if (prevOrgCounts != null)
{
orgArray = ReduceOrgArray(currentOrgCounts, prevOrgCounts, orgArray);
}
else
{
}
}
}
// base condition - if no counts yet, then get counts from filePath
if (prevOrgCounts == null)
{
foreach (string line in GetLinesFromFile(filePath, numLines))
{
prevOrgCounts = GetOrgCounts(filePath, _orgArray);
}
}
}
Entire Class / All Code
The entire class can be found below.
using System;
namespace OrgProcessor
{
internal class OrgProcessor
{
/// <summary>
/// <c>string[]</c> containing list of orgs in order of precedence. In case of ties between counts, order with lowest index takes precedence in org determination.
/// </summary>
static string[] _orgArray = { "Org1", "Org2", "Org3"};
/// <summary>
/// Length of Org (is consistent amongst orgs as each org is an "org code" representing an org that can be found in a lookup table.
/// </summary>
static byte _orgLength = 4;
/// <summary>
/// Compare 2 dictionaries and return a dictionary containing only keys and values that exist in both dictionaries.
/// </summary>
/// <param name="dictionary1"><c>Dictionary<string, int></c></param>
/// <param name="dictionary2"><c>Dictionary<string, int></param>
/// <returns><c>Dictionary<string, int> - New dictionary containing key-value pairs that exist in both input dictionaries</returns>
public static Dictionary<string, int> GetDictIntersects(Dictionary<string, int> dictionary1, Dictionary<string, int> dictionary2)
{
// only return entries that exist in both dictionaries
Dictionary<string, int> returnDict = new Dictionary<string, int>();
foreach (dynamic key in dictionary1.Keys)
{
// ensure key exists in other dictionary's keys AND values match in both dictionaries
if (dictionary2.ContainsKey(key))
{
if (dictionary2[key] == dictionary1[key])
{
returnDict.Add(key, dictionary1[key]);
}
}
}
return returnDict;
}
/// <summary>
/// Iterator method returning file content, line by line
/// </summary>
/// <param name="filePath"><c>string</c> - path to file to read from</param>
/// <param name="numLines"><c>int</c> - number of lines to read from the file. Negative numbers will be interpreted as "All Lines". Default value is -1 (Read "All" lines)</param>
/// <returns><c>IEnumerable</c><<c>string</c>></returns>
public static IEnumerable<string> GetLinesFromFile(string filePath, int numLines = -1)
{
// TODO: Make more generic so iterator can take instructions to manipulate lines in file
// and optionally write to file (would need to write to temp, then delete orig and rename temp
// track lines iterated
int i = 0;
// create reader
using (StreamReader reader = new StreamReader(filePath))
{
// yield line if not reached end of file AND
// num lines is not specified (i == -1) OR
// i (num lines return) has not exceeded num lines specified
while (!reader.EndOfStream && (i < numLines || numLines == -1))
{
yield return reader.ReadLine();
i++;
}
}
}
/// <summary>
/// Get number of times each org occurs in specified text
/// </summary>
/// <param name="lineOfText"><c>string</c> of text to process</param>
/// <param name="orgArray"><c>string[]</c> containing orgs to be counted</param>
/// <returns><c>Dictionary<string, int></c> containing each Org and number of occurences in specified text</returns>
public static Dictionary<string, int> GetOrgCounts(string lineOfText, string[] orgArray)
{
// instantiate return value
Dictionary<string, int> orgCounts = new Dictionary<string, int>();
// get length of line of text as it will be referenced multiple times
int textLength = lineOfText.Length;
foreach (string org in orgArray)
{
//// set matchCount to 0
//// int matchCount = 0;
// since orgs are 4 characters long, iterate each character and compare with next 3 characters for each
for(int i = 0; i < textLength; i ++)
{
// get character at index
char c = lineOfText[i];
// calculate remaining characters
int remainingChars = textLength - i;
// char can only be part of an org if enough characters remain in lineOfText
if (remainingChars >= _orgLength)
{
// Get amount of chars that equals org length
string curCharBuffer = lineOfText.Substring(i, _orgLength);
// if characters match current org, then increment count dictionary
// or add to dict with count of 1
if (curCharBuffer == org)
{
if (orgCounts.ContainsKey(org))
{
orgCounts[org] += 1;
}
else
{
orgCounts.Add(org, 1);
}
// no need to evaluate other characters that were part of org so adjust loop incrementer to start next iteration after buffer
i += curCharBuffer.Length - 1;
}
}
}
//// orgCounts[org] = matchCount;
}
return orgCounts;
}
/// <summary>
/// Accepts 2 dictionaries (containing orgs and associated counts) and an array of strings (representing potential orgs) and returns a new string array having removed any "invalid" strings based on specified business rules:
/// <list type="number">
/// <item>If no orgs exist in array, return empty array</item>
/// </list>
/// </summary>
/// <param name="dictA"><c>Dictionary<string, int> containing orgs and counts</c></param>
/// <param name="dictB"><c>Dictionary<string, int> containing orgs and counts</c></param>
/// <param name="orgArray"><c>string[]</c> portential orgs</param>
/// <returns><c>string[]</c> - represents potential orgs</returns>
public static string[] ReduceOrgArray(Dictionary<string, int> dictA, Dictionary<string, int> dictB, string[] orgArray)
{
// base condition - if orgArray is empty, then return as is
if (orgArray.Length == 0)
{
return orgArray;
}
// Return value
List<string> remainingOrgs= new List<string>();
// business rules require that org counts be same from record to record
// we can rule out potential orgs by removing those with inconsistent counts amongst records
Dictionary<string, int> remainingDict = GetDictIntersects(dictA, dictB);
// Iterate over remaining orgs
// remove those that don't have matching keys in remaining dict (showing inconsistency amongst recs)
// remove those with 0 counts (org must exist on all rows)
foreach (string org in orgArray)
{
if (remainingDict.ContainsKey(org))
{
if (remainingDict[org] > 0)
{
remainingOrgs.Add(org);
}
}
}
// return remainingOrgs as array
return remainingOrgs.ToArray();
}
/// <summary>
/// Determine the appropriate organization for specified file
/// Recursively apply the following business rules:
/// <list type="number">
/// <item>Initial run uses all Orgs</item>
/// <item>Get Org Counts for each org on a line-by-line basis</item>
/// <item>Compare each line's Org Counts with the previous line's Org Counts, removing any orgs from potential org list that do not have same counts on both lines</item>
/// <item>After entire file has been read, determine a single Org by identifying which Org has the most occurences (highest value in dict)</item>
/// <item>In case of ties, class member org array lists order of precedence. Org with lowest index takes precedence.</item>
/// </list>
/// </summary>
/// <param name="filePath"><c>string</c> - file to be processed</param>
/// <param name="numLines"><c>int</c>:
/// Number of lines to be read from file in order to determine associated org.
/// Value less than 1 indicates to read the entire file.
/// Default value is -1 (read entire file to determine associated org).
/// </param>
/// <param name="orgArray"><c>string[]</c> representing potential orgs that file may be associated with</param>
/// <param name="streamReader"><c>StreamReader</c> stream to specified file (read-only)</param>
/// <param name="prevOrgCounts"><c>int</c> representing Org Counts for previous line of text</param>
/// <returns><c>string</c> - represents org that file is associated with</returns>
public static string DetermineOrg(string filePath, int numLines = -1, string[] orgArray = null, IEnumerable<string> streamReader = null, Dictionary<string, int> prevOrgCounts = null)
{
// base condition - no streamreader exists yet
if (streamReader == null)
{
streamReader = GetLinesFromFile(filePath, numLines);
// if no orgArray value is set, then use class member as starting value
if (orgArray == null)
{
orgArray = _orgArray;
}
}
else
{
// get org counts from iterator
foreach (string line in streamReader)
{
Dictionary<string, int> currentOrgCounts = GetOrgCounts(line, orgArray);
// if we have previous and current counts, then get reduce orgs
if (prevOrgCounts != null)
{
orgArray = ReduceOrgArray(currentOrgCounts, prevOrgCounts, orgArray);
}
else
{
}
}
}
// base condition - if no counts yet, then get counts from filePath
if (prevOrgCounts == null)
{
foreach (string line in GetLinesFromFile(filePath, numLines))
{
prevOrgCounts = GetOrgCounts(filePath, _orgArray);
}
}
}
}
}
If I understood your code correctly, you only keep track of the current list of candidates, but not the ocurrence count so you have nothing to compare to.
Here is my solution:
string[] orgs = { "ORG1", "ORG2", "ORG3"};
// This array will hold
// - either the number of times the corresponding organisation name occurs in each line
// - or 0 if the corresponding organisation name does not occur in any line
// or occurs with different count in some lines
var orgCounts = new int[orgs.Length];
var readLines = 0; // the number of lines read so far (used to recognize the first line)
foreach (var line in File.ReadLines(fileName))
{
for (var i = 0; i < orgs.Length; i++)
{
// count the occurrences of orgs[i] in the read line
var count = CountOccurrences(line, orgs[i]);
if (readLines == 0)
{
// first line: just remember the count of occurrences
orgCounts[i] = count;
}
else if (orgCounts[i] != count)
{
// mismatch, set count to 0
orgCounts[i] = 0;
}
readLines++;
}
}
// helper function to count the occurrences of toFind in str
int CountOccurrences(string str, string toFind)
{
var count = 0;
var index = str.IndexOf(toFind);
while (index >= 0)
{
count++;
index = str.IndexOf(toFind, index+1);
}
return count;
}
This is the solution that worked. This was basically the final piece to the puzzle and now everything fits together:
public static string DetermineOrg(string filePath)
{
// Initialize variables to store previous line's org counts and current list of potential orgs
Dictionary<string, int> previousLineOrgCounts = null;
string[] potentialOrgs = _orgArray;
// Iteratve over the file's lines using the GetLinesFromFile method
foreach(string line in GetLinesFromFile(filePath))
{
// Get the org counts for the current line
Dictionary<string, int> currentLineOrgCounts = GetOrgCounts(line, potentialOrgs);
// Check if this is not the first line of the file
if (previousLineOrgCounts != null)
{
// reduce the list of potential orgs using the current and previous line org counts
potentialOrgs = ReduceOrgArray(previousLineOrgCounts, currentLineOrgCounts, potentialOrgs);
}
// update the previous line or g counts for the next iteration
previousLineOrgCounts = currentLineOrgCounts;
}
// Check if only one org remains in the potential orgs list
if(potentialOrgs.Length == 1)
{
// return the remaining org
return potentialOrgs[0];
}
else
{
// Initialize variables to store the max org count and the org with the max count
int maxOrgCount = 0;
string orgWithMaxCount = null;
// Iterate over the remaining potential orgs
foreach (string org in potentialOrgs)
{
// Check if the current org has a higher count that the previous max count
if (previousLineOrgCounts[org] > maxOrgCount)
{
// update the max org count and the org with the max count
maxOrgCount = previousLineOrgCounts[org];
orgWithMaxCount = org;
}
}
// Return the org with the max count
return orgWithMaxCount;
}
}
I have a method that yields an IEnumerable, but it uses the yield keyword to return elements when executed. I don't always know how big the total collection is. It's kind of similar to the standard Fibonacci example when you go to Try .NET except that it will yield a finite number of elements. That being said, because there's no way of knowing how many elements it will return beforehand, it could keep yielding pretty much forever if there are too many.
When I looked for other questions about this topic here, one of the answers provided a clean LINQ query to randomly sample N elements from a collection. However, the assumption here was that the collection was static. If you go to the Try .NET website and modify the code to use the random sampling implementation from that answer, you will get an infinite loop.
public static void Main()
{
foreach (var i in Fibonacci().OrderBy(f => Guid.NewGuid()).Take(20))
{
Console.WriteLine(i);
}
}
The query tries to order all the elements in the returned IEnumerable, but to order all the elements it must first calculate all the elements, of which there are an infinite number, which means it will keep going on and on and never return an ordered collection.
So what would be a good strategyfor randomly sampling an IEnumerable with an unknown number of contained elements? Is it even possible?
If a sequence is infinite in length, you can't select N elements from it in less than infinite time where the chance of each element in the sequence being selected is the same.
However it IS possible to select N items from a sequence of unknown, but finite, length. You can do that using reservoir sampling.
Here's an example implementation:
/// <summary>
/// This uses Reservoir Sampling to select <paramref name="n"/> items from a sequence of items of unknown length.
/// The sequence must contain at least <paramref name="n"/> items.
/// </summary>
/// <typeparam name="T">The type of items in the sequence from which to randomly choose.</typeparam>
/// <param name="items">The sequence of items from which to randomly choose.</param>
/// <param name="n">The number of items to randomly choose from <paramref name="items"/>.</param>
/// <param name="rng">A random number generator.</param>
/// <returns>The randomly chosen items.</returns>
public static T[] RandomlySelectedItems<T>(IEnumerable<T> items, int n, System.Random rng)
{
// See http://en.wikipedia.org/wiki/Reservoir_sampling for details.
var result = new T[n];
int index = 0;
int count = 0;
foreach (var item in items)
{
if (index < n)
{
result[count++] = item;
}
else
{
int r = rng.Next(0, index + 1);
if (r < n)
result[r] = item;
}
++index;
}
if (index < n)
throw new ArgumentException("Input sequence too short");
return result;
}
This must still iterate over the entire sequence, however, so it does NOT work for an infinitely long sequence.
If you want to support input sequences longer than 2^31, you can use longs in the implementation like so:
public static T[] RandomlySelectedItems<T>(IEnumerable<T> items, int n, System.Random rng)
{
// See http://en.wikipedia.org/wiki/Reservoir_sampling for details.
var result = new T[n];
long index = 0;
int count = 0;
foreach (var item in items)
{
if (index < n)
{
result[count++] = item;
}
else
{
long r = rng.NextInt64(0, index + 1);
if (r < n)
result[r] = item;
}
++index;
}
if (index < n)
throw new ArgumentException("Input sequence too short");
return result;
}
Note that this implementation requires .Net 6.0 or higher because of the rng.NextInt64().
Also note that there's no point in making n long because you can't have an array that exceeds ~2^31 elements, so it wouldn't be possible to fill it. You could in theory fix that by returning multiple arrays, but I'll leave that as an exercise for the reader. ;)
I want to create a code that when button 1 is clicked :
creates a list with items (ex : 1,2,3)
choose a random item in list (ex: 2)
display the item (in this case "2")in a message box
Someone knows how can i do it ?
Thanks
Creating a List with Items:
List<string> AuthorList = new List<int>();
//The following code snippet adds items to the list.
AuthorList.Add(1);
AuthorList.Add(2);
AuthorList.Add(3);
Alternatively, we can also pass an array of objects to create a List object. The following code snippet creates a List object from an array of integers.
// Create a List using Range
int[] number= { 1, 2, 3 };
List<int> numberRange = new List<int>(number);
Choosing Random Item in List:
First Create an instance of Random class somewhere. Note that it's pretty important not to create a new instance each time you need a random number. You should reuse the old instance to achieve uniformity in the generated numbers. You can have a static field somewhere (be careful about thread safety issues):
static Random rnd = new Random();
Ask the Random instance to give you a random number with the maximum of the number of items in the List:
int r = rnd.Next(numberRange.Count);
Display the number:
MessageBox.Show((string)list[r]);
When Button is clicked
Just put all the code above into the ButtonClick Function
private void NumberGenerator_ButtonClick(object sender, EventArgs e)
{ }
private Random _random = new Random();
public void DoIt()
{
List<int> list = new List<int>(){1 ,2, 3};
int pos = _random.Next(list.Count);
MessageBox.Show(list[pos]);
}
Ok so, I have a list of lists, like the title says and I want to make combinations of k lists in which every list has different elements than the rest.
Example:
I have the following list of lists:
{ {1,2,3} , {1,11} , {2,3,6} , {6,5,7} , {4,8,9} }
A valid 3-sized combination of these lists could be:
{ {1,11}, {4,8,9} ,{6,5,7} }
This is only ONE of the valid combinations, what I want to return is a list of all the valid combinations of K lists.
An invalid combination would be:
{ {1,11} ,{2, 3, 6}, {6, 5, 7} }
because the element 6 is present in the second and third list.
I already have a code that does this but it just finds all possible combinations and checks if they are valid before addding it to a final result list. As this list of lists is quite large (153 lists) when K gets bigger, the time taken is ridiculously big too (at K = 5 it takes me about 10 minutes.)
I want to see if there's an efficient way of doing this.
Below is my current code (the lists I want to combine are attribute of the class Item):
public void recursiveComb(List<Item> arr, int len, int startPosition, Item[] result)
{
if (len == 0)
{
if (valid(result.ToList()))
{
//Here I add the result to final list
//valid is just a function that checks if any list has repeated elements in other
}
return;
}
for (int i = startPosition; i <= arr.Count - len; i++)
{
result[result.Length - len] = arr[i];
recursiveComb(arr, len - 1, i + 1, result);
}
}
Use a HashSet
https://msdn.microsoft.com/en-us/library/bb359438(v=vs.110).aspx
to keep track of distinct elements as you build the output from the candidates in the input list of lists/tuples
accumulate an output list of non overlapping tuples by Iterating across the input list of tuples and evaluate each tuple as a candidate as follows:
For each input tuple, insert each tuple element into the HashSet. If the element you are trying to insert is already in the set, then the tuple fails the constraint and should be skipped, otherwise the tuple elements are all distinct from ones already in the output.
The hashset object effectively maintains a registry of distinct items in your accepted list of tuples.
If I understood your code correctly then, you are passing each list<int> from your input to recursiveComb() function. which look like this
for(int i = 0; i < inputnestedList.Count; i++)
{
recursiveComb();
// Inside of recursiveComb() you are using one more for loop with recursion.
// This I observed from your first parameter i.e. List<int>
}
Correct me if I am wrong
This leads to time complexity more than O(n^2)
Here is my simplest solution, with two forloops without recursion.
List<List<int>> x = new List<List<int>>{ new List<int>(){1,2,3} , new List<int>(){1,11} , new List<int>(){2,3,6} , new List<int>(){6,5,7} , new List<int>(){4,8,9} };
List<List<int>> result = new List<List<int>>();
var watch = Stopwatch.StartNew();
for (int i = 0; i < x.Count;i++)
{
int temp = 0;
for (int j = 0; j < x.Count; j++)
{
if (i != j && x[i].Intersect(x[j]).Any())
temp++;
}
// This condition decides, that elements of ith list are available in other lists
if (temp <= 1)
result.Add(x[i]);
}
watch.Stop();
var elapsedMs = watch.Elapsed.TotalMilliseconds;
Console.WriteLine(elapsedMs);
Now when I print execution time then output is
Execution Time: 11.4628
Check execution time of your code. If execution time of your code is higher than mine, then you can consider it as efficient code
Proof of code: DotNetFiddler
Happy coding
If I understood your problem correctly then this will work:
/// <summary>
/// Get Unique List sets
/// </summary>
/// <param name="sets"></param>
/// <returns></returns>
public List<List<T>> GetUniqueSets<T>(List<List<T>> sets )
{
List<List<T>> cache = new List<List<T>>();
for (int i = 0; i < sets.Count; i++)
{
// add to cache if it's empty
if (cache.Count == 0)
{
cache.Add(sets[i]);
continue;
}
else
{
//check whether current item is in the cache and also whether current item intersects with any of the items in cache
var cacheItems = from item in cache where (item != sets[i] && item.Intersect(sets[i]).Count() == 0) select item;
//if not add to cache
if (cacheItems.Count() == cache.Count)
{
cache.Add(sets[i]);
}
}
}
return cache;
}
Tested, it's fast and took 00:00:00.0186033 for finding sets.
I have a list that contains file names like f1, f2, f3,...,f6. my
program needs to output a list with file names appearing in
random order such as f4,f1,f6,f2,f3,f5.
I want to swap or shift string correctly inside a list I have a list of
size 6 named fileName already containing 6 different file names I
am swapping file names inside of a list fileName as follows and fil
is also a string for remembering current string or file name.
temp =-1;
foreach (Control control in tableLayoutPanel1.Controls) // run loop untill every control inside tablelayoutpanel1.Controls is check or read
{
Button btns = control as Button; // btn sotre the
current button in table.contr
if (btns != null) // check btn got a button from
the panel then
{
temp++;
int randomNumber = 0;
randomNumber = theArray[temp]; //this pic the random number from 0 index then 1 so on theArray already contains random number from 0 to 5 without any repitition and also tested
fil = fileName[randomNumber]; //fil for holding string
fileName[temp] = fileName[randomNumber]; // at filname[0]
swap or shift filename[randomNumber] random are between 0 to
5 and without repitition
fileName[randomNumber] = fil; // this line isnt even necessary
but to be safe i wrot
btns.BackgroundImage = images[randomNumber]; // change
btn image to current random image
copyImages.Add(images[randomNumber]);
btns.BackgroundImage = null; // i purposely doing this :)
}
Using that code I am able to swap string but I cant swap them
correctly as it only run for 6 times so it should swap 6 strings
(each with different name) inside the list on 6 different location
inside the list fileName but its not happening some strings are
showing twice or thrice, hoping someone can point out what I am
doing wrong and theres no index out of range or exception error
I tested it for like hundred time please help thanks and any idea
suggestion or piece of code will be helpful and fil just storing the string at the location of fileName[temp] :) and temp just going from 0 to 5 in a loop
i dont want to shuffle them i just want to swap them according to given index which i am doing in my code but cant to it properly theArray already contains the suffle index i just want to assign the fileName[0] index to theArray[temp] i can send you my proj if you want to have a look just send me hi to my id which show in my profile
So given you have a List of length 6 and an int[6] containing 0 to five in random order
List<String> newList = newList<String>();
foreach(int position in theArray)
{
newList.Add(filename[pos]);
}
filename.Clear();
fileName.AddRange(newList);
would be one way.
or you could simply do filename = newList and not bother with the Clear and AddRange.
You stored the wrong String in your temporary variable.
fil = fileName[temp]; // index changed here
fileName[temp] = fileName[randomNumber];
fileName[randomNumber] = fil;
This is a simple way to shuffle elements in an array. Basicly you go through the array from one end to the middle, swapping each element with one selected at random. Since each swap operation results in two elements being randomly placed, when we reach the middle, the whole array is shuffled.
void Main()
{
var arr = new string[] {"a","b","c"};
Shuffle(arr);
// arr is now shuffled
}
public static void Shuffle<T>(T[] arr)
{
Random r = new Random();
for(int i = arr.Length; i > arr.Length / 2; i--)
{
Swap(arr, r.Next(i), i -1);
}
}
private static void Swap<T>(T[] arr, int first, int second)
{
T temp = arr[first];
arr[first] = arr[second];
arr[second] = temp;
}