From 6ec0b96c12bb474fb4779790cf336b68dd44520d Mon Sep 17 00:00:00 2001 From: sarthakgupta1907-cell Date: Fri, 6 Nov 2026 11:02:49 +0530 Subject: [PATCH] feat: add array rotate algorithm --- Data-Structures/Array/Rotate.js | 25 ++++++++++++ Data-Structures/Array/test/Rotate.test.js | 49 +++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 Data-Structures/Array/Rotate.js create mode 100644 Data-Structures/Array/test/Rotate.test.js diff --git a/Data-Structures/Array/Rotate.js b/Data-Structures/Array/Rotate.js new file mode 100644 index 0000000000..f8298f5cdc --- /dev/null +++ b/Data-Structures/Array/Rotate.js @@ -0,0 +1,25 @@ +/** + * @function rotate + * @description Rotates an array to the right by k positions. + * Elements that fall off the end are placed at the beginning. + * @param {Array} arr - The input array + * @param {number} k - Number of positions to rotate right + * @returns {Array} - The rotated array + * @see https://en.wikipedia.org/wiki/Circular_shift + * @example rotate([1, 2, 3, 4, 5], 2) => [4, 5, 1, 2, 3] + * @example rotate([1, 2, 3], 1) => [3, 1, 2] + * @example rotate([1, 2, 3], 3) => [1, 2, 3] + */ +const rotate = (arr, k) => { + if (!Array.isArray(arr)) { + throw new TypeError('First argument must be an array') + } + if (!Number.isInteger(k)) { + throw new TypeError('Second argument must be an integer') + } + if (arr.length === 0) return [] + const steps = ((k % arr.length) + arr.length) % arr.length + return [...arr.slice(arr.length - steps), ...arr.slice(0, arr.length - steps)] +} + +export { rotate } diff --git a/Data-Structures/Array/test/Rotate.test.js b/Data-Structures/Array/test/Rotate.test.js new file mode 100644 index 0000000000..278a6bdf46 --- /dev/null +++ b/Data-Structures/Array/test/Rotate.test.js @@ -0,0 +1,49 @@ +import { rotate } from '../Rotate.js' + +describe('rotate', () => { + test('rotate([1,2,3,4,5], 2) returns [4,5,1,2,3]', () => { + expect(rotate([1, 2, 3, 4, 5], 2)).toEqual([4, 5, 1, 2, 3]) + }) + + test('rotate([1,2,3], 1) returns [3,1,2]', () => { + expect(rotate([1, 2, 3], 1)).toEqual([3, 1, 2]) + }) + + test('rotate([1,2,3], 3) returns [1,2,3]', () => { + expect(rotate([1, 2, 3], 3)).toEqual([1, 2, 3]) + }) + + test('rotate([1,2,3], 0) returns [1,2,3]', () => { + expect(rotate([1, 2, 3], 0)).toEqual([1, 2, 3]) + }) + + test('rotate with k larger than array length', () => { + expect(rotate([1, 2, 3], 4)).toEqual([3, 1, 2]) + }) + + test('rotate with negative k rotates left', () => { + expect(rotate([1, 2, 3, 4, 5], -2)).toEqual([3, 4, 5, 1, 2]) + }) + + test('rotate empty array returns empty array', () => { + expect(rotate([], 3)).toEqual([]) + }) + + test('rotate single element returns same array', () => { + expect(rotate([1], 5)).toEqual([1]) + }) + + test('rotate does not mutate original array', () => { + const arr = [1, 2, 3, 4, 5] + rotate(arr, 2) + expect(arr).toEqual([1, 2, 3, 4, 5]) + }) + + test('throws TypeError for non-array input', () => { + expect(() => rotate('123', 2)).toThrow(TypeError) + }) + + test('throws TypeError for float k', () => { + expect(() => rotate([1, 2, 3], 1.5)).toThrow(TypeError) + }) +})