diff --git a/src/pages/string/index.ts b/src/pages/string/index.ts index 3011347..ccc5a01 100644 --- a/src/pages/string/index.ts +++ b/src/pages/string/index.ts @@ -1,3 +1,4 @@ +import { tool as stringPalindrome } from './palindrome/meta'; import { tool as stringToMorse } from './to-morse/meta'; import { tool as stringSplit } from './split/meta'; import { tool as stringJoin } from './join/meta'; diff --git a/src/pages/string/palindrome/index.tsx b/src/pages/string/palindrome/index.tsx new file mode 100644 index 0000000..a7104cb --- /dev/null +++ b/src/pages/string/palindrome/index.tsx @@ -0,0 +1,11 @@ +import { Box } from '@mui/material'; +import React from 'react'; +import * as Yup from 'yup'; + +const initialValues = {}; +const validationSchema = Yup.object({ + // splitSeparator: Yup.string().required('The separator is required') +}); +export default function Palindrome() { + return Lorem ipsum; +} \ No newline at end of file diff --git a/src/pages/string/palindrome/meta.ts b/src/pages/string/palindrome/meta.ts new file mode 100644 index 0000000..868cff3 --- /dev/null +++ b/src/pages/string/palindrome/meta.ts @@ -0,0 +1,13 @@ +import { defineTool } from '@tools/defineTool'; +import { lazy } from 'react'; +// import image from '@assets/text.png'; + +export const tool = defineTool('string', { + name: 'Palindrome', + path: 'palindrome', + // image, + description: '', + shortDescription: '', + keywords: ['palindrome'], + component: lazy(() => import('./index')) +}); \ No newline at end of file diff --git a/src/pages/string/palindrome/palindrome.service.test.ts b/src/pages/string/palindrome/palindrome.service.test.ts new file mode 100644 index 0000000..10d5f2e --- /dev/null +++ b/src/pages/string/palindrome/palindrome.service.test.ts @@ -0,0 +1,60 @@ +import { expect, describe, it } from 'vitest'; +import { palindromeList } from './service'; + +describe('palindromeList', () => { + test('should return true for single character words', () => { + const input = 'a|b|c'; + const separator = '|'; + const result = palindromeList('symbol', input, separator); + expect(result).toBe('true|true|true'); + }); + + test('should return false for non-palindromes', () => { + const input = 'hello|world'; + const separator = '|'; + const result = palindromeList('symbol', input, separator); + expect(result).toBe('false|false'); + }); + + test('should split using regex', () => { + const input = 'racecar,abba,hello'; + const separator = ','; + const result = palindromeList('regex', input, separator); + expect(result).toBe('true,true,false'); + }); + + test('should return empty string for empty input', () => { + const input = ''; + const separator = '|'; + const result = palindromeList('symbol', input, separator); + expect(result).toBe(''); + }); + + test('should split using custom separator', () => { + const input = 'racecar;abba;hello'; + const separator = ';'; + const result = palindromeList('symbol', input, separator); + expect(result).toBe('true;true;false'); + }); + + test('should handle leading and trailing spaces', () => { + const input = ' racecar | abba | hello '; + const separator = '|'; + const result = palindromeList('symbol', input, separator); + expect(result).toBe('true|true|false'); + }); + + test('should handle multilines checking with trimming', () => { + const input = ' racecar \n abba \n hello '; + const separator = '\n'; + const result = palindromeList('symbol', input, separator); + expect(result).toBe('true\ntrue\nfalse'); + }); + + test('should handle empty strings in input', () => { + const input = 'racecar||hello'; + const separator = '|'; + const result = palindromeList('symbol', input, separator); + expect(result).toBe('true|true|false'); + }); +}); \ No newline at end of file diff --git a/src/pages/string/palindrome/service.ts b/src/pages/string/palindrome/service.ts new file mode 100644 index 0000000..e383fd4 --- /dev/null +++ b/src/pages/string/palindrome/service.ts @@ -0,0 +1,47 @@ +export type SplitOperatorType = 'symbol' | 'regex'; + +function isPalindrome( + word: string, + left: number, + right: number +): boolean { + if (left >= right) return true; + if (word[left] !== word[right]) return false; + + return isPalindrome(word, left + 1, right - 1); +} + +// check each word of the input and add the palindrome status in an array +function checkPalindromes(array: string[]): boolean[] { + let status: boolean[] = []; + for (const word of array) { + const palindromeStatus = isPalindrome(word, 0, word.length - 1); + status.push(palindromeStatus); + } + return status; +} + +export function palindromeList( + splitOperatorType: SplitOperatorType, + input: string, + separator: string, // the splitting separator will be the joining separator for visual satisfaction +): string { + if (!input) return ''; + let array: string[]; + switch (splitOperatorType) { + case 'symbol': + array = input.split(separator); + break; + case 'regex': + array = input.split(new RegExp(separator)); + break; + } + // trim all items to focus on the word and not biasing the result due to spaces (leading and trailing) + array = array.map((item) => item.trim()); + + const statusArray = checkPalindromes(array); + + return statusArray.map(status => status.toString()).join(separator); + +} +