Skip to content

Commit

Permalink
Merge pull request #465 from sir-gon/feature/sherlock-and-valid-string
Browse files Browse the repository at this point in the history
[Hacker Rank] Interview Preparation Kit: String Manipulation: Sherloc…
  • Loading branch information
sir-gon authored Aug 31, 2024
2 parents e8eb493 + 0752034 commit 1563c08
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# [String Manipulation: Sherlock and the Valid String](https://www.hackerrank.com/challenges/sherlock-and-valid-string)

- Difficulty: `#medium`
- Category: `#ProblemSolvinIntermediate` `#strings`

Sherlock considers a string to be valid if all characters of the string appear
the same number of times.
It is also valid if he can remove just ´1´ character at index in the string,
and the remaining characters will occur the same number of times.
Given a string `s`, determine if it is valid.
If so, return `YES`, otherwise return `NO`.

## Example

`s = abc`

This is a valid string because frequencies are `{a: 1, b: 1, c: 1}`.

`s = abcc`

This is a valid string because we can remove one `c` and have of
each character in the remaining string.

`s = abccc`

This string is not valid as we can only remove `1` occurrence of `c`.
That leaves character frequencies of `{a: 1, b: 1, c: 2}`.

## Function Description

Complete the isValid function in the editor below.

isValid has the following parameter(s):

- `string s`: a string

## Returns

- `string`: either `YES` or `NO`

## Input Format

A single string `s`.

## Constraints

- $ 1 \leq |s| \leq 10^5 $
- Each character `s[i]` $ \in $ `ascii[a-z]`

## Sample Input 0

```text
aabbcd
```

## Sample Output 0

```text
NO
```

## Explanation 0

Given `s = "abbcd"`, we would need to remove two characters,
both `c` and `d` -> `aabb` or a and b abcd, to make it valid.
We are limited to removing only one character, so `s` is invalid.

## Sample Input 1

```text
aabbccddeefghi
```

## Sample Output 1

```text
NO
```

## Explanation 1

Frequency counts for the letters are as follows:

```text
{'a': 2, 'b': 2, 'c': 2, 'd': 2, 'e': 2, 'f': 1, 'g': 1, 'h': 1, 'i': 1}
```

There are two ways to make the valid string:

- Remove `4` characters with a frequency of `1`: `{fghi}`.
- Remove `5` characters of frequency `2`: `{abcde}`.
Neither of these is an option.

## Sample Input 2

```text
abcdefghhgfedecba
```

## Sample Output 2

```text
YES
```

## Explanation 2

All characters occur twice except for `e` which occurs `3` times.
We can delete one instance of `e` to have a valid string.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { describe, expect, it } from '@jest/globals';

import { isValid } from './sherlock_and_valid_string';
import TEST_CASES from './sherlock_and_valid_string.testcases.json';

describe('isValid', () => {
it('isValid test cases', () => {
expect.assertions(9);

const __YES__ = 'YES';

TEST_CASES.forEach((test) => {
const result = isValid(test.input) === __YES__;

expect(result).toStrictEqual(test.expected);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[
{
"title": "counterexample",
"input": "aabbccc",
"expected": true
},
{
"title": "counterexample",
"input": "a",
"expected": true
},
{
"title": "counterexample",
"input": "aaa",
"expected": true
},
{
"title": "counterexample",
"input": "abbccc",
"expected": false
},
{
"title": "counterexample",
"input": "bbccc",
"expected": false
},
{
"title": "Sample Test case 0",
"input": "aabbcd",
"expected": false
},
{
"title": "Sample Test case 1",
"input": "aabbccddeefghi",
"expected": false
},
{
"title": "Sample Test case 2",
"input": "abcdefghhgfedecba",
"expected": true
},
{
"title": "Sample Test case 4",
"input": "aabbc",
"expected": true
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* @link Problem definition [[docs/hackerrank/interview_preparation_kit/string_manipulation/sherlock-and-valid-string.md]]
*/

const __YES__ = 'YES';
const __NO__ = 'NO';

export function isValidCompute(s: string): boolean {
if (s.length <= 1) {
return true;
}

const stringMap: Record<string, number> = {};

for (const letter of s.split('')) {
stringMap[letter] = stringMap?.[letter] ? stringMap[letter] + 1 : 1;
}

const frequencies: Record<number, number> = {};

for (const event of Object.values(stringMap)) {
frequencies[event] = frequencies?.[event] ? frequencies[event] + 1 : 1;
}

const frequenciesSize = Object.entries(frequencies).length;

if (frequenciesSize === 1) {
return true;
}

if (frequenciesSize === 2) {
const frequenciesList = Object.entries(frequencies).sort(
([, a], [, b]) => a - b
);
const __RADIX__ = 10;
const __TOLERANCE__ = 1;
const minorFreq: number = parseInt(frequenciesList[0][0], __RADIX__);
const majorFreq: number = parseInt(frequenciesList[1][0], __RADIX__);

if (
frequencies[minorFreq] === __TOLERANCE__ &&
(minorFreq === __TOLERANCE__ || minorFreq - majorFreq === __TOLERANCE__)
) {
return true;
}
}

return false;
}

export function isValid(s: string): string {
return isValidCompute(s) ? __YES__ : __NO__;
}

export default { isValid };

0 comments on commit 1563c08

Please sign in to comment.