From 5d0391076bcfc90c85d768ee788630e21df3bc24 Mon Sep 17 00:00:00 2001 From: sarthakgupta1907-cell Date: Mon, 2 Nov 2026 18:37:39 +0530 Subject: [PATCH] feat: add number to Roman numeral conversion --- Conversions/NumberToRoman.js | 43 +++++++++++++++++++++++ Conversions/test/NumberToRoman.test.js | 47 ++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 Conversions/NumberToRoman.js create mode 100644 Conversions/test/NumberToRoman.test.js diff --git a/Conversions/NumberToRoman.js b/Conversions/NumberToRoman.js new file mode 100644 index 0000000000..eeec43e85c --- /dev/null +++ b/Conversions/NumberToRoman.js @@ -0,0 +1,43 @@ +/** + * @function numberToRoman + * @description Converts a decimal number to its Roman numeral representation. + * @param {number} num - A positive integer between 1 and 3999 + * @returns {string} - The Roman numeral representation + * @see https://en.wikipedia.org/wiki/Roman_numerals + * @example numberToRoman(3) => "III" + * @example numberToRoman(9) => "IX" + * @example numberToRoman(58) => "LVIII" + * @example numberToRoman(1994) => "MCMXCIV" + */ +const numberToRoman = (num) => { + if (!Number.isInteger(num) || num < 1 || num > 3999) { + throw new TypeError('Input must be an integer between 1 and 3999') + } + const values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1] + const symbols = [ + 'M', + 'CM', + 'D', + 'CD', + 'C', + 'XC', + 'L', + 'XL', + 'X', + 'IX', + 'V', + 'IV', + 'I' + ] + let result = '' + let remaining = num + for (let i = 0; i < values.length; i++) { + while (remaining >= values[i]) { + result += symbols[i] + remaining -= values[i] + } + } + return result +} + +export { numberToRoman } diff --git a/Conversions/test/NumberToRoman.test.js b/Conversions/test/NumberToRoman.test.js new file mode 100644 index 0000000000..e986449240 --- /dev/null +++ b/Conversions/test/NumberToRoman.test.js @@ -0,0 +1,47 @@ +import { numberToRoman } from '../NumberToRoman.js' + +describe('numberToRoman', () => { + test("numberToRoman(1) returns 'I'", () => { + expect(numberToRoman(1)).toBe('I') + }) + + test("numberToRoman(3) returns 'III'", () => { + expect(numberToRoman(3)).toBe('III') + }) + + test("numberToRoman(4) returns 'IV'", () => { + expect(numberToRoman(4)).toBe('IV') + }) + + test("numberToRoman(9) returns 'IX'", () => { + expect(numberToRoman(9)).toBe('IX') + }) + + test("numberToRoman(40) returns 'XL'", () => { + expect(numberToRoman(40)).toBe('XL') + }) + + test("numberToRoman(58) returns 'LVIII'", () => { + expect(numberToRoman(58)).toBe('LVIII') + }) + + test("numberToRoman(1994) returns 'MCMXCIV'", () => { + expect(numberToRoman(1994)).toBe('MCMXCIV') + }) + + test("numberToRoman(3999) returns 'MMMCMXCIX'", () => { + expect(numberToRoman(3999)).toBe('MMMCMXCIX') + }) + + test('throws TypeError for 0', () => { + expect(() => numberToRoman(0)).toThrow(TypeError) + }) + + test('throws TypeError for 4000', () => { + expect(() => numberToRoman(4000)).toThrow(TypeError) + }) + + test('throws TypeError for float', () => { + expect(() => numberToRoman(1.5)).toThrow(TypeError) + }) +})