word permutation with repetition where words are used multiple times - c#

I am trying to generate a list of combinations from an array of words.
I have been using http://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G to generate Combinations
var words = File.ReadAllLines(#"C:\words.txt");
var allCombinations = new List<string>();
var combis = new Combinations<string>(words, 3, GenerateOption.WithRepetition);
allCombinations.AddRange(combis.Select(c => c.Aggregate((j, k) => j + "-" + k)));
given 3 words "Word1", "Word2" and "Word3" I get a list of combinations like
"Word1-Word1-Word1"
"Word1-Word1-Word2"
"Word1-Word1-Word3"
etc.
But I am missing combinations where a word is used multiple times
"Word1-Word2-Word1"
"Word1-Word3-Word1"
"Word2-Word1-Word2"
How do I get combinations of words that uses words multiple times?

Your situation is basically like counting in base 3:
0 0 0
0 0 1
0 0 2
0 1 0
0 1 1
0 1 2
0 2 0
// and so on..
If the library you're using doesn't implement the logic you require, you can implement it yourself. Here is the idea:
public static IEnumerable<string> Permutate(string[] words)
{
// 0 0 0
int[] indices = new int[words.Length];
// yield 0 0 0
yield return string.Join("-", indicies.Select(x => words[x]));
// moves to 0 0 1 and so on, returns false after 3 3 3
while (CountStep(indicies))
{
// yield next permutation
yield return string.Join("-", indicies.Select(x => words[x]));
}
}
Implementing CountStep is not hard either:
public static bool CountStep(int[] arr)
{
// assumes we count in base N for an N sized array
var maxDigit = arr.Length - 1;
for (var i = arr.Length - 1; i >= 0; i--)
{
if (arr[i] < maxDigit)
{
arr[i]++;
for (var j = i + 1; j < arr.Length; j++)
{
arr[j] = 0;
}
return true;
}
}
return false;
}

Related

How to find all combinations of 30 integers within 0-1000

I am looking for a way to find all combinations of a 30 numbers in numbersArray which has numbers between 0-1000.
For example 1st combination is: 0,1,2,3,4,5,6......29,30
For example 2nd combination is: 0,2,3,4,5,6,7......30,31
For example 2rd combination is: 0,3,4,5,6,7,8......31,32
Then continue to find all combinations. Any number must only appear once in the series of 30 numbers.
The very important detail here is if it is possible while create those combinations, then use them straight away. With other words, not storing the combinations first and then iterating through them again. Which would mean double amount of iterations?
Thank you!
void findcombinations()
{
//Declaring the array with 1000 indexes
//The number of indexes can be up to 100,000 indexes
int[] numbersArray = new int[1000];
for (int i = 0; i < numbersArray.Length; i++)
{
numbersArray[i] = i; //Assign number from 0-1000
}
//How to find all combinations of 30 numbers between: 0-1000?
//For example 1st combination is: 0,1,2,3,5,6,7......29,30
//For example 2nd combination is: 0,2,3,5,6,7,8......30,31
//For example 2rd combination is: 0,3,5,6,7,8,9......31,32
//How to dynamically find all combinations of a group of 30 numbers between 0-1000?
//Not perheps exactly use the below approach because that would mean that we already have filled the
//Array with the combinations.
//I am trying to see if there is a dynamic approach where the combinations are produced right away so
//They can be used straight away as they are produced?
int[,] allCombinations = new int[???,30]; ///??? How many combinations of 30 numbers
for (int i = 0; i < allCombinations.Length; i++)
{
for (int i2 = 0; i2 < allCombinations.GetLength(i); i2++)
{
//Do something with the combination of numbers here
}
}
}
Here you have the solution:
using System;
using System.Collections.Generic;
namespace combinatory
{
public class Combinations
{
private readonly int n;
private readonly int k;
private readonly int[] combination;
public Combinations(int n, int k)
{
if (n <= 0) throw new ArgumentException("n argument must be greater than 0", nameof(n));
if (k <= 0) throw new ArgumentException("k argument must be greater than 0", nameof(k));
if (n < k) throw new ArgumentException("k argument must be greater or equals to n", nameof(k));
this.n = n;
this.k = k;
combination = new int[k];
for (int i = 0; i < k; i++)
{
combination[i] = i;
}
}
public IEnumerable<int[]> Get()
{
yield return combination;
while (TrySetNextCombination())
{
yield return combination;
}
}
private bool TrySetNextCombination()
{
int incrementableIndex = findFirstIncrementableIndex();
if (incrementableIndex < 0) return false;
var value = combination[incrementableIndex];
for (int i = incrementableIndex; i < k; i++)
{
combination[i] = ++value;
}
return true;
}
private int findFirstIncrementableIndex()
{
int index = k - 1;
int threshold = n - 1;
while (index >= 0)
{
if (combination[index] < threshold) return index;
index--;
threshold--;
}
return index;
}
}
}
The class Combinations has a constructor that takes n and k arguments. n is the number of elements in the set, k is the number of elements in the subset. It has the Get method, it enumerates all combinations. It is very memory efficient because it just need an array of k integers. The key point is to initialize the first combination and then calculate the next one.
This is how you can use it:
using System;
namespace combinatory
{
class Program
{
static void Main(string[] args)
{
var combinations = new Combinations(6, 3);
foreach (var comb in combinations.Get())
{
foreach (var v in comb)
{
Console.Write(" ");
Console.Write(v);
}
Console.WriteLine();
}
}
}
}
This is the output:
0 1 2
0 1 3
0 1 4
0 1 5
0 2 3
0 2 4
0 2 5
0 3 4
0 3 5
0 4 5
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
In fact, if you want just the number of combinations, there's a mathematical compution for this:
n! / (p! . (n - p)!)
Where n is the total number count (1000), and p is de picked count (30).
Source: https://en.m.wikipedia.org/wiki/Combination

Fall down elements in 2d array

Hello looking for simple loop where numbers will fall down in 2d array for example
0 0 0 3 3
2 1 3 1 1
1 1 5 1 1
1 2 0 0 0
0 0 0 0 2
expected:
0 0 0 0 0
0 0 0 0 3
2 1 0 3 1
1 1 3 1 1
1 2 5 1 2
Do you have suggestions? Thank you.
Hint: Fall down means non-zero items must go down in each column!
Here is a solution:
void FallDown(ref int[,] numbers)
{
var rowCount = numbers.GetLength(0);
for (var c = 0; c < numbers.GetLength(1); c++)
{
var colValues = new List<int>();
for (var r = 0; r < rowCount; r++)
{
var colValue = numbers[r, c];
if (colValue > 0)
{
colValues.Add(colValue); // collect only non-zero values
}
}
if (colValues.Count < rowCount) // there were zeroes ...
{
do
{
colValues.Insert(0, 0); // fill it up with leading zeroes.
} while (colValues.Count < rowCount);
for (var r = 0; r < rowCount; r++) {
numbers[r, c] = colValues[r]; // put numbers back into original array
}
}
}
}
The result will be replaced in the original array, which is why it is passed in by ref.
Found this.
public void FallDown()
{
for (var row = 0; row < RowCount - 1; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
if (tiles[row + 1, column] == 0 && tiles[row, column] != 0)
{
tiles[row + 1, column] = tiles[row, column];
tiles[row, column] = 0;
row = 0;
column = 0;
}
}
}
}

Finding unknown repeating patterns in a string consisting numbers

I've been struggling with this for a week.
I have a string like this: 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1.....
What I need to find: 1 1 0
example 2: 1 1 2 0 2 2 1 0 1 1 2 0 2 2 1 0 1 1 2 0 2 2 1 0 1 1 2 0 2 2 1 0 ....
What I need to find: 1 1 2 0 2 2 1 0
example 3: 1 1 2 3 1 0 1 1 2 3 1 0 1 1 2 3 1 0 1 1 2 3 1 0 1 1 2 3 1 0...
112310
etc. etc.
My code as now:
private string tekrarArama(double[] mods)
{
string part1 = "";
string part2 = "";
string patern = "";
int number1 = mods.Length;
for (int i = 0; i < mods.Length; i++)
{
part1 = "";
part2 = "";
for (int j = 0; j < number1; j++)
{
part1 += mods[j] + ",";
}
for (int k = 0; k < mods.Length; k++)
{
part2 += mods[k] + ",";
}
int actualcount = Regex.Matches(part2, part1).Count;
int count = part2.Replace(",", "").Length / part1.Replace(",", "").Length;
if (part2.IndexOf(bolum1) >= 0 && actualcount == count )
{
patern = part2.Substring(part2.IndexOf(part1),part1.Length);
}
number1--;
}
return patern;
}
It creates two copies of the string and deletes 1 character at a time from one of the strings in each iteration, to find the smallest repeating pattern.
It's a mess and doesn't work very well at all.
How can I do this? Thanks in advance.
If you're looking for something simple and don't need optimal complexity, here's a concise way to represent the query.
string FindPattern(string text)
{
if (text == null)
{
return null;
}
return Enumerable
.Range(1, text.Length / 2)
.Where(n => text.Length % n == 0)
.Select(n => text.Substring(0, n))
.Where(pattern => Enumerable
.Range(0, text.Length / pattern.Length)
.SelectMany(i => pattern)
.SequenceEqual(text))
.FirstOrDefault();
}
Note that the complexity here is quadratic in the worst case, so it's not a good idea to use it for very long strings.

Different combinations of an array (C#)

how can we find out different combination of the elements of an array using c# code.
are there any inbuilt library function for this.?
for eg: suppose an array has elements {2,3,4,5,6,7}
then the possible combination would be 2,3,4,5,6,7,2 3,2 3 4,2 3 4 5, etc
so basically wat i need is a function which gives different combination based on its input for eg: comb(array,2) gives output 2 3,1 2,3 4 and comb(array,3) gives output 1 2 3,2 3 4,3 4 5 and so on
Eg: valid comnbination for array= {1, 2, 3} and length = 2 are 1 2,1 3,2 3 .....
static void Main()
{
var cnk = comb(new [] {1,2,3},2);
foreach ( var c in cnk)
{
}
}
public static IEnumerable<int[]> comb(int[] a, int k)
{
if (a == null || a.Length == 0 || k < 1 || k > a.Length)
yield break;
int n = a.Length;
// 1
if ( k == 1)
for ( int i = 0; i < n; i++)
{
yield return new int[] {a[i]};
}
else
{
// k
for ( int i = 0; i < n - k + 1; i++)
{
var res = new int[k];
for (int t = i, c = 0; t < i + k - 1; t++, c++)
res[c] = a[t];
for (int j = i + k - 1; j < n; j++)
{
res[k-1] = a[j];
yield return res;
}
}
}
}
You should take the algorithm from here, my answer doesn't solve your problem
Algorithm to return all combinations of k elements from n
Seemed logic is not absolutely correct as:
var cnk = comb(new[] { 1, 2, 3, 4 }, 3);
This gives 3 variants, but as a matter of fact it is 4:
1 2 3
1 2 4
1 3 4
2 3 4
I guess comb is better to be implemented in recursive way.

Is it possible to express this code in LINQ?

I'm reading a C# book for beginners, and in every end of the chapter, there are exercises to be answered based on the lessons tackled.
One of those exercises goes this way: (not the exact wordings)
Write a program that will accept an int as the array length, and the values for the array.
Then will print:
"0" if the array is not sorted in ascending way.
"1" if it is sorted. And,
"2" if it is sorted, but there are duplicates.
Example:
// Sorted
Input: 1, 2, 3, 5
Print: 1
// Not sorted
Input: 2, 1, 3, 6
Print: 0
// Sorted, but with duplicates
Input: 2, 2, 3, 7
Print: 2
I don't know if my logic here is absolute, but somehow it is working,
and I done it in my way using this code:
int arrayLength = 0;
int prev, next;
int sortStatus = 1;
Console.Write("Input array Length: ");
arrayLength = Convert.ToInt32(Console.ReadLine());
int[] ar = new int[arrayLength];
for (int x = 0; x < arrayLength; x++)
{
Console.Write("Input {0} value: ", (x+1).ToString());
ar[x] = Convert.ToInt32(Console.ReadLine());
}
for (int x = 0; x < ar.Length-1; x++)
{
prev = (int)ar[x];
next = (int)ar[x + 1];
if (next < prev)
sortStatus = 0;
if (next == prev)
sortStatus = 2;
}
Console.Write(sortStatus.ToString());
Console.Read();
Is it possible to express this in LINQ? How?
if (ar.SequenceEqual(ar.OrderBy(x => x)))
{
if (ar.Distinct().Count() == ar.Length)
return 1;
else
return 2;
}
else
{
return 0;
}
A pure LINQ alternative ... (for academic interest only (but probably still faster than the accepted answer!)
var input = new int[] { 1, 2, 3, 4, 5 };
var output = input.Zip(input.Skip(1), (a, b) => new {a=a, b=b})
.Aggregate(1, (status, x) => status == 0 ? 0 : ((x.a > x.b ? 0 : (x.a == x.b ? 2 : status))));
As a note, your expressed non-LINQ logic has a flaw.
if (next < prev)
sortStatus = 0;
if (next == prev)
sortStatus = 2;
Your rule says that the array must be sorted ascending but have duplicates in order to get an output of 2. However, your logic will return 2 for { 1, 9, 7, 7 }.
Another way to write your code might be the following. (This is not using LINQ, but this is too long to post as a comment to your question.)
static int EvaluateArray(int[] array)
{
int? lastItem = null;
bool match = false;
foreach (int item in array)
{
if (item < lastItem)
return 0;
else if (item == lastItem)
match = true;
lastItem = item;
}
if (match)
return 2;
return 1;
}
In this method, we will early-return as soon as we have an item less than the previous item. Otherwise, we will set a boolean if we come across a matching value. At the end of the loop, we know the array is sorted ascending. The only thing left is check if there was a match.
Untested.
IEnumerable<int> signs =
from i in Enumerable.Range(0, ar.Length).Skip(1)
select ar[i-1].CompareTo(ar[i]);
int result =
signs.Any(sign => sign < 0) ? 0 :
signs.All(sign => 0 < sign) ? 1 :
2;
Also untested:
int minSign = !ar.Skip(1).Any() ? 1 :
(
from i in Enumerable.Range(0, ar.Length).Skip(1)
select ar[i-1].CompareTo(ar[i])
).TakeWhile(x => 0 <= x).Min();
int result =
minSign < 0 ? 0 :
0 < minSign ? 1 :
2;

Categories