diff --git a/Data-Structures/Array/RotateArray.js b/Data-Structures/Array/RotateArray.js new file mode 100644 index 0000000000..7228829041 --- /dev/null +++ b/Data-Structures/Array/RotateArray.js @@ -0,0 +1,61 @@ +/** + * Rotates an array to the right by k positions + * @see https://en.wikipedia.org/wiki/Circular_shift + * @param {number[]} array - The array to rotate + * @param {number} k - Number of positions to rotate + * @returns {number[]} - New array rotated to the right by k positions + * @throws {TypeError} - If input is not an array + */ +const rotateRight = (array, k) => { + if (!Array.isArray(array)) { + throw new TypeError('Input must be an array') + } + + if (!Number.isInteger(k) || k < 0) { + throw new TypeError('Rotation count must be a non-negative integer') + } + + const length = array.length + if (length === 0) return [] + + const normalizedK = k % length + const rotated = new Array(length) + + for (let i = 0; i < length; i++) { + rotated[(i + normalizedK) % length] = array[i] + } + + return rotated +} + +/** + * Rotates an array to the left by k positions + * @see https://en.wikipedia.org/wiki/Circular_shift + * @param {number[]} array - The array to rotate + * @param {number} k - Number of positions to rotate + * @returns {number[]} - New array rotated to the left by k positions + * @throws {TypeError} - If input is not an array + */ +const rotateLeft = (array, k) => { + if (!Array.isArray(array)) { + throw new TypeError('Input must be an array') + } + + if (!Number.isInteger(k) || k < 0) { + throw new TypeError('Rotation count must be a non-negative integer') + } + + const length = array.length + if (length === 0) return [] + + const normalizedK = k % length + const rotated = new Array(length) + + for (let i = 0; i < length; i++) { + rotated[i] = array[(i + normalizedK) % length] + } + + return rotated +} + +export { rotateRight, rotateLeft } diff --git a/Data-Structures/Array/test/RotateArray.test.js b/Data-Structures/Array/test/RotateArray.test.js new file mode 100644 index 0000000000..5f3b4930fa --- /dev/null +++ b/Data-Structures/Array/test/RotateArray.test.js @@ -0,0 +1,53 @@ +import { rotateRight, rotateLeft } from '../RotateArray.js' + +describe('rotateRight', () => { + it('should rotate array to the right by k positions', () => { + expect(rotateRight([1, 2, 3, 4, 5], 2)).toEqual([4, 5, 1, 2, 3]) + expect(rotateRight([1, 2, 3], 1)).toEqual([3, 1, 2]) + }) + + it('should handle rotation count larger than array length', () => { + expect(rotateRight([1, 2, 3], 5)).toEqual([2, 3, 1]) + expect(rotateRight([1], 10)).toEqual([1]) + }) + + it('should return empty array for empty input', () => { + expect(rotateRight([], 3)).toEqual([]) + }) + + it('should handle zero rotation', () => { + expect(rotateRight([1, 2, 3], 0)).toEqual([1, 2, 3]) + }) + + it('should throw TypeError for invalid inputs', () => { + expect(() => rotateRight('not an array', 1)).toThrow(TypeError) + expect(() => rotateRight([1, 2, 3], -1)).toThrow(TypeError) + expect(() => rotateRight([1, 2, 3], 1.5)).toThrow(TypeError) + }) +}) + +describe('rotateLeft', () => { + it('should rotate array to the left by k positions', () => { + expect(rotateLeft([1, 2, 3, 4, 5], 2)).toEqual([3, 4, 5, 1, 2]) + expect(rotateLeft([1, 2, 3], 1)).toEqual([2, 3, 1]) + }) + + it('should handle rotation count larger than array length', () => { + expect(rotateLeft([1, 2, 3], 5)).toEqual([3, 1, 2]) + expect(rotateLeft([1], 10)).toEqual([1]) + }) + + it('should return empty array for empty input', () => { + expect(rotateLeft([], 3)).toEqual([]) + }) + + it('should handle zero rotation', () => { + expect(rotateLeft([1, 2, 3], 0)).toEqual([1, 2, 3]) + }) + + it('should throw TypeError for invalid inputs', () => { + expect(() => rotateLeft('not an array', 1)).toThrow(TypeError) + expect(() => rotateLeft([1, 2, 3], -1)).toThrow(TypeError) + expect(() => rotateLeft([1, 2, 3], 1.5)).toThrow(TypeError) + }) +})