Reputation: 37
I want to permute with replacement but skip if a symbol is not in the list. Currently the implementation does not rely on PayDistribution. it uses only the symbol list. So, if I send the symbolList of (A,B,C) and windowWidth of 3, I will get:
A,A,A
A,A,B
A,A,C
A,B,A
A,B,B
...
C,C,C
But if for example I have a PayDistribution of:
symbol: first to third positions
A:1 1 1
B:1 1 0
C:1 1 1
Where B will not be in the third position, then I don't want to include any permutations where B is in the third position:
A,A,B for example should not exist.
I just want it to jump the the next valid entry. Seems I can add a check in the GetCombinations function to do so, but I am not sure how. Really looking to speed this up by skipping. With large symbolLists it can take a while. My usage isn't super important:
public ACombo[] PayHashLineCreate(SymbolList symbolList, ComboList comboTable, int windowWidth,List<List<int>> PayDistribution)
{
Console.Write("Creating Pay Hash ");
WindowWidth = windowWidth;
SymbolCount = symbolList.NumRegularSym;
var count = 0;
var filteredList = new SymbolList();
filteredList.AddRange(symbolList.Where(symbol => typeof (RegularSymbol) == symbol.GetType()));
filteredList.AddRange(symbolList.Where(symbol => typeof (ScatterSymbol) == symbol.GetType()));
var filteredSymbolListArray = filteredList.ToArray();
var filteredComboList = new ComboList();
filteredComboList.AddRange(comboTable.Where(combo => typeof (T) == combo.GetType()));
foreach (
var symbolArrangement in
CombinationsWithReplacement.GetCombinationsWithReplacementLexographicOrder(filteredSymbolListArray, windowWidth,PayDistribution))
{
Add(null);
foreach (var combo in filteredComboList)
{
var match = Compare(combo, symbolArrangement);
if (!match) continue;
this[count] = combo;
break;
}
count++;
}
Console.WriteLine("DONE");
return ToArray();
}
But the important functions:
public static IEnumerable<List<T>> GetCombinationsWithReplacementLexographicOrder<T>(IList<T> pool,
int comboLength, List<List<int>> PayDistribution)
{
foreach (var list in GetCombinations(pool, comboLength, PayDistribution).Select(c =>
c.ToList()))
yield return list;
}
private static IEnumerable<IEnumerable<T>> GetCombinations<T>(IList<T> list, int length,
List<List<int>> PayDistribution)
{
if (length == 1) return list.Select(t => new[] { t });
return GetCombinations(list, length -1).SelectMany(t => list, (t1, t2) => t1.Concat(new[] { t2
}));
}
Upvotes: 0
Views: 87
Reputation: 26917
Since the PayDistribution
is position first, then symbol, it can be directly converted to a Dictionary
for each T
and filter the combinations by the matching Dictionary
for each position:
private static IEnumerable<List<T>> GetCombinationsWithReplacementLexographicOrder<T>(IList<T> list, int length, List<List<int>> PayDistribution) {
var PayMap = PayDistribution.Select(g => g.Select((pd,i) => (pd,i)).ToDictionary(pdi => list[pdi.i], pdi => pdi.pd > 0)).ToList();
foreach (var c in GetCombinations(list, length, PayMap))
yield return c.ToList();
}
private static IEnumerable<IEnumerable<T>> GetCombinations<T>(IList<T> list, int length, List<Dictionary<T, bool>> PayMaps, int pos = 1) {
var payMap = PayMaps[length-pos];
if (pos == length)
return list.Where(t => payMap[t]).Select(t => new[] { t });
return GetCombinations(list, length, PayMaps, pos + 1)
.SelectMany(t => list.Where(t2 => payMap[t2]), (t1, t2) => t1.Concat(new[] { t2 }));
}
Upvotes: 1
Reputation: 37
Using @NetMage solution, I just needed to modify it slightly to remove the Pivot() call and change the pdi.pd == 1 to pdi.pd >0. The count being more than 1 is insignificant in my case. I just didn't want to create a permutation with 0. Now the List A,B,C,D or how many I want, will create Permutations With Replacement in windowWidth (length) number of positions unless I send it a double list with 0 in a specific position. thus skipping invalid permutations.
public static IEnumerable<List<T>> GetCombinationsWithReplacementLexographicOrder<T>(IList<T> list, int length, List<List<int>> PayDistribution)
{
var PayMap = PayDistribution
.Select(g => g.Select((pd, i) => (pd, i))
.ToDictionary(pdi => list[pdi.i], pdi => pdi.pd >0)
).ToList();
foreach (var c in GetCombinations(list, length, PayMap))
yield return c.ToList();
}
private static IEnumerable<IEnumerable<T>> GetCombinations<T>(IList<T> list, int length, List<Dictionary<T, bool>> PayMaps, int pos = 1)
{
var payMap = PayMaps[length - pos];
if (pos == length)
return list.Where(t => payMap[t]).Select(t => new[] { t });
return GetCombinations(list, length, PayMaps, pos + 1)
.SelectMany(t => list.Where(t2 => payMap[t2]), (t1, t2) => t1.Concat(new[] { t2 }));
}
Upvotes: 0