Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 43c6189

Browse files
author
Gonzalo Diaz
committed
[Hacker Rank] Interview Preparation Kit: Dictionaries and Hashmaps: Sherlock and Anagrams. Solved ✅.
1 parent b199ebf commit 43c6189

File tree

5 files changed

+352
-0
lines changed

5 files changed

+352
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# [Sherlock and Anagrams](https://www.hackerrank.com/challenges/sherlock-and-anagrams)
2+
3+
- Difficulty: `#medium`
4+
- Category: `#ProblemSolvingMedium` `#DictionariesAndHashmaps` `#Strings`
5+
6+
## About solution
7+
8+
To answer the question of "how many pairs" of words can be anagrammed
9+
using fragments from adjacent letters of an initial word, two steps are needed:
10+
11+
1) Obtain all possible fragment candidates to be anagrams,
12+
from each of the possible fragments that can be generated
13+
from adjacent letters of a word.
14+
15+
2) For each list of candidate anagrams,
16+
calculate all possible permutations and add them up.
17+
The total gives the answer.
18+
19+
The second part of this problem can be solved with the binomial coefficient formula:
20+
21+
<https://en.wikipedia.org/wiki/Binomial_coefficient>
22+
23+
But the entire cost of this formula falls on the "factorial" function.
24+
25+
In javascript, the factorial quickly reaches results that return large numbers,
26+
in scientific notation, losing precision.
27+
This loss of precision can result in an erroneous result
28+
in the final calculation of permutations.
29+
30+
To avoid this problem, it is necessary to introduce large number handling using BigInt.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# [Sherlock and Anagrams](https://www.hackerrank.com/challenges/sherlock-and-anagrams)
2+
3+
- Difficulty: `#medium`
4+
- Category: `#ProblemSolvingMedium` `#DictionariesAndHashmaps` `#Strings`
5+
6+
Two strings are [http://en.wikipedia.org/wiki/Anagram](anagrams) of each other
7+
if the letters of one string can be rearranged to form the other string.
8+
Given a string, find the number of pairs of substrings of the string that are
9+
anagrams of each other.
10+
11+
## Example
12+
13+
`s = mom`
14+
15+
The list of all anagrammatic pairs is `[m, m]`, `[mo, om]`
16+
at positions `[[0], [2]]`, `[[0, 1], [1, 2]]` respectively.
17+
18+
## Function Description
19+
20+
Complete the function sherlockAndAnagrams in the editor below.
21+
22+
*sherlockAndAnagrams* has the following parameter(s):
23+
24+
- `string s`: a string
25+
26+
## Returns
27+
28+
- `int`: the number of unordered anagrammatic pairs of substrings in **`s`**
29+
30+
## Input Format
31+
32+
The first line contains an integer `q`, the number of queries.
33+
Each of the next `q` lines contains a string `s` to analyze.
34+
35+
## Constraints
36+
37+
- $ 1 \leq 10 \leq 10 $
38+
- $ 2 \leq $ lenght of `s` $ \leq 100 $
39+
40+
`s` contains only lowercase letters in the range ascii[a-z].
41+
42+
## Sample Input 0
43+
44+
```text
45+
2
46+
abba
47+
abcd
48+
```
49+
50+
## Sample Output 0
51+
52+
```text
53+
4
54+
0
55+
```
56+
57+
## Explanation 0
58+
59+
The list of all anagrammatic pairs is `[a, a]`, `[ab, ba]`,
60+
`[b, b]` and `[abb, bba]` at positions `[[0], [3]]`, `[[0, 1]], [[2, 3]]`,
61+
`[[1], [2]]` and `[[0, 1, 2], [1, 2, 3]]` respectively.
62+
63+
No anagrammatic pairs exist in the second query as no character repeats.
64+
65+
## Sample Input 1
66+
67+
```text
68+
2
69+
ifailuhkqq
70+
kkkk
71+
````
72+
73+
## Sample Output 1
74+
75+
```text
76+
3
77+
10
78+
```
79+
80+
## Explanation 1
81+
82+
For the first query, we have anagram pairs `[i, i]`, `[q, q]`
83+
and `[ifa, fai]` at positions `[[0], [3]]`, `[[8], [9]]`
84+
and `[[0, 1, 2], [1, 2, 3]]` respectively.
85+
86+
For the second query:
87+
88+
There are `6` anagrams of the form `[k, k]` at positions `[[0, 1]]`,
89+
`[[0], [2]]`, `[[0], [3]]`, `[[1], [2]]`, `[[1], [3]]` and `[[2], [3]]`.
90+
91+
There are 3 anagrams of the form `[kk, kk]` at positions `[[0, 1], [1, 2]]`,
92+
`[[0, 1], [2, 3]]` and `[[1, 2], [2, 3]]`.
93+
94+
There is 1 anagram of the form `[kkk, kkk]` at position `[[0, 1, 2], [1, 2, 3]]`.
95+
96+
## Sample Input 2
97+
98+
```text
99+
1
100+
cdcd
101+
```
102+
103+
## Sample Output 2
104+
105+
```text
106+
5
107+
```
108+
109+
## Explanation 2
110+
111+
There are two anagrammatic pairs of length `1`: `[c, c]` and `[d, d]`.
112+
There are three anagrammatic pairs of length `2`:
113+
`[cd, dc]`, `[cd, cd]`, `[dc, cd]` at positions
114+
`[[0, 1] [1, 2]]`, `[[0, 1], [2, 3]]`, `[1, 2], [2, 3]` respectively.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// @link Problem definition [[docs/hackerrank/interview_preparation_kit/dictionaries_and_hashmaps/ctci-ransom-note.md]]
2+
3+
namespace algorithm_exercises_csharp.hackerrank.interview_preparation_kit.dictionaries_and_hashmaps;
4+
5+
using System.Diagnostics.CodeAnalysis;
6+
using System.Numerics;
7+
8+
public class SherlockAndAnagrams
9+
{
10+
[ExcludeFromCodeCoverage]
11+
protected SherlockAndAnagrams() { }
12+
13+
/**
14+
* factorial().
15+
*/
16+
public static BigInteger factorial(int number)
17+
{
18+
BigInteger result = BigInteger.One;
19+
for (int i = 1; i <= number; i++)
20+
{
21+
result *= i;
22+
}
23+
24+
return result;
25+
}
26+
27+
public static int sherlockAndAnagrams(string s)
28+
{
29+
Dictionary<string, List<string>> candidates = [];
30+
31+
int size = s.Length;
32+
for (int i = 0; i < size; i++)
33+
{
34+
for (int j = 0; j < size - i; j++)
35+
{
36+
string word = s[i..(size - j)];
37+
char[] wordArray = word.ToCharArray();
38+
Array.Sort(wordArray);
39+
string anagramCandidate = new(wordArray);
40+
41+
if (candidates.TryGetValue(anagramCandidate, out List<string>? value))
42+
{
43+
value.Add(word);
44+
}
45+
else
46+
{
47+
candidates[anagramCandidate] = [word];
48+
}
49+
}
50+
}
51+
52+
int total = 0;
53+
54+
foreach (List<string> value in candidates.Values)
55+
{
56+
int quantityOfAnagrams = value.Count;
57+
int k = 2;
58+
59+
if (quantityOfAnagrams > 1)
60+
{
61+
// Binomial coefficient: https://en.wikipedia.org/wiki/Binomial_coefficient
62+
int count = (int)(factorial(quantityOfAnagrams) / factorial(k) / factorial(quantityOfAnagrams - k));
63+
total += count;
64+
}
65+
}
66+
67+
return total;
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
[
2+
{
3+
"title": "Sample Test Case 0",
4+
"tests": [
5+
{
6+
"input": "abba",
7+
"expected": 4
8+
},
9+
{
10+
"input": "abcd",
11+
"expected": 0
12+
}
13+
]
14+
},
15+
{
16+
"title": "Sample Test Case 1",
17+
"tests": [
18+
{
19+
"input": "ifailuhkqq",
20+
"expected": 3
21+
},
22+
{
23+
"input": "kkkk",
24+
"expected": 10
25+
}
26+
]
27+
},
28+
{
29+
"title": "Sample Test Case 1",
30+
"tests": [
31+
{
32+
"input": "cdcd",
33+
"expected": 5
34+
}
35+
]
36+
},
37+
{
38+
"title": "Test case 3",
39+
"tests": [
40+
{
41+
"input":
42+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
43+
"expected": 166650
44+
},
45+
{
46+
"input":
47+
"bbcaadacaacbdddcdbddaddabcccdaaadcadcbddadababdaaabcccdcdaacadcababbabbdbacabbdcbbbbbddacdbbcdddbaaa",
48+
"expected": 4832
49+
},
50+
{
51+
"input":
52+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
53+
"expected": 166650
54+
},
55+
{
56+
"input":
57+
"cacccbbcaaccbaacbbbcaaaababcacbbababbaacabccccaaaacbcababcbaaaaaacbacbccabcabbaaacabccbabccabbabcbba",
58+
"expected": 13022
59+
},
60+
{
61+
"input":
62+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
63+
"expected": 166650
64+
},
65+
{
66+
"input":
67+
"bbcbacaabacacaaacbbcaabccacbaaaabbcaaaaaaaccaccabcacabbbbabbbbacaaccbabbccccaacccccabcabaacaabbcbaca",
68+
"expected": 9644
69+
},
70+
{
71+
"input":
72+
"cbaacdbaadbabbdbbaabddbdabbbccbdaccdbbdacdcabdbacbcadbbbbacbdabddcaccbbacbcadcdcabaabdbaacdccbbabbbc",
73+
"expected": 6346
74+
},
75+
{
76+
"input":
77+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
78+
"expected": 166650
79+
},
80+
{
81+
"input":
82+
"babacaccaaabaaaaaaaccaaaccaaccabcbbbabccbbabababccaabcccacccaaabaccbccccbaacbcaacbcaaaaaaabacbcbbbcc",
83+
"expected": 8640
84+
},
85+
{
86+
"input":
87+
"bcbabbaccacbacaacbbaccbcbccbaaaabbbcaccaacaccbabcbabccacbaabbaaaabbbcbbbbbaababacacbcaabbcbcbcabbaba",
88+
"expected": 11577
89+
}
90+
]
91+
}
92+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace algorithm_exercises_csharp_test.hackerrank.interview_preparation_kit.dictionaries_and_hashmaps;
2+
using algorithm_exercises_csharp_test.lib;
3+
using algorithm_exercises_csharp.hackerrank.interview_preparation_kit.dictionaries_and_hashmaps;
4+
5+
[TestClass]
6+
public class SherlockAndAnagramsTest
7+
{
8+
public class SherlockAndAnagramsTestCase
9+
{
10+
/**
11+
* SherlockAndAnagramsTestCase.TestCase.
12+
*/
13+
public class TestCase
14+
{
15+
public string input { get; set; } = default!;
16+
public int expected { get; set; } = default!;
17+
}
18+
19+
public string title { get; set; } = default!;
20+
public List<TestCase> tests { get; set; } = default!;
21+
}
22+
23+
private List<SherlockAndAnagramsTestCase> testCases { get; set; } = default!;
24+
25+
[TestInitialize]
26+
public void testInitialize()
27+
{
28+
testCases = JsonLoader.resourceLoad<List<SherlockAndAnagramsTestCase>>(
29+
"hackerrank/interview_preparation_kit/dictionaries_and_hashmaps/sherlock_and_anagrams.testcases.json"
30+
) ?? [];
31+
}
32+
33+
[TestMethod]
34+
public void testSherlockAndAnagrams()
35+
{
36+
int result;
37+
38+
foreach (SherlockAndAnagramsTestCase testSet in testCases)
39+
{
40+
foreach (SherlockAndAnagramsTestCase.TestCase test in testSet.tests)
41+
{
42+
result = SherlockAndAnagrams.sherlockAndAnagrams(test.input);
43+
Assert.AreEqual(test.expected, result);
44+
}
45+
}
46+
}
47+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /