why is my program giving back undefined values for my roman numeral convert?

36 views Asked by At

I am trying to create a roman numeral converter using javascript, css, and html, but whenever I try to get the value of the roman numeral I need it returns undefined and I am unsure as to why.

const output = document.getElementById("output");
const number = document.getElementById('number');
const convertBtn = document.getElementById('convert-btn');
/*declared the variables */

/*declared the input value */
const lettersList = [
    {
        0:['', 'I','II','III','IV','V', 'VI', 'VII', 'VIII', 'IX']
    },{
        1:['X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC']
    },{
        2:['C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM']
    },{
        3:['M', 'MM', 'MMM']
    }
]
//0 1 2 3
//3 9 9 9
//MMM CM XC IX

const makeNum = (input) =>{//making the roman numeral, input is the argument
    output.removeAttribute("hidden")//removes hidden
    const inputList = input.value.split('').reverse()//this splits the list values and then reverses them to make them easier to work with

    if (input.value > 3999){//if a value is greater then 3999 it will send an error
        output.innerHTML = `
        <p>Please enter a number less than or equal to 3999</p>
        `
    } else if (input.value < 1){//if a value is less then one it will send an error
        output.innerHTML = `
        <p>Please enter a number greater than or equal to 1 </p>
        `
    } else {//if it is between 1-3999 then it will attempt to convert the numbers to roman numerals
        for (let i = 0; i < inputList.length; i++){//for the length of the list it will repeat
            console.log(inputList[i])//it will print where in the list we are in the console
            let deletedItem = inputList.splice(i, 1,);//this removes the current area in the list we are and stores it to attempt to convert it
            inputList.splice(i, 0, `${lettersList[i][deletedItem[0]]}`)//this might be where i am getting errors as i use splice again to get the value of lettersList, depending on the place it will go to that list, then in that list, depending on the value of the number it SHOULD give me back the value of that roman numeral.
            console.log(lettersList[i], deletedItem[0], lettersList[i][deletedItem[0]])// this is just to print it into the console to see whats wrong
        }
    }
    output.innerHTML = ``//this clears the output value
    output.innerHTML = `
    <p>${inputList}</p>
    `//this adds the output into the DOM
};

convertBtn.addEventListener("click", ()=>{
    makeNum(number);//this is just the button
})

I was expecting it to return the value of the lettersList for the code. I was gonna reverse it back and then join it together so it would be the correct roman numeral. it was supposed to give me a list of roman numerals backwards (i.e. instead of 123 being CXXIII it would be IIIXXC) but it just gives me back 'undefined'

1

There are 1 answers

0
trincot On

There are a few issues:

  • lettersList[i] is not an array of strings, but an array of objects, each with an array property. That won't work: make lettersList to be an array of arrays of strings.

  • Comparing input.value directly with 3999 can give unintended results. You should first convert input.value to a number before comparing it with another number. Also, you'll want to verify that the user hasn't entered things like "3.85" or "1e2", ... the input should consist of digits only

  • lettersList has the right intension with including "" for the value 0, but it should have similar entries for the other arrays. For instance, think of input 101. Now the middle digit is zero, and with that digit you'll find "X", but there should be no "X" in the output. So you need an empty string for that as well.

  • The output ${inputList} will convert your array to a comma separated list, which is not really want you want in the output.

  • Splicing the inputList to extract and then insert again a translation will work, but overcomplicates it. Just create a different variable for collecting the output. And make it a string so that it solves the previous point as well, and you can concatenate it in the right order (not reversed).

Here is the adaptation of your code with those remarks taken into account:

const output = document.getElementById("output");
const number = document.getElementById('number');
const convertBtn = document.getElementById('convert-btn');

const lettersList = [
    ['', 'I','II','III','IV','V', 'VI', 'VII', 'VIII', 'IX'],
    ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
    ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'],
    ['', 'M', 'MM', 'MMM']
];

const makeNum = (input) => {
    output.removeAttribute("hidden");
    let result = ""; // Collect the result in a different variable
    const inputList = input.value.split("").reverse();

    const n = +input.value; // Convert to number before comparing
    // Make sure no decimal point or scientific notation: only digits are allowed
    if (!(n > 0 && n < 4000 && /^\d+$/.test(input.value))) {
        output.textContent = "Please enter an integer number between 1 and 3999";
    } else {
        for (let i = 0; i < inputList.length; i++) {
            result = `${lettersList[i][inputList[i]]}${result}`;
        }
        output.textContent = result;
    }
};

convertBtn.addEventListener("click", () => makeNum(number));
Integer: <input id="number"><button id="convert-btn">Convert</button><br>
Output: <span id="output"></span><br>