mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-22 07:46:15 -04:00
feat(tool): roman-arabic numbers converter
This commit is contained in:
parent
3ae61147a9
commit
655019cf23
5 changed files with 154 additions and 0 deletions
|
@ -4,6 +4,7 @@ import type { ToolCategory } from './Tool';
|
||||||
import { tool as tokenGenerator } from './token-generator';
|
import { tool as tokenGenerator } from './token-generator';
|
||||||
import { tool as hashText } from './hash-text';
|
import { tool as hashText } from './hash-text';
|
||||||
import { tool as uuidGenerator } from './uuid-generator';
|
import { tool as uuidGenerator } from './uuid-generator';
|
||||||
|
import { tool as romanNumeralConverter } from './roman-numeral-converter';
|
||||||
|
|
||||||
export const toolsByCategory: ToolCategory[] = [
|
export const toolsByCategory: ToolCategory[] = [
|
||||||
{
|
{
|
||||||
|
@ -11,6 +12,11 @@ export const toolsByCategory: ToolCategory[] = [
|
||||||
icon: LockOpen,
|
icon: LockOpen,
|
||||||
components: [tokenGenerator, hashText, uuidGenerator],
|
components: [tokenGenerator, hashText, uuidGenerator],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Converter',
|
||||||
|
icon: LockOpen,
|
||||||
|
components: [romanNumeralConverter],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const tools = toolsByCategory.flatMap(({ components }) => components);
|
export const tools = toolsByCategory.flatMap(({ components }) => components);
|
||||||
|
|
11
src/tools/roman-numeral-converter/index.ts
Normal file
11
src/tools/roman-numeral-converter/index.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { LetterX } from '@vicons/tabler';
|
||||||
|
import type { ITool } from '../Tool';
|
||||||
|
|
||||||
|
export const tool: ITool = {
|
||||||
|
name: 'Roman numeral converter',
|
||||||
|
path: '/roman-numeral-converter',
|
||||||
|
description: 'Convert Roman numerals to numbers and convert numbers to Roman numerals.',
|
||||||
|
keywords: ['roman', 'arabic', 'converter', 'X', 'I', 'V', 'L', 'C', 'D', 'M'],
|
||||||
|
component: () => import('./roman-numeral-converter.vue'),
|
||||||
|
icon: LetterX,
|
||||||
|
};
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { expect, describe, it } from 'vitest';
|
||||||
|
import { arabicToRoman } from './roman-numeral-converter.service';
|
||||||
|
|
||||||
|
describe('roman-numeral-converter', () => {
|
||||||
|
describe('arabicToRoman', () => {
|
||||||
|
it('should convert numbers lower than 1 to empty string', () => {
|
||||||
|
expect(arabicToRoman(-100)).toEqual('');
|
||||||
|
expect(arabicToRoman(-42)).toEqual('');
|
||||||
|
expect(arabicToRoman(-26)).toEqual('');
|
||||||
|
expect(arabicToRoman(-10)).toEqual('');
|
||||||
|
expect(arabicToRoman(0)).toEqual('');
|
||||||
|
expect(arabicToRoman(0.5)).toEqual('');
|
||||||
|
expect(arabicToRoman(0.9)).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert floating points number to the lower integer in roman version', () => {
|
||||||
|
expect(arabicToRoman(-100)).toEqual('');
|
||||||
|
expect(arabicToRoman(-42)).toEqual('');
|
||||||
|
expect(arabicToRoman(-26)).toEqual('');
|
||||||
|
expect(arabicToRoman(-10)).toEqual('');
|
||||||
|
expect(arabicToRoman(0)).toEqual('');
|
||||||
|
expect(arabicToRoman(0.5)).toEqual('');
|
||||||
|
expect(arabicToRoman(0.9)).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert positive integers to roman numbers', () => {
|
||||||
|
expect(arabicToRoman(1)).toEqual('I');
|
||||||
|
expect(arabicToRoman(2)).toEqual('II');
|
||||||
|
expect(arabicToRoman(3)).toEqual('III');
|
||||||
|
expect(arabicToRoman(4)).toEqual('IV');
|
||||||
|
expect(arabicToRoman(5)).toEqual('V');
|
||||||
|
expect(arabicToRoman(6)).toEqual('VI');
|
||||||
|
expect(arabicToRoman(7)).toEqual('VII');
|
||||||
|
expect(arabicToRoman(8)).toEqual('VIII');
|
||||||
|
expect(arabicToRoman(9)).toEqual('IX');
|
||||||
|
expect(arabicToRoman(10)).toEqual('X');
|
||||||
|
expect(arabicToRoman(11)).toEqual('XI');
|
||||||
|
expect(arabicToRoman(12)).toEqual('XII');
|
||||||
|
expect(arabicToRoman(13)).toEqual('XIII');
|
||||||
|
expect(arabicToRoman(14)).toEqual('XIV');
|
||||||
|
expect(arabicToRoman(15)).toEqual('XV');
|
||||||
|
expect(arabicToRoman(16)).toEqual('XVI');
|
||||||
|
expect(arabicToRoman(17)).toEqual('XVII');
|
||||||
|
expect(arabicToRoman(18)).toEqual('XVIII');
|
||||||
|
expect(arabicToRoman(19)).toEqual('XIX');
|
||||||
|
expect(arabicToRoman(20)).toEqual('XX');
|
||||||
|
expect(arabicToRoman(21)).toEqual('XXI');
|
||||||
|
expect(arabicToRoman(24)).toEqual('XXIV');
|
||||||
|
expect(arabicToRoman(28)).toEqual('XXVIII');
|
||||||
|
expect(arabicToRoman(29)).toEqual('XXIX');
|
||||||
|
expect(arabicToRoman(30)).toEqual('XXX');
|
||||||
|
expect(arabicToRoman(40)).toEqual('XL');
|
||||||
|
expect(arabicToRoman(50)).toEqual('L');
|
||||||
|
expect(arabicToRoman(60)).toEqual('LX');
|
||||||
|
expect(arabicToRoman(70)).toEqual('LXX');
|
||||||
|
expect(arabicToRoman(80)).toEqual('LXXX');
|
||||||
|
expect(arabicToRoman(90)).toEqual('XC');
|
||||||
|
expect(arabicToRoman(100)).toEqual('C');
|
||||||
|
expect(arabicToRoman(200)).toEqual('CC');
|
||||||
|
expect(arabicToRoman(300)).toEqual('CCC');
|
||||||
|
expect(arabicToRoman(400)).toEqual('CD');
|
||||||
|
expect(arabicToRoman(500)).toEqual('D');
|
||||||
|
expect(arabicToRoman(600)).toEqual('DC');
|
||||||
|
expect(arabicToRoman(700)).toEqual('DCC');
|
||||||
|
expect(arabicToRoman(800)).toEqual('DCCC');
|
||||||
|
expect(arabicToRoman(900)).toEqual('CM');
|
||||||
|
expect(arabicToRoman(999)).toEqual('CMXCIX');
|
||||||
|
expect(arabicToRoman(1000)).toEqual('M');
|
||||||
|
expect(arabicToRoman(2000)).toEqual('MM');
|
||||||
|
expect(arabicToRoman(9000)).toEqual('MMMMMMMMM');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
export function arabicToRoman(num: number) {
|
||||||
|
if (num < 1) return '';
|
||||||
|
|
||||||
|
const lookup: { [key: string]: number } = { M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90, L: 50, XL: 40, X: 10, IX: 9, V: 5, IV: 4, I: 1 };
|
||||||
|
let roman = '';
|
||||||
|
for (const i in lookup) {
|
||||||
|
while (num >= lookup[i]) {
|
||||||
|
roman += i;
|
||||||
|
num -= lookup[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function romanToArabic(s: string) {
|
||||||
|
const map: { [key: string]: number } = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
|
||||||
|
return [...s].reduce((r, c, i, s) => (map[s[i + 1]] > map[c] ? r - map[c] : r + map[c]), 0);
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<n-card title="Arabic to roman">
|
||||||
|
<n-space align="center" justify="space-between">
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="inputNumeral"
|
||||||
|
:min="1"
|
||||||
|
style="width: 200px;"
|
||||||
|
:show-button="false"
|
||||||
|
/>
|
||||||
|
<div class="result">{{ outputRoman }}</div>
|
||||||
|
<n-button @click="copyRoman" secondary autofocus>Copy</n-button>
|
||||||
|
</n-space>
|
||||||
|
</n-card>
|
||||||
|
<br />
|
||||||
|
<n-card title="Roman to arabic">
|
||||||
|
<n-space align="center" justify="space-between">
|
||||||
|
<n-input v-model:value="inputRoman" style="width: 200px;" />
|
||||||
|
<div class="result">{{ outputNumeral }}</div>
|
||||||
|
<n-button @click="copyArabic" secondary autofocus>Copy</n-button>
|
||||||
|
</n-space>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useCopy } from '@/composable/copy';
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { arabicToRoman, romanToArabic } from './roman-numeral-converter.service'
|
||||||
|
|
||||||
|
const inputNumeral = ref(42)
|
||||||
|
const outputRoman = computed(() => arabicToRoman(inputNumeral.value))
|
||||||
|
|
||||||
|
const inputRoman = ref('IVX')
|
||||||
|
const outputNumeral = computed(() => romanToArabic(inputRoman.value))
|
||||||
|
|
||||||
|
const { copy: copyRoman } = useCopy({ source: outputRoman, text: 'Roman number copied to the clipboard' })
|
||||||
|
const { copy: copyArabic } = useCopy({ source: outputNumeral, text: 'Arabic number copied to the clipboard' })
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.result {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Add table
Add a link
Reference in a new issue