Skip to content

Commit 66474d6

Browse files
committed
include selection option(r) in permutation
1 parent 698a494 commit 66474d6

File tree

2 files changed

+38
-97
lines changed

2 files changed

+38
-97
lines changed

Advanced.Algorithms.Tests/Combinatorics/Permutation_Tests.cs

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,77 +12,64 @@ namespace Advanced.Algorithms.Tests.Combinatorics
1212
public class Permutation_Tests
1313
{
1414
//for verification
15-
readonly Func<int, int> factorial = n => n == 0 ? 1 :
15+
static readonly Func<int, int> factorial = n => n == 0 ? 1 :
1616
Enumerable.Range(1, n).Aggregate((acc, x) => acc * x);
1717

18-
19-
[TestMethod]
20-
public void Permutation_Without_Repetitions_Smoke_Test()
21-
{
22-
var input = "".ToCharArray().ToList();
23-
var permuations = Permutation.Find<char>(input);
24-
Assert.AreEqual(factorial(input.Count), permuations.Count);
25-
26-
input = "cookie".ToCharArray().ToList();
27-
permuations = Permutation.Find<char>(input);
28-
Assert.AreEqual(factorial(input.Count), permuations.Count);
29-
30-
input = "monster".ToCharArray().ToList();
31-
permuations = Permutation.Find<char>(input);
32-
Assert.AreEqual(factorial(input.Count), permuations.Count);
33-
}
34-
18+
//for verification
19+
static readonly Func<int, int, int> permutation = (int n, int r)
20+
=> n == 0 || r == 0 ? 1 : factorial(n) / factorial(n - r);
3521

3622
[TestMethod]
3723
public void Permutation_With_Repetition_Smoke_Test()
3824
{
3925
var input = "".ToCharArray().ToList();
40-
var permuations = Permutation.Find<char>(input, true);
26+
var permuations = Permutation.Find<char>(input, input.Count, true);
4127
Assert.AreEqual(Math.Pow(input.Count, input.Count), permuations.Count);
4228

4329
input = "pen".ToCharArray().ToList();
44-
permuations = Permutation.Find<char>(input, true);
30+
permuations = Permutation.Find<char>(input, input.Count, true);
4531
Assert.AreEqual(Math.Pow(input.Count, input.Count), permuations.Count);
4632

4733
input = "scan".ToCharArray().ToList();
48-
permuations = Permutation.Find<char>(input, true);
34+
permuations = Permutation.Find<char>(input, input.Count, true);
4935
Assert.AreEqual(Math.Pow(input.Count, input.Count), permuations.Count);
50-
}
5136

52-
[TestMethod]
53-
public void Permutation_Without_Repetition_Without_Inversions_Smoke_Test()
54-
{
55-
var input = "".ToCharArray().ToList();
56-
var permuations = Permutation.Find<char>(input, false, false);
57-
Assert.AreEqual(factorial(input.Count) / 2, permuations.Count);
37+
input = "scan".ToCharArray().ToList();
38+
permuations = Permutation.Find<char>(input, 2, true);
39+
Assert.AreEqual(Math.Pow(input.Count, 2), permuations.Count);
5840

59-
input = "abc".ToCharArray().ToList();
60-
permuations = Permutation.Find<char>(input, false, false);
61-
Assert.AreEqual(factorial(input.Count) / 2, permuations.Count);
41+
input = "scan".ToCharArray().ToList();
42+
permuations = Permutation.Find<char>(input, 3, true);
43+
Assert.AreEqual(Math.Pow(input.Count, 3), permuations.Count);
6244

63-
input = "acde".ToCharArray().ToList();
64-
permuations = Permutation.Find<char>(input, false, false);
65-
Assert.AreEqual(factorial(input.Count) / 2, permuations.Count);
45+
input = "scaner".ToCharArray().ToList();
46+
permuations = Permutation.Find<char>(input, 4, true);
47+
Assert.AreEqual(Math.Pow(input.Count, 4), permuations.Count);
6648
}
6749

6850

6951
[TestMethod]
70-
public void Permutation_With_Repetition_Without_Inversions_Smoke_Test()
52+
public void Permutation_Without_Repetitions_Smoke_Test()
7153
{
72-
7354
var input = "".ToCharArray().ToList();
74-
var permuations = Permutation.Find<char>(input, true, false);
75-
Assert.AreEqual(0, permuations.Count);
55+
var permuations = Permutation.Find<char>(input, input.Count);
56+
Assert.AreEqual(permutation(input.Count, input.Count), permuations.Count);
7657

77-
input = "pen".ToCharArray().ToList();
78-
permuations = Permutation.Find<char>(input, true, false);
79-
Assert.AreEqual(9, permuations.Count);
58+
input = "cookie".ToCharArray().ToList();
59+
permuations = Permutation.Find<char>(input, input.Count);
60+
Assert.AreEqual(permutation(input.Count, input.Count), permuations.Count);
8061

81-
input = "cool".ToCharArray().ToList();
82-
permuations = Permutation.Find<char>(input, true, false);
83-
Assert.AreEqual(80, permuations.Count);
84-
}
62+
input = "monster".ToCharArray().ToList();
63+
permuations = Permutation.Find<char>(input, input.Count);
64+
Assert.AreEqual(permutation(input.Count, input.Count), permuations.Count);
8565

86-
66+
input = "cookie".ToCharArray().ToList();
67+
permuations = Permutation.Find<char>(input, 2);
68+
Assert.AreEqual(permutation(input.Count, 2), permuations.Count);
69+
70+
input = "monster".ToCharArray().ToList();
71+
permuations = Permutation.Find<char>(input, 3);
72+
Assert.AreEqual(permutation(input.Count, 3), permuations.Count);
73+
}
8774
}
8875
}

Advanced.Algorithms/Combinatorics/Permutation.cs

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@ namespace Advanced.Algorithms.Combinatorics
88
{
99
public class Permutation
1010
{
11-
public static List<List<T>> Find<T>(List<T> input, bool withRepetition = false)
11+
public static List<List<T>> Find<T>(List<T> input, int r, bool withRepetition = false)
1212
{
1313
var result = new List<List<T>>();
1414

15-
Recurse(input, withRepetition, new List<T>(), new HashSet<int>(), result);
15+
Recurse(input, r, withRepetition, new List<T>(), new HashSet<int>(), result);
1616

1717
return result;
1818
}
1919

20-
private static void Recurse<T>(List<T> input, bool withRepetition,
20+
private static void Recurse<T>(List<T> input, int r, bool withRepetition,
2121
List<T> prefix, HashSet<int> prefixIndices,
2222
List<List<T>> result)
2323
{
24-
if (prefix.Count == input.Count)
24+
if (prefix.Count == r)
2525
{
2626
result.Add(new List<T>(prefix));
2727
return;
@@ -37,53 +37,7 @@ private static void Recurse<T>(List<T> input, bool withRepetition,
3737
prefix.Add(input[j]);
3838
prefixIndices.Add(j);
3939

40-
Recurse(input, withRepetition, prefix, prefixIndices, result);
41-
42-
prefix.RemoveAt(prefix.Count - 1);
43-
prefixIndices.Remove(j);
44-
}
45-
}
46-
47-
public static List<List<T>> Find<T>(List<T> input, bool withRepetition,
48-
bool withInversions) where T : IComparable
49-
{
50-
var result = new List<List<T>>();
51-
52-
Recurse(input, withRepetition, withInversions,
53-
new List<T>(), new HashSet<int>(), result);
54-
55-
return result;
56-
}
57-
58-
private static void Recurse<T>(List<T> input,
59-
bool withRepetition, bool withInversions,
60-
List<T> prefix, HashSet<int> prefixIndices,
61-
List<List<T>> result) where T : IComparable
62-
{
63-
if (prefix.Count == input.Count
64-
&& (withInversions ||
65-
(prefix.Count > 0 && prefix[0].CompareTo(prefix[prefix.Count - 1]) < 0)))
66-
{
67-
result.Add(new List<T>(prefix));
68-
return;
69-
}
70-
71-
if (prefix.Count == input.Count)
72-
{
73-
return;
74-
}
75-
76-
for (int j = 0; j < input.Count; j++)
77-
{
78-
if (prefixIndices.Contains(j) && !withRepetition)
79-
{
80-
continue;
81-
}
82-
83-
prefix.Add(input[j]);
84-
prefixIndices.Add(j);
85-
86-
Recurse(input, withRepetition, withInversions, prefix, prefixIndices, result);
40+
Recurse(input, r, withRepetition, prefix, prefixIndices, result);
8741

8842
prefix.RemoveAt(prefix.Count - 1);
8943
prefixIndices.Remove(j);

0 commit comments

Comments
 (0)