From 191e21b31cc5682bd8a4e7fe5feda5ba23747b3e Mon Sep 17 00:00:00 2001 From: Farkhanda-Dalal <7farkhanda@gmail.com> Date: Thu, 18 Sep 2025 14:25:15 +0530 Subject: [PATCH] Added Anagram Check Functionality --- README.md | 24 +++++++++++++ package-lock.json | 24 +++++++------ package.json | 2 +- src/tests/validations/isAnagram.test.ts | 48 +++++++++++++++++++++++++ src/validations/index.ts | 5 ++- src/validations/isAnagram.ts | 23 ++++++++++++ 6 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 src/tests/validations/isAnagram.test.ts create mode 100644 src/validations/isAnagram.ts diff --git a/README.md b/README.md index d101a44..d37f2a6 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ const count = stringzy.analyze.wordCount('Hello world'); // 2 - [isUpperCase](#isuppercase) - Checks if given string only has upper case characters. - [isAlphabetic](#isalphabetic) - Checks if input string contains only Alphabets (case insensitive) - [isAlphaNumeric](#isalphanumeric) - Checks if input string contains only Alphabets and Digits (case insensitive) +- [isAnagram](#isanagram)- Checks if both strings are anagrams of each other. (ignores case and punctuations) ### Analysis @@ -730,6 +731,29 @@ isAlphaNumeric(''); // false | --------- | ------ | -------- | ----------------------------------------------- | | text | string | required | The input string to check for alphanumeric only | +#### `isAnagram(str1, str2)` + +Checks whether two strings are anagrams of each other (contain the same characters in the same frequency, regardless of order). +- Comparison is case-insensitive. +- Spaces and punctuation are ignored. +- Throws an error if either input is not a string. + +```javascript +import { isAnagram } from 'stringzy'; + +isAnagram('listen', 'silent'); // true +isAnagram('Debit Card', 'Bad Credit'); // true +isAnagram('Astronomer', 'Moon starer'); // true +isAnagram('hello', 'world'); // false +isAnagram('a', 'b'); // false +isAnagram('', ''); // true +``` + +| Parameter | Type | Default | Description | +| --------- | ------ | -------- | ---------------------------------------- | +| str1 | string | required | The first string to check as an anagram | +| str2 | string | required | The second string to check as an anagram | + --- ### 📊 Analysis diff --git a/package-lock.json b/package-lock.json index e4901a0..159a654 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,26 +1,27 @@ { "name": "stringzy", - "version": "3.0.0", + "version": "4.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "stringzy", - "version": "3.0.0", + "version": "4.0.0", "license": "MIT", "devDependencies": { - "@types/node": "^24.0.4", + "@types/node": "^24.5.2", "prettier": "^3.6.2", "typescript": "^5.8.3" } }, "node_modules/@types/node": { - "version": "24.0.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz", - "integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==", + "version": "24.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", + "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~7.8.0" + "undici-types": "~7.12.0" } }, "node_modules/prettier": { @@ -53,10 +54,11 @@ } }, "node_modules/undici-types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", - "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", - "dev": true + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", + "dev": true, + "license": "MIT" } } } diff --git a/package.json b/package.json index 3af744b..6888631 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "url": "git+https://github.com/Samarth2190/stringzy.git" }, "devDependencies": { - "@types/node": "^24.0.4", + "@types/node": "^24.5.2", "prettier": "^3.6.2", "typescript": "^5.8.3" } diff --git a/src/tests/validations/isAnagram.test.ts b/src/tests/validations/isAnagram.test.ts new file mode 100644 index 0000000..5a3f6f2 --- /dev/null +++ b/src/tests/validations/isAnagram.test.ts @@ -0,0 +1,48 @@ +import { describe, it } from 'node:test'; +import assert from 'node:assert'; +import { isAnagram } from '../../validations/isAnagram'; + +describe('isAnagram', () => { + it('returns true for valid anagrams (simple lowercase words)', () => { + assert.strictEqual(isAnagram('listen', 'silent'), true); + assert.strictEqual(isAnagram('evil', 'vile'), true); + }); + + it('returns true for case-insensitive matches', () => { + assert.strictEqual(isAnagram('Listen', 'Silent'), true); + assert.strictEqual(isAnagram('Debit Card', 'Bad Credit'), true); + }); + + it('returns true when ignoring spaces and punctuation', () => { + assert.strictEqual(isAnagram('Astronomer', 'Moon starer'), true); + assert.strictEqual(isAnagram('The eyes!!', 'They see'), true); + }); + + it('returns false for non-anagrams', () => { + assert.strictEqual(isAnagram('hello', 'world'), false); + assert.strictEqual(isAnagram('abc', 'abcd'), false); + }); + + it('returns true for single character anagrams', () => { + assert.strictEqual(isAnagram('a', 'a'), true); + }); + + it('returns false for different single characters', () => { + assert.strictEqual(isAnagram('a', 'b'), false); + }); + + it('returns true for empty strings (both empty)', () => { + assert.strictEqual(isAnagram('', ''), true); + }); + + it('returns false when only one string is empty', () => { + assert.strictEqual(isAnagram('', 'a'), false); + assert.strictEqual(isAnagram('a', ''), false); + }); + + it('throws an error if inputs are not strings', () => { + assert.throws(() => isAnagram(123 as any, 'abc'), /Both inputs must be strings/); + assert.throws(() => isAnagram(null as any, 'abc'), /Both inputs must be strings/); + assert.throws(() => isAnagram(undefined as any, 'abc'), /Both inputs must be strings/); + }); +}); diff --git a/src/validations/index.ts b/src/validations/index.ts index c1d0ae8..01b5d9d 100644 --- a/src/validations/index.ts +++ b/src/validations/index.ts @@ -11,6 +11,7 @@ export {isLowerCase} from './isLowerCase'; export {isUpperCase} from './isUpperCase'; export { isAlphabetic } from './isAlphabetic'; export { isAlphaNumeric } from './isAlphaNumeric'; +export { isAnagram } from './isAnagram'; import { isCoordinates } from './isCoordinates'; import { isDate } from './isDate'; @@ -25,6 +26,7 @@ import { isLowerCase } from './isLowerCase'; import { isUpperCase } from './isUpperCase'; import { isAlphabetic } from './isAlphabetic'; import { isAlphaNumeric } from './isAlphaNumeric'; +import { isAnagram } from './isAnagram'; export const validations = { isCoordinates, @@ -39,5 +41,6 @@ export const validations = { isLowerCase, isUpperCase, isAlphabetic, - isAlphaNumeric + isAlphaNumeric, + isAnagram }; diff --git a/src/validations/isAnagram.ts b/src/validations/isAnagram.ts new file mode 100644 index 0000000..0865f78 --- /dev/null +++ b/src/validations/isAnagram.ts @@ -0,0 +1,23 @@ +/** + * Checks whether two strings are anagrams of each other. + * + * Rules: + * - Comparison is case-insensitive. + * - Spaces and punctuation are ignored. + * + * @param {string} str1 - The first input string. + * @param {string} str2 - The second input string. + * @returns {boolean} True if the inputs are anagrams, otherwise false. + * @throws {TypeError} If either input is not a string. + */ +export function isAnagram(str1: string, str2: string): boolean { + if (typeof str1 !== 'string' || typeof str2 !== 'string') { + throw new TypeError('Both inputs must be strings'); + } + + // Normalize: lowercase, remove spaces & punctuation + const normalize = (str: string) => + str.toLowerCase().replace(/[^a-z0-9]/g, '').split('').sort().join(''); + + return normalize(str1) === normalize(str2); +}