How to perform combinatoric task in C# - c#

i have a problem with an combinatoric task. I want to have a code which can handle this math calculation 48/5 = 1712304 (5! = 5*4*3*2*1 = 120 48*47*46*45*44 = 205476480 205476480/120 = 1712304)
Here some more details.
I have a string array with 48 strings. The strings have a length between 2 and 3 chars.
string array[] = new string[]{"A1","1D","410" /*[....]*/}
i want to combine 5 strings together, and i want to do this with the whole array, my biggest problem is that a combined string is just allowed to include each of the 48 strings just once. And each combined string have to be unique.
In the end i need a List with 1712304 string entries, which have to be between 10 and 15 degits long. For example one string could look like this "A11A4103E1T".
Back to the math, i know that there are 1712304 combined options so any other result must be wrong. That's where my problem appears.
I created the following code without succesful result
string[] siDigit = new string[iNumDigits];
List<string> liste = new List<string>();
const int iDigitBase = 48;
const int iNumDigits = 5;
for (int i = 0; i < 1712303; ++i)
{
int i2 = i;
for (int i3 = 0; i3 < iNumDigits; ++i3)
{
siDigit[i3] = array[i2 % iDigitBase];
i2 /= iDigitBase;
}
bool duplicate_free = siDigit.Distinct().Count() == siDigit.Length;
if (duplicate_free == true)
{
liste.Add(siDigit[0] + siDigit[1] + siDigit[2] + siDigit[3] + siDigit[4]);
Console.Write(siDigit[0] + siDigit[1] + siDigit[2] + siDigit[3] + siDigit[4]);
Console.WriteLine();
}
}
What i get is way to less entries in my list, i just get 1317051 entries and dont know why. I cant find any solution for my problem, may someone out there can help me out.
Any help would be greatly appreciated.
P.S In germany they dont teach better english :)

I think your algorithm is wrong.
Consider i equals 0, i2 equals 0, so siDigit[i3](i3 = 0, 1, 2, 3 ,4) are array[0], duplicate_free is false. You lose one. So, you can not get all entries.
Here is a recursive algorithm:
private static void GetCombination(ref List<string[]> list, string[] t, int n, int m, int[] b, int M)
{
for (int i = n; i >= m; i--)
{
b[m - 1] = i - 1;
if (m > 1)
{
GetCombination(ref list, t, i - 1, m - 1, b, M);
}
else
{
if (list == null)
{
list = new List<string[]>();
}
string[] temp = new string[M];
for (int j = 0; j < b.Length; j++)
{
temp[j] = t[b[j]];
}
list.Add(temp);
}
}
}
public static List<string[]> GetCombination(string[] t, int n)
{
if (t.Length < n)
{
return null;
}
int[] temp = new int[n];
List<string[]> list = new List<string[]>();
GetCombination(ref list, t, t.Length, n, temp, n);
return list;
}

Related

Almost Ordered not sorting the exact amount of values i give it

this is a really easy question but i cant figure out a way around it. Apparently the almost ordered has a bug that it might randomize a little bit more than you ask it. the code is rather simple:
public void Section1Task1AlmostOrdered(int arraySize, int percentage)
{
int[] testArray = new int[arraySize];
Console.WriteLine("Ordered List: ");
for (int i = 1; i <= testArray.Length; i++)
{
testArray[i-1] = i;
Console.Write(i + "\t");
}
Console.WriteLine("Almost Ordered List: ");
testArray = shuffler.AlmostOrdered(arraySize, percentage);
for (int i = 0; i < testArray.Length; i++)
{
Console.Write(testArray[i] + "\t");
}
}
The shuffler is this part of the code:
public int[] AlmostOrdered(int n, double p)
{
if (p > 100)
{
throw new InvalidOperationException("Cannot shuffle more than 100% of the numbers");
}
int shuffled = 0;
//Create and Populate an array
int[] array = new int[n];
for(int i = 1; i <= n; i++)
{
array[i-1] = i;
}
//Calculate numbers to shuffle
int numsOutOfPlace = (int) Math.Ceiling(n * (p / 100));
int firstRandomIndex = 0;
int secondRandomIndex = 0;
do
{
firstRandomIndex = this.random.Next(n-1);
// to make sure that the two numbers are not the same
do
{
secondRandomIndex = this.random.Next(n - 1);
} while (firstRandomIndex == secondRandomIndex);
int temp = array[firstRandomIndex];
array[firstRandomIndex] = array[secondRandomIndex];
array[secondRandomIndex] = temp;
shuffled++;
}
while (shuffled < numsOutOfPlace);
return array;
}
When i enter values 10 for array size and 40 for percentage to be shuffled, it is shuffling 5 numbers instead of 4. Is there a way to perfect this method to make it more accurate?
Likely the problem is with the calculation:
int numsOutOfPlace = (int)Math.Ceiling(n * (p / 100));
So if p=40 and n=10, then in theory you should get 4. But you're dealing with floating point numbers. So if (p/100) returns 0.400000000001, then the result will be 4.000000001, and Math.Ceiling will round that up to 5.
You might want to replace Math.Ceiling with Math.Round and see how that works out.

Fibonacci Sequence Error in C#

I've recently started learning C# (having learnt other languages) and I'm trying to create a function that generates the fibonacci sequence to the 'nth' term using a while loop and then returns the value of the 'nth' term.
My current code is this:
void fibonacci(int n)
{
int[] terms = { 0, 1 };
int i = 2;
while (i<=n)
{
terms.Concat( terms[i-1] + terms[i-2] );
i += 1;
}
return terms[n];
}
My understanding of C# is very poor as visual studio is telling me that I can't use 'Concat' with int[] - I'm trying to append the array with the new values. Any help would be great.
Arrays in C# are fixed length.
If you want to use a variable length collection, use a strongly typed List<T> instead, which has an Add method:
int fibonacci(int n)
{
var terms = new List<int>{ 0, 1 };
int i = 2;
while (i<=n)
{
terms.Add( terms[i-1] + terms[i-2] );
i += 1;
}
return terms[n];
}
You can't append to an array. In .Net, arrays have constant size and you can't resize them after creation.
Instead, you should use List<int> and its Add() method.
You can for example use list and change your code to:
int fibonacci(int n)
{
List<int> terms = new List<int> { 0, 1 };
int i = 2;
while (i<=n)
{
terms.Add(terms[i-1] + terms[i-2]);
i += 1;
}
return terms[n];
}
You can't add items to an array as it has fixed length. Use List<int> instead of array
I'm surprised nobody mentioned fixing the array size.
Well, maybe I'm missing something, but you could do:
int[] FibonacciArray(int n)
{
int[] F = new int[n+1];
F[0] = 0;
F[1] = 1;
for (int i = 2; i <= n; ++i)
{
F[i] = F[i - 1] + F[i - 2];
}
return F;
}
It's in average 2.5x faster than the version using a list.
But as often there is no free-lunch: the drawback is that your memory consumption is not smoothed: you pay upfront for all the memory you'll need.
Don't append values to an array. arrays have static size and you can't resize them after creation.
use
List<int> and its Add() method instead of array.
here is your solution for fibonacci series.
int fibonacci(int n)
{
var terms = new List<int>{ 0, 1 };
int i = 2;
while (i<=n)
{
terms.Add( terms[i-1] + terms[i-2] );
i += 1;
}
return terms[n];
}
also can be done like this :
class FibonacciSeries
{
static void Main(string[] args)
{
Console.WriteLine("Enter a num till which you want fibonacci series : ");
int val = Convert.ToInt32(Console.ReadLine());
int num1, num2;
num1 = num2 = 1;
Console.WriteLine(num1);
if (val > num2)
{
while (num2 < val)
{
Console.WriteLine(num2);
num2 += num1;
num1 = num2 - num1;
}
}
Console.ReadLine();
}
}
in your array format here is the solution
public int[] FibonacciSeriesArray(int num)
{
int[] arr = new int[num+1];
arr[0] = 0;
arr[1] = 1;
for (int startnum = 2; startnum <= num; startnum++)
{
arr[startnum] = arr[startnum - 1] + arr[startnum - 2];
}
return arr;
}
I would do it as a recursion, and not as a loop.
private static int fibonacci(int fib)
{
if (fib == 2 || fib == 1)
{
return 1;
}
else
{
return fibonacci(fib - 1) + fibonacci(fib - 2);
}
}
Here's a much more efficient way of finding fibonnaci numbers.
public static IEnumerable<double> FibList(int n)
{
for (int i = 1; i <= n; i++)
{
yield return Math.Round(Fib(i));
}
}
public static double Fib(double n)
{
double golden = 1.61803398875;
return (n == 0 || n == 1) ? 1 : (Math.Pow(golden, n) - Math.Pow(-golden, -n))/Math.Sqrt(5);
}

More efficient way to get all indexes of a character in a string

Instead of looping through each character to see if it's the one you want then adding the index your on to a list like so:
var foundIndexes = new List<int>();
for (int i = 0; i < myStr.Length; i++)
{
if (myStr[i] == 'a')
foundIndexes.Add(i);
}
You can use String.IndexOf, see example below:
string s = "abcabcabcabcabc";
var foundIndexes = new List<int>();
long t1 = DateTime.Now.Ticks;
for (int i = s.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1))
{
// for loop end when i=-1 ('a' not found)
foundIndexes.Add(i);
}
long t2 = DateTime.Now.Ticks - t1; // read this value to see the run time
I use the following extension method to yield all results:
public static IEnumerable<int> AllIndexesOf(this string str, string searchstring)
{
int minIndex = str.IndexOf(searchstring);
while (minIndex != -1)
{
yield return minIndex;
minIndex = str.IndexOf(searchstring, minIndex + searchstring.Length);
}
}
usage:
IEnumerable<int> result = "foobar".AllIndexesOf("o"); // [1,2]
Side note to a edge case: This is a string approach which works for one or more characters. In case of "fooo".AllIndexesOf("oo") the result is just 1 https://dotnetfiddle.net/CPC7D2
How about
string xx = "The quick brown fox jumps over the lazy dog";
char search = 'f';
var result = xx.Select((b, i) => b.Equals(search) ? i : -1).Where(i => i != -1);
The raw iteration is always better & most optimized.
Unless it's a bit complex task, you never really need to seek for a better optimized solution...
So I would suggest to continue with :
var foundIndexes = new List<int>();
for (int i = 0; i < myStr.Length; i++)
if (myStr[i] == 'a') foundIndexes.Add(i);
If the string is short, it may be more efficient to search the string once and count up the number of times the character appears, then allocate an array of that size and search the string a second time, recording the indexes in the array. This will skip any list re-allocations.
What it comes down to is how long the string is and how many times the character appears. If the string is long and the character appears few times, searching it once and appending indicies to a List<int> will be faster. If the character appears many times, then searching the string twice (once to count, and once to fill an array) may be faster. Exactly where the tipping point is depends on many factors that can't be deduced from your question.
If you need to search the string for multiple different characters and get a list of indexes for those characters separately, it may be faster to search through the string once and build a Dictionary<char, List<int>> (or a List<List<int>> using character offsets from \0 as the indicies into the outer array).
Ultimately, you should benchmark your application to find bottlenecks. Often the code that we think will perform slowly is actually very fast, and we spend most of our time blocking on I/O or user input.
public static List<int> GetSubstringLocations(string text, string searchsequence)
{
try
{
List<int> foundIndexes = new List<int> { };
int i = 0;
while (i < text.Length)
{
int cindex = text.IndexOf(searchsequence, i);
if (cindex >= 0)
{
foundIndexes.Add(cindex);
i = cindex;
}
i++;
}
return foundIndexes;
}
catch (Exception ex) { }
return new List<int> { };
}
public static String[] Split(this string s,char c = '\t')
{
if (s == null) return null;
var a = new List<int>();
int i = s.IndexOf(c);
if (i < 0) return new string[] { s };
a.Add(i);
for (i = i+1; i < s.Length; i++) if (s[i] == c) a.Add(i);
var result = new string[a.Count +1];
int startIndex = 0;
result[0] = s.Remove(a[0]);
for(i=0;i<a.Count-1;i++)
{
result[i + 1] = s.Substring(a[i] + 1, a[i + 1] - a[i] - 1);
}
result[a.Count] = s.Substring(a[a.Count - 1] + 1);
return result;
}

Easiest way to Rotate a List in c#

Lists say I have a list List<int> {1,2,3,4,5}
Rotate means:
=> {2,3,4,5,1} => {3,4,5,1,2} => {4,5,1,2,3}
Maybe rotate is not the best word for this, but hope you understand what I means
My question, whats the easiest way (in short code, c# 4 Linq ready), and will not be hit by performance (reasonable performance)
Thanks.
List<T>
The simplest way (for a List<T>) is to use:
int first = list[0];
list.RemoveAt(0);
list.Add(first);
Performance is nasty though - O(n).
Array
This is basically equivalent to the List<T> version, but more manual:
int first = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = first;
LinkedList<T>
If you could use a LinkedList<T> instead, that would be much simpler:
int first = linkedList.First;
linkedList.RemoveFirst();
linkedList.AddLast(first);
This is O(1) as each operation is constant time.
Queue<T>
cadrell0's solution of using a queue is a single statement, as Dequeue removes the element and returns it:
queue.Enqueue(queue.Dequeue());
While I can't find any documentation of the performance characteristic of this, I'd expect Queue<T> to be implemented using an array and an index as the "virtual starting point" - in which case this is another O(1) solution.
Note that in all of these cases you'd want to check for the list being empty first. (You could deem that to be an error, or a no-op.)
You could implement it as a queue. Dequeue and Enqueue the same value.
**I wasn't sure about performance in converting a List to a Queue, but people upvoted my comment, so I'm posting this as an answer.
I use this one:
public static List<T> Rotate<T>(this List<T> list, int offset)
{
return list.Skip(offset).Concat(list.Take(offset)).ToList();
}
It seems like some answerers have treated this as a chance to explore data structures. While those answers are informative and useful, they are not very Linq'ish.
The Linq'ish approach is: You get an extension method which returns a lazy IEnumerable that knows how to build what you want. This method doesn't modify the source and should only allocate a copy of the source if necessary.
public static IEnumerable<IEnumerable<T>> Rotate<T>(this List<T> source)
{
for(int i = 0; i < source.Count; i++)
{
yield return source.TakeFrom(i).Concat(source.TakeUntil(i));
}
}
//similar to list.Skip(i-1), but using list's indexer access to reduce iterations
public static IEnumerable<T> TakeFrom<T>(this List<T> source, int index)
{
for(int i = index; i < source.Count; i++)
{
yield return source[i];
}
}
//similar to list.Take(i), but using list's indexer access to reduce iterations
public static IEnumerable<T> TakeUntil<T>(this List<T> source, int index)
{
for(int i = 0; i < index; i++)
{
yield return source[i];
}
}
Used as:
List<int> myList = new List<int>(){1, 2, 3, 4, 5};
foreach(IEnumerable<int> rotation in myList.Rotate())
{
//do something with that rotation
}
How about this:
var output = input.Skip(rot)
.Take(input.Count - rot)
.Concat(input.Take(rot))
.ToList();
Where rot is the number of spots to rotate - which must be less than the number of elements in the input list.
As #cadrell0 answer shows if this is all you do with your list, you should use a queue instead of a list.
My solution maybe too basic (I wouldn't like to say it's lame...) and not LINQ'ish.
However, it has a pretty good performance.
int max = 5; //the fixed size of your array.
int[] inArray = new int[5] {0,0,0,0,0}; //initial values only.
void putValueToArray(int thisData)
{
//let's do the magic here...
Array.Copy(inArray, 1, inArray, 0, max-1);
inArray[max-1] = thisData;
}
Try
List<int> nums = new List<int> {1,2,3,4,5};
var newNums = nums.Skip(1).Take(nums.Count() - 1).ToList();
newNums.Add(nums[0]);
Although, I like Jon Skeet's answer better.
My solution for Arrays:
public static void ArrayRotate(Array data, int index)
{
if (index > data.Length)
throw new ArgumentException("Invalid index");
else if (index == data.Length || index == 0)
return;
var copy = (Array)data.Clone();
int part1Length = data.Length - index;
//Part1
Array.Copy(copy, 0, data, index, part1Length);
//Part2
Array.Copy(copy, part1Length, data, 0, index);
}
I've used the following extensions for this:
static class Extensions
{
public static IEnumerable<T> RotateLeft<T>(this IEnumerable<T> e, int n) =>
n >= 0 ? e.Skip(n).Concat(e.Take(n)) : e.RotateRight(-n);
public static IEnumerable<T> RotateRight<T>(this IEnumerable<T> e, int n) =>
e.Reverse().RotateLeft(n).Reverse();
}
They're certainly easy (OP title request), and they've got reasonable performance (OP write-up request). Here's a little demo I ran in LINQPad 5 on an above-average-powered laptop:
void Main()
{
const int n = 1000000;
const int r = n / 10;
var a = Enumerable.Range(0, n);
var t = Stopwatch.StartNew();
Console.WriteLine(a.RotateLeft(r).ToArray().First());
Console.WriteLine(a.RotateLeft(-r).ToArray().First());
Console.WriteLine(a.RotateRight(r).ToArray().First());
Console.WriteLine(a.RotateRight(-r).ToArray().First());
Console.WriteLine(t.ElapsedMilliseconds); // e.g. 236
}
You can use below code for left Rotation.
List<int> backUpArray = array.ToList();
for (int i = 0; i < array.Length; i++)
{
int newLocation = (i + (array.Length - rotationNumber)) % n;
array[newLocation] = backUpArray[i];
}
You can play nice in .net framework.
I understand that what you want to do is more up to be an iteration behavior than a new collection type; so I would suggest you to try this extension method based on IEnumerable, which will work with Collections, Lists and so on...
class Program
{
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7 };
IEnumerable<int> circularNumbers = numbers.AsCircular();
IEnumerable<int> firstFourNumbers = circularNumbers
.Take(4); // 1 2 3 4
IEnumerable<int> nextSevenNumbersfromfourth = circularNumbers
.Skip(4).Take(7); // 4 5 6 7 1 2 3
}
}
public static class CircularEnumerable
{
public static IEnumerable<T> AsCircular<T>(this IEnumerable<T> source)
{
if (source == null)
yield break; // be a gentleman
IEnumerator<T> enumerator = source.GetEnumerator();
iterateAllAndBackToStart:
while (enumerator.MoveNext())
yield return enumerator.Current;
enumerator.Reset();
if(!enumerator.MoveNext())
yield break;
else
yield return enumerator.Current;
goto iterateAllAndBackToStart;
}
}
Reasonable performance
Flexible
If you want go further, make a CircularList and hold the same enumerator to skip the Skip() when rotating like in your sample.
below is my approach. Thank you
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
public static int[] RightShiftRotation(int[] a, int times) {
int[] demo = new int[a.Length];
int d = times,i=0;
while(d>0) {
demo[d-1] = a[a.Length - 1 - i]; d = d - 1; i = i + 1;
}
for(int j=a.Length-1-times;j>=0;j--) { demo[j + times] = a[j]; }
return demo;
}
Using Linq,
List<int> temp = new List<int>();
public int[] solution(int[] array, int range)
{
int tempLength = array.Length - range;
temp = array.Skip(tempLength).ToList();
temp.AddRange(array.Take(array.Length - range).ToList());
return temp.ToArray();
}
If you're working with a string you can do this quite efficiently using ReadOnlySpans:
ReadOnlySpan<char> apiKeySchema = "12345";
const int apiKeyLength = 5;
for (int i = 0; i < apiKeyLength; i++)
{
ReadOnlySpan<char> left = apiKeySchema.Slice(start: i, length: apiKeyLength - i);
ReadOnlySpan<char> right = apiKeySchema.Slice(start: 0, length: i);
Console.WriteLine(string.Concat(left, right));
}
Output:
12345
23451
34512
45123
51234
I was asked to reverse a character array with minimal memory usage.
char[] charArray = new char[]{'C','o','w','b','o','y'};
Method:
static void Reverse(ref char[] s)
{
for (int i=0; i < (s.Length-i); i++)
{
char leftMost = s[i];
char rightMost = s[s.Length - i - 1];
s[i] = rightMost;
s[s.Length - i - 1] = leftMost;
}
}
How about using modular arithmetic :
public void UsingModularArithmetic()
{
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int k = Convert.ToInt32(tokens_n[1]);
int[] a = new int[n];
for(int i = 0; i < n; i++)
{
int newLocation = (i + (n - k)) % n;
a[newLocation] = Convert.ToInt32(Console.ReadLine());
}
foreach (int i in a)
Console.Write("{0} ", i);
}
So basically adding the values to the array when I am reading from console.

Divide sequence elements into pairs

I have a sequence of 16 elements: 1,2,3,..., 16 ( or 2*n elements). Sequence elements always goes from 1 to length(sequence) that is sequence of 4 elements is 1,2,3,4.
Edit: first sequence element is always = 1, second sequence element = 2, third sequence element = 3 and so on. It's for a game "find a pair pictures".
I want to write an algorithm which divide elements into pairs. For Example,
1-15
2-16
3-13
4-9
5-14
6-10
7-11
8-12
PS: no linq please :) vs2005
Edit: As I can see, my question is so simple so no one can answer it :) Or everybody afraid something ?
Without a selection criteria, just take every other one.....
var result = new List<Tuple<int,int>>();
for (int i = 1; i < size; i+=2 )
{
var pair = new Tuple.Create(i,i+1);
result.Add(pair);
}
What about this?
class Program
{
static void Main(string[] args)
{
int size = 8;
List<int> tmpList = new List<int>();
for (int i = size; i <= size * 2; i++)
{
tmpList.Add(i);
}
List<Pair> result = new List<Pair>();
Random r = new Random();
for (int i = 1; i <= size; i++)
{
Pair pair = new Pair() { a = i, b = PopRandom(r, tmpList) };
result.Add(pair);
}
foreach (Pair p in result)
{
Console.WriteLine("{0} - {1}", p.a, p.b);
}
}
static private int PopRandom(Random r, List<int> list)
{
int i = r.Next(0, list.Count);
int result = list[i];
list.RemoveAt(i);
return result;
}
struct Pair
{
public int a;
public int b;
}
}
UPD: this was compiled successfully for .net 2.0 target platform
UPD 2: Random instance moved out from PopRandom()

Categories

Resources