Skip to content

Commit d8b693a

Browse files
authored
Merge pull request #520 from sir-gon/feature/sherlock-and-valid-string
[Hacker Rank] Interview Preparation Kit: String Manipulation: Sherloc…
2 parents 1b4a2e7 + 3f4c486 commit d8b693a

File tree

4 files changed

+229
-0
lines changed

4 files changed

+229
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# [String Manipulation: Sherlock and the Valid String](https://www.hackerrank.com/challenges/sherlock-and-valid-string)
2+
3+
- Difficulty: `#medium`
4+
- Category: `#ProblemSolvinIntermediate` `#strings`
5+
6+
Sherlock considers a string to be valid if all characters of the string appear
7+
the same number of times.
8+
It is also valid if he can remove just ´1´ character at index in the string,
9+
and the remaining characters will occur the same number of times.
10+
Given a string `s`, determine if it is valid.
11+
If so, return `YES`, otherwise return `NO`.
12+
13+
## Example
14+
15+
`s = abc`
16+
17+
This is a valid string because frequencies are `{a: 1, b: 1, c: 1}`.
18+
19+
`s = abcc`
20+
21+
This is a valid string because we can remove one `c` and have of
22+
each character in the remaining string.
23+
24+
`s = abccc`
25+
26+
This string is not valid as we can only remove `1` occurrence of `c`.
27+
That leaves character frequencies of `{a: 1, b: 1, c: 2}`.
28+
29+
## Function Description
30+
31+
Complete the isValid function in the editor below.
32+
33+
isValid has the following parameter(s):
34+
35+
- `string s`: a string
36+
37+
## Returns
38+
39+
- `string`: either `YES` or `NO`
40+
41+
## Input Format
42+
43+
A single string `s`.
44+
45+
## Constraints
46+
47+
- $ 1 \leq |s| \leq 10^5 $
48+
- Each character `s[i]` $ \in $ `ascii[a-z]`
49+
50+
## Sample Input 0
51+
52+
```text
53+
aabbcd
54+
```
55+
56+
## Sample Output 0
57+
58+
```text
59+
NO
60+
```
61+
62+
## Explanation 0
63+
64+
Given `s = "abbcd"`, we would need to remove two characters,
65+
both `c` and `d` -> `aabb` or a and b abcd, to make it valid.
66+
We are limited to removing only one character, so `s` is invalid.
67+
68+
## Sample Input 1
69+
70+
```text
71+
aabbccddeefghi
72+
```
73+
74+
## Sample Output 1
75+
76+
```text
77+
NO
78+
```
79+
80+
## Explanation 1
81+
82+
Frequency counts for the letters are as follows:
83+
84+
```text
85+
{'a': 2, 'b': 2, 'c': 2, 'd': 2, 'e': 2, 'f': 1, 'g': 1, 'h': 1, 'i': 1}
86+
```
87+
88+
There are two ways to make the valid string:
89+
90+
- Remove `4` characters with a frequency of `1`: `{fghi}`.
91+
- Remove `5` characters of frequency `2`: `{abcde}`.
92+
Neither of these is an option.
93+
94+
## Sample Input 2
95+
96+
```text
97+
abcdefghhgfedecba
98+
```
99+
100+
## Sample Output 2
101+
102+
```text
103+
YES
104+
```
105+
106+
## Explanation 2
107+
108+
All characters occur twice except for `e` which occurs `3` times.
109+
We can delete one instance of `e` to have a valid string.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @link Problem definition [[docs/hackerrank/interview_preparation_kit/string_manipulation/sherlock-and-valid-string.md]]
3+
*/
4+
5+
const __YES__ = 'YES';
6+
const __NO__ = 'NO';
7+
8+
export function isValidCompute(s) {
9+
if (s.length <= 1) {
10+
return true;
11+
}
12+
13+
const stringMap = {};
14+
15+
for (const letter of s.split('')) {
16+
stringMap[letter] = stringMap?.[letter] ? stringMap[letter] + 1 : 1;
17+
}
18+
19+
const frequencies = {};
20+
21+
for (const event of Object.values(stringMap)) {
22+
frequencies[event] = frequencies?.[event] ? frequencies[event] + 1 : 1;
23+
}
24+
25+
const frequenciesSize = Object.entries(frequencies).length;
26+
27+
if (frequenciesSize === 1) {
28+
return true;
29+
}
30+
31+
if (frequenciesSize === 2) {
32+
const frequenciesList = Object.entries(frequencies).sort(
33+
([, a], [, b]) => a - b
34+
);
35+
const __RADIX__ = 10;
36+
const __TOLERANCE__ = 1;
37+
const minorFreq = parseInt(frequenciesList[0][0], __RADIX__);
38+
const majorFreq = parseInt(frequenciesList[1][0], __RADIX__);
39+
40+
if (
41+
frequencies[minorFreq] === __TOLERANCE__ &&
42+
(minorFreq === __TOLERANCE__ || minorFreq - majorFreq === __TOLERANCE__)
43+
) {
44+
return true;
45+
}
46+
}
47+
48+
return false;
49+
}
50+
51+
export function isValid(s) {
52+
return isValidCompute(s) ? __YES__ : __NO__;
53+
}
54+
55+
export default { isValid };
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, expect, it } from '@jest/globals';
2+
3+
import { isValid } from './sherlock_and_valid_string.js';
4+
import TEST_CASES from './sherlock_and_valid_string.testcases.json';
5+
6+
describe('isValid', () => {
7+
it('isValid test cases', () => {
8+
expect.assertions(9);
9+
10+
const __YES__ = 'YES';
11+
12+
TEST_CASES.forEach((test) => {
13+
const result = isValid(test.input) === __YES__;
14+
15+
expect(result).toStrictEqual(test.expected);
16+
});
17+
});
18+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[
2+
{
3+
"title": "counterexample",
4+
"input": "aabbccc",
5+
"expected": true
6+
},
7+
{
8+
"title": "counterexample",
9+
"input": "a",
10+
"expected": true
11+
},
12+
{
13+
"title": "counterexample",
14+
"input": "aaa",
15+
"expected": true
16+
},
17+
{
18+
"title": "counterexample",
19+
"input": "abbccc",
20+
"expected": false
21+
},
22+
{
23+
"title": "counterexample",
24+
"input": "bbccc",
25+
"expected": false
26+
},
27+
{
28+
"title": "Sample Test case 0",
29+
"input": "aabbcd",
30+
"expected": false
31+
},
32+
{
33+
"title": "Sample Test case 1",
34+
"input": "aabbccddeefghi",
35+
"expected": false
36+
},
37+
{
38+
"title": "Sample Test case 2",
39+
"input": "abcdefghhgfedecba",
40+
"expected": true
41+
},
42+
{
43+
"title": "Sample Test case 4",
44+
"input": "aabbc",
45+
"expected": true
46+
}
47+
]

0 commit comments

Comments
 (0)