Skip to content

Commit 6da05a2

Browse files
committed
Updates from code review
1 parent a410a72 commit 6da05a2

File tree

2 files changed

+61
-50
lines changed

2 files changed

+61
-50
lines changed

Dynamic-Programming/Abbreviation.js

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,47 @@
11
/**
22
* @description
3-
* Given two strings, `a` and `b`, determine if it's possible to make `a` equal
4-
* to `b` You can perform the following operations on the string `a`:
5-
* 1. Capitalize zero or more of `a`'s lowercase letters.
6-
* 2. Delete all the remaining lowercase letters in `a`.
3+
* Given two strings, `source` and `target`, determine if it's possible to make `source` equal
4+
* to `target` You can perform the following operations on the string `source`:
5+
* 1. Capitalize zero or more of `source`'s lowercase letters.
6+
* 2. Delete all the remaining lowercase letters in `source`.
77
*
8-
* ### Algorithm
9-
* The idea is in the problem statement itself: iterate through characters of
10-
* string `a` and `b` (for character indexes `i` and `j` respectively):
11-
* 1. If `a[i]` and `b[j]` are equal, then move to next position
12-
* 2. If `a[i]` is lowercase of `b[j]`, then explore two possibilities:
13-
* a) Capitalize `a[i]` or
14-
* b) Skip `a[i]`
15-
* 3. If the `a[i]` is not uppercase, just discard that character, else return
16-
* `false`
8+
* Time Complexity: (O(|source|*|target|)) where `|source|` => length of string `source`
179
*
18-
* Time Complexity: (O(|a|*|b|)) where `|a|` => length of string `a`
19-
*
20-
* @param {String} a
21-
* @param {String} b
22-
* @returns {Boolean}
10+
* @param {String} source - The string to be transformed.
11+
* @param {String} target - The string we want to transform `source` into.
12+
* @returns {Boolean} - Whether the transformation is possible.
2313
* @see https://www.hackerrank.com/challenges/abbr/problem - Related problem on HackerRank.
2414
*/
25-
export const abbreviation = (a, b) => {
26-
const n = a.length
27-
const m = b.length
15+
export const isAbbreviation = (source, target) => {
16+
const sourceLength = source.length
17+
const targetLength = target.length
2818

29-
let dp = Array.from({length: n + 1}, () => Array(m + 1).fill(false))
30-
dp[0][0] = true
19+
// Initialize a table to keep track of possible abbreviations
20+
let canAbbreviate = Array.from({ length: sourceLength + 1 }, () =>
21+
Array(targetLength + 1).fill(false)
22+
)
23+
// Empty strings are trivially abbreviatable
24+
canAbbreviate[0][0] = true
3125

32-
for (let i = 0; i < n; i++) {
33-
for (let j = 0; j <= m; j++) {
34-
if (dp[i][j]) {
35-
if (j < m && a[i].toUpperCase() === b[j]) {
36-
dp[i + 1][j + 1] = true
26+
for (let sourceIndex = 0; sourceIndex < sourceLength; sourceIndex++) {
27+
for (let targetIndex = 0; targetIndex <= targetLength; targetIndex++) {
28+
if (canAbbreviate[sourceIndex][targetIndex]) {
29+
// If characters at the current position are equal, move to the next position in both strings.
30+
if (
31+
targetIndex < targetLength &&
32+
source[sourceIndex].toUpperCase() === target[targetIndex]
33+
) {
34+
canAbbreviate[sourceIndex + 1][targetIndex + 1] = true
3735
}
38-
if (a[i] === a[i].toLowerCase()) {
39-
dp[i + 1][j] = true
36+
// If the current character in `source` is lowercase, explore two possibilities:
37+
// a) Capitalize it (which is akin to "using" it in `source` to match `target`), or
38+
// b) Skip it (effectively deleting it from `source`).
39+
if (source[sourceIndex] === source[sourceIndex].toLowerCase()) {
40+
canAbbreviate[sourceIndex + 1][targetIndex] = true
4041
}
4142
}
4243
}
4344
}
4445

45-
return dp[n][m]
46-
}
46+
return canAbbreviate[sourceLength][targetLength]
47+
}
Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
1-
import { abbreviation } from '../Abbreviation.js'
1+
import { isAbbreviation } from '../Abbreviation.js'
22

3-
describe('Abbreviation', () => {
4-
test('it can abbreviate string a to b', () => {
5-
expect(abbreviation('', '')).toBe(true)
6-
expect(abbreviation('a', '')).toBe(true)
7-
expect(abbreviation('', 'A')).toBe(false)
8-
expect(abbreviation('a', 'A')).toBe(true)
9-
expect(abbreviation('abcDE', 'ABCDE')).toBe(true)
10-
expect(abbreviation('ABcDE', 'ABCDE')).toBe(true)
11-
expect(abbreviation('abcde', 'ABCDE')).toBe(true)
12-
expect(abbreviation('abcde', 'ABC')).toBe(true)
13-
expect(abbreviation('a', 'ABC')).toBe(false)
14-
expect(abbreviation('abcXYdefghijKLmnopqrs', 'XYKL')).toBe(true)
15-
expect(abbreviation('aBcXYdefghijKLmnOpqrs', 'XYKLOP')).toBe(false)
16-
expect(abbreviation('abc123', 'ABC')).toBe(true)
17-
expect(abbreviation('abc123', 'ABC123')).toBe(true)
18-
expect(abbreviation('abc!@#def', 'ABC')).toBe(true)
3+
const expectPositive = (word, abbr) =>
4+
expect(isAbbreviation(word, abbr)).toBe(true)
5+
const expectNegative = (word, abbr) =>
6+
expect(isAbbreviation(word, abbr)).toBe(false)
7+
8+
describe('Abbreviation - Positive Tests', () => {
9+
test('it should correctly abbreviate or transform the source string to match the target string', () => {
10+
expectPositive('', '')
11+
expectPositive('a', '')
12+
expectPositive('a', 'A')
13+
expectPositive('abcDE', 'ABCDE')
14+
expectPositive('ABcDE', 'ABCDE')
15+
expectPositive('abcde', 'ABCDE')
16+
expectPositive('abcde', 'ABC')
17+
expectPositive('abcXYdefghijKLmnopqrs', 'XYKL')
18+
expectPositive('abc123', 'ABC')
19+
expectPositive('abc123', 'ABC123')
20+
expectPositive('abc!@#def', 'ABC')
21+
})
22+
})
23+
24+
describe('Abbreviation - Negative Tests', () => {
25+
test('it should fail to abbreviate or transform the source string when it is not possible to match the target string', () => {
26+
expectNegative('', 'A')
27+
expectNegative('a', 'ABC')
28+
expectNegative('aBcXYdefghijKLmnOpqrs', 'XYKLOP')
1929
})
20-
})
30+
})

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy