Skip to content

Commit 874422c

Browse files
Add method to get all permutations (TheAlgorithms#293)
1 parent 56d1434 commit 874422c

File tree

4 files changed

+110
-0
lines changed

4 files changed

+110
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Algorithms.Numeric;
5+
using Algorithms.Strings;
6+
using FluentAssertions;
7+
using NUnit.Framework;
8+
9+
namespace Algorithms.Tests.Strings
10+
{
11+
public class PermutationTests
12+
{
13+
[TestCase("")]
14+
[TestCase("A")]
15+
[TestCase("abcd")]
16+
[TestCase("aabcd")]
17+
[TestCase("aabbbcd")]
18+
[TestCase("aabbbccccd")]
19+
public void Test_GetEveryUniquePermutation(string word)
20+
{
21+
var permutations = Permutation.GetEveryUniquePermutation(word);
22+
23+
// We need to make sure that
24+
// 1. We have the right number of permutations
25+
// 2. Every string in permutations List is a permutation of word
26+
// 3. There are no repetitions
27+
28+
// Start 1.
29+
// The number of unique permutations is
30+
// n!/(A1! * A2! * ... An!)
31+
// where n is the length of word and Ai is the number of occurrences if ith char in the string
32+
var charOccurrence = new Dictionary<char, int>();
33+
foreach (var c in word)
34+
{
35+
if (charOccurrence.ContainsKey(c))
36+
{
37+
charOccurrence[c] += 1;
38+
}
39+
else
40+
{
41+
charOccurrence[c] = 1;
42+
}
43+
}
44+
// now we know the values of A1, A2, ..., An
45+
// evaluate the above formula
46+
var expectedNumberOfAnagrams = Factorial.Calculate(word.Length);
47+
expectedNumberOfAnagrams = charOccurrence.Aggregate(expectedNumberOfAnagrams, (current, keyValuePair) =>
48+
{
49+
return current / Factorial.Calculate(keyValuePair.Value);
50+
});
51+
Assert.AreEqual(expectedNumberOfAnagrams, permutations.Count);
52+
// End 1.
53+
54+
// Start 2
55+
// string A is a permutation of string B if and only if sorted(A) == sorted(b)
56+
var wordSorted = SortString(word);
57+
foreach (var permutation in permutations)
58+
{
59+
Assert.AreEqual(wordSorted, SortString(permutation));
60+
}
61+
// End 2
62+
63+
// Start 3
64+
Assert.AreEqual(permutations.Count, new HashSet<string>(permutations).Count);
65+
// End 3
66+
}
67+
68+
private static string SortString(string word)
69+
{
70+
var asArray = word.ToArray();
71+
Array.Sort(asArray);
72+
return new string(asArray);
73+
}
74+
}
75+
}
File renamed without changes.

Algorithms/Strings/Permutation.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace Algorithms.Strings
5+
{
6+
public static class Permutation
7+
{
8+
/// <summary>
9+
/// Returns every anagram of a given word.
10+
/// </summary>
11+
/// <returns>List of anagrams.</returns>
12+
public static List<string> GetEveryUniquePermutation(string word)
13+
{
14+
if (word.Length < 2)
15+
{
16+
return new List<string>
17+
{
18+
word,
19+
};
20+
}
21+
22+
var result = new HashSet<string>();
23+
24+
for (var i = 0; i < word.Length; i++)
25+
{
26+
var temp = GetEveryUniquePermutation(word.Remove(i, 1));
27+
28+
result.UnionWith(temp.Select(subPerm => word[i] + subPerm));
29+
}
30+
31+
return result.ToList();
32+
}
33+
}
34+
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ This repository contains algorithms and data structures implemented in C# for ed
122122
* [Rabin Karp](./Algorithms/Strings/RabinKarp.cs)
123123
* [Boyer Moore](./Algorithms/Strings/BoyerMoore.cs)
124124
* [Palindrome Checker](./Algorithms/Strings/palindrome.cs)
125+
* [Get all permutations of a string](./Algorithms/Strings/Permutation.cs)
125126
* [Other](./Algorithms/Other)
126127
* [Fermat Prime Checker](./Algorithms/Other/FermatPrimeChecker.cs)
127128
* [Sieve of Eratosthenes](./Algorithms/Other/SieveOfEratosthenes.cs)

0 commit comments

Comments
 (0)