-
-
Notifications
You must be signed in to change notification settings - Fork 1
[Hacker Rank] Interview Preparation Kit: Dictionaries and Hashmaps: S… #292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
80 changes: 80 additions & 0 deletions
80
...e/hackerrank/interview_preparation_kit/dictionaries_and_hashmaps/SherlockAndAnagrams.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package ae.hackerrank.interview_preparation_kit.dictionaries_and_hashmaps; | ||
|
||
import java.math.BigInteger; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* SherlockAndAnagrams. | ||
* | ||
* @link Problem definition [[docs/hackerrank/interview_preparation_kit/dictionaries_and_hashmaps/sherlock_and_anagrams.md]] | ||
* @link Solution notes [[docs/hackerrank/interview_preparation_kit/dictionaries_and_hashmaps/sherlock_and_anagrams-solution-notes.md]] | ||
*/ | ||
public class SherlockAndAnagrams { | ||
private SherlockAndAnagrams() {} | ||
|
||
/** | ||
* factorial(). | ||
*/ | ||
public static BigInteger factorial(int number) { | ||
BigInteger result = BigInteger.ONE; | ||
for (int i = 1; i <= number; i++) { | ||
result = result.multiply(new BigInteger(Integer.toString(i))); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
/** | ||
* sherlockAndAnagrams. | ||
*/ | ||
public static int sherlockAndAnagrams(String sWord) { | ||
|
||
Map<String, List<String>> candidates = new HashMap<>(); | ||
int size = sWord.length(); | ||
|
||
for (int i = 0; i < size; i++) { | ||
for (int j = 0; j < size - i; j++) { | ||
String substr = sWord.substring(i, size - j); | ||
|
||
// Add substrings to a candidate list. | ||
// two strings are anagrams if sorted strings are the same. | ||
String anagramCandidate = Arrays.stream(substr.split("")) | ||
.sorted() | ||
.collect(Collectors.joining()); | ||
|
||
|
||
// Append candidates to dictionary by "sorted string" key | ||
if (candidates.containsKey(anagramCandidate)) { | ||
candidates.get(anagramCandidate).add(substr); | ||
} else { | ||
ArrayList<String> anagrams = new ArrayList<>(); | ||
anagrams.add(substr); | ||
candidates.put(anagramCandidate, anagrams); | ||
} | ||
} | ||
} | ||
|
||
int total = 0; | ||
|
||
// Final Anagram list | ||
for (Map.Entry<String, List<String>> entry : candidates.entrySet()) { | ||
int quantityOfAnagrams = entry.getValue().size(); | ||
int k = 2; | ||
|
||
if (quantityOfAnagrams > 1) { | ||
// Binomial coefficient: https://en.wikipedia.org/wiki/Binomial_coefficient | ||
int count = factorial(quantityOfAnagrams).divide( | ||
(factorial(k).multiply(factorial(quantityOfAnagrams - k))) | ||
).intValue(); | ||
total += count; | ||
} | ||
} | ||
|
||
return total; | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
...ckerrank/interview_preparation_kit/dictionaries_and_hashmaps/SherlockAndAnagramsTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package ae.hackerrank.interview_preparation_kit.dictionaries_and_hashmaps; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.TestInstance; | ||
import org.junit.jupiter.api.TestInstance.Lifecycle; | ||
import util.JsonLoader; | ||
|
||
/** | ||
* SherlockAndAnagrams. | ||
* | ||
* @link Problem definition [[docs/hackerrank/interview_preparation_kit/dictionaries_and_hashmaps/two-strings.md]] | ||
*/ | ||
@TestInstance(Lifecycle.PER_CLASS) | ||
class SherlockAndAnagramsTest { | ||
|
||
/** | ||
* SherlockAndAnagramsTestCase. | ||
*/ | ||
public static class SherlockAndAnagramsTestCase { | ||
/** | ||
* SherlockAndAnagramsTestCase.TestCase. | ||
*/ | ||
public static class TestCase { | ||
public String input; | ||
public Integer expected; | ||
} | ||
|
||
public String title; | ||
public List<TestCase> tests; | ||
} | ||
|
||
List<SherlockAndAnagramsTestCase> testCases; | ||
|
||
/** | ||
* Sets up the test environment by loading test cases from a JSON file. | ||
* The JSON file is located in the specified path relative to the project structure. | ||
* | ||
* @throws IOException if an error occurs while reading the JSON file. | ||
*/ | ||
@BeforeAll | ||
void setup() throws IOException { | ||
String path = String.join("/", "hackerrank", | ||
"interview_preparation_kit", | ||
"dictionaries_and_hashmaps", | ||
"sherlock_and_anagrams.testcases.json"); | ||
|
||
this.testCases = JsonLoader.loadJson(path, SherlockAndAnagramsTestCase.class); | ||
} | ||
|
||
private SherlockAndAnagramsTest() {} | ||
|
||
/** | ||
* sherlockAndAnagrams. | ||
*/ | ||
@Test void sherlockAndAnagrams() { | ||
for (SherlockAndAnagramsTestCase _testCases : this.testCases) { | ||
|
||
for (SherlockAndAnagramsTestCase.TestCase test : _testCases.tests) { | ||
Integer solutionFound = SherlockAndAnagrams.sherlockAndAnagrams(test.input); | ||
|
||
assertEquals(test.expected, solutionFound, | ||
"%s(%s) answer must be: %s".formatted( | ||
"SherlockAndAnagrams.sherlockAndAnagrams", | ||
test.input, | ||
test.expected | ||
) | ||
); | ||
} | ||
} | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
.../interview_preparation_kit/dictionaries_and_hashmaps/sherlock_and_anagrams.testcases.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
[ | ||
{ | ||
"title": "Sample Test Case 0", | ||
"tests": [ | ||
{ | ||
"input": "abba", | ||
"expected": 4 | ||
}, | ||
{ | ||
"input": "abcd", | ||
"expected": 0 | ||
} | ||
] | ||
}, | ||
{ | ||
"title": "Sample Test Case 1", | ||
"tests": [ | ||
{ | ||
"input": "ifailuhkqq", | ||
"expected": 3 | ||
}, | ||
{ | ||
"input": "kkkk", | ||
"expected": 10 | ||
} | ||
] | ||
}, | ||
{ | ||
"title": "Sample Test Case 1", | ||
"tests": [ | ||
{ | ||
"input": "cdcd", | ||
"expected": 5 | ||
} | ||
] | ||
}, | ||
{ | ||
"title": "Test case 3", | ||
"tests": [ | ||
{ | ||
"input": | ||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
"expected": 166650 | ||
}, | ||
{ | ||
"input": | ||
"bbcaadacaacbdddcdbddaddabcccdaaadcadcbddadababdaaabcccdcdaacadcababbabbdbacabbdcbbbbbddacdbbcdddbaaa", | ||
"expected": 4832 | ||
}, | ||
{ | ||
"input": | ||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
"expected": 166650 | ||
}, | ||
{ | ||
"input": | ||
"cacccbbcaaccbaacbbbcaaaababcacbbababbaacabccccaaaacbcababcbaaaaaacbacbccabcabbaaacabccbabccabbabcbba", | ||
"expected": 13022 | ||
}, | ||
{ | ||
"input": | ||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
"expected": 166650 | ||
}, | ||
{ | ||
"input": | ||
"bbcbacaabacacaaacbbcaabccacbaaaabbcaaaaaaaccaccabcacabbbbabbbbacaaccbabbccccaacccccabcabaacaabbcbaca", | ||
"expected": 9644 | ||
}, | ||
{ | ||
"input": | ||
"cbaacdbaadbabbdbbaabddbdabbbccbdaccdbbdacdcabdbacbcadbbbbacbdabddcaccbbacbcadcdcabaabdbaacdccbbabbbc", | ||
"expected": 6346 | ||
}, | ||
{ | ||
"input": | ||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
"expected": 166650 | ||
}, | ||
{ | ||
"input": | ||
"babacaccaaabaaaaaaaccaaaccaaccabcbbbabccbbabababccaabcccacccaaabaccbccccbaacbcaacbcaaaaaaabacbcbbbcc", | ||
"expected": 8640 | ||
}, | ||
{ | ||
"input": | ||
"bcbabbaccacbacaacbbaccbcbccbaaaabbbcaccaacaccbabcbabccacbaabbaaaabbbcbbbbbaababacacbcaabbcbcbcabbaba", | ||
"expected": 11577 | ||
} | ||
] | ||
} | ||
] |
30 changes: 30 additions & 0 deletions
30
...eparation_kit/dictionaries_and_hashmaps/sherlock_and_anagrams-solution-notes.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# [Sherlock and Anagrams](https://www.hackerrank.com/challenges/sherlock-and-anagrams) | ||
|
||
- Difficulty: `#medium` | ||
- Category: `#ProblemSolvingMedium` `#DictionariesAndHashmaps` `#Strings` | ||
|
||
## About solution | ||
|
||
To answer the question of "how many pairs" of words can be anagrammed | ||
using fragments from adjacent letters of an initial word, two steps are needed: | ||
|
||
1) Obtain all possible fragment candidates to be anagrams, | ||
from each of the possible fragments that can be generated | ||
from adjacent letters of a word. | ||
|
||
2) For each list of candidate anagrams, | ||
calculate all possible permutations and add them up. | ||
The total gives the answer. | ||
|
||
The second part of this problem can be solved with the binomial coefficient formula: | ||
|
||
<https://en.wikipedia.org/wiki/Binomial_coefficient> | ||
|
||
But the entire cost of this formula falls on the "factorial" function. | ||
|
||
In javascript, the factorial quickly reaches results that return large numbers, | ||
in scientific notation, losing precision. | ||
This loss of precision can result in an erroneous result | ||
in the final calculation of permutations. | ||
|
||
To avoid this problem, it is necessary to introduce large number handling using BigInt. |
114 changes: 114 additions & 0 deletions
114
...nk/interview_preparation_kit/dictionaries_and_hashmaps/sherlock_and_anagrams.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# [Sherlock and Anagrams](https://www.hackerrank.com/challenges/sherlock-and-anagrams) | ||
|
||
- Difficulty: `#medium` | ||
- Category: `#ProblemSolvingMedium` `#DictionariesAndHashmaps` `#Strings` | ||
|
||
Two strings are [http://en.wikipedia.org/wiki/Anagram](anagrams) of each other | ||
if the letters of one string can be rearranged to form the other string. | ||
Given a string, find the number of pairs of substrings of the string that are | ||
anagrams of each other. | ||
|
||
## Example | ||
|
||
`s = mom` | ||
|
||
The list of all anagrammatic pairs is `[m, m]`, `[mo, om]` | ||
at positions `[[0], [2]]`, `[[0, 1], [1, 2]]` respectively. | ||
|
||
## Function Description | ||
|
||
Complete the function sherlockAndAnagrams in the editor below. | ||
|
||
*sherlockAndAnagrams* has the following parameter(s): | ||
|
||
- `string s`: a string | ||
|
||
## Returns | ||
|
||
- `int`: the number of unordered anagrammatic pairs of substrings in **`s`** | ||
|
||
## Input Format | ||
|
||
The first line contains an integer `q`, the number of queries. | ||
Each of the next `q` lines contains a string `s` to analyze. | ||
|
||
## Constraints | ||
|
||
- $ 1 \leq 10 \leq 10 $ | ||
- $ 2 \leq $ lenght of `s` $ \leq 100 $ | ||
|
||
`s` contains only lowercase letters in the range ascii[a-z]. | ||
|
||
## Sample Input 0 | ||
|
||
```text | ||
2 | ||
abba | ||
abcd | ||
``` | ||
|
||
## Sample Output 0 | ||
|
||
```text | ||
4 | ||
0 | ||
``` | ||
|
||
## Explanation 0 | ||
|
||
The list of all anagrammatic pairs is `[a, a]`, `[ab, ba]`, | ||
`[b, b]` and `[abb, bba]` at positions `[[0], [3]]`, `[[0, 1]], [[2, 3]]`, | ||
`[[1], [2]]` and `[[0, 1, 2], [1, 2, 3]]` respectively. | ||
|
||
No anagrammatic pairs exist in the second query as no character repeats. | ||
|
||
## Sample Input 1 | ||
|
||
```text | ||
2 | ||
ifailuhkqq | ||
kkkk | ||
```` | ||
|
||
## Sample Output 1 | ||
|
||
```text | ||
3 | ||
10 | ||
``` | ||
|
||
## Explanation 1 | ||
|
||
For the first query, we have anagram pairs `[i, i]`, `[q, q]` | ||
and `[ifa, fai]` at positions `[[0], [3]]`, `[[8], [9]]` | ||
and `[[0, 1, 2], [1, 2, 3]]` respectively. | ||
|
||
For the second query: | ||
|
||
There are `6` anagrams of the form `[k, k]` at positions `[[0, 1]]`, | ||
`[[0], [2]]`, `[[0], [3]]`, `[[1], [2]]`, `[[1], [3]]` and `[[2], [3]]`. | ||
|
||
There are 3 anagrams of the form `[kk, kk]` at positions `[[0, 1], [1, 2]]`, | ||
`[[0, 1], [2, 3]]` and `[[1, 2], [2, 3]]`. | ||
|
||
There is 1 anagram of the form `[kkk, kkk]` at position `[[0, 1, 2], [1, 2, 3]]`. | ||
|
||
## Sample Input 2 | ||
|
||
```text | ||
1 | ||
cdcd | ||
``` | ||
|
||
## Sample Output 2 | ||
|
||
```text | ||
5 | ||
``` | ||
|
||
## Explanation 2 | ||
|
||
There are two anagrammatic pairs of length `1`: `[c, c]` and `[d, d]`. | ||
There are three anagrammatic pairs of length `2`: | ||
`[cd, dc]`, `[cd, cd]`, `[dc, cd]` at positions | ||
`[[0, 1] [1, 2]]`, `[[0, 1], [2, 3]]`, `[1, 2], [2, 3]` respectively. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.