Map for each and moral dilemma? (roman numeral challenge)

For almost a week I’ve been trying to get past the Roman Numeral challenge, so out of desperation I scrolled down through the hint section and eventually looked at the basic answer.

When I read the answer I could kick myself in the head, it seemed clean and straightforward. Problem is although I understand the answer and could easily recreate it without help, I don’t just want to copy it over and while thinking of another solution to the challenge, the basic answer has become a “once you see it, you can’t unsee it” situation.

I’m still hesitant to use the hint solution, so I thought of improving the code by replacing the for loop with a map function and combine the arrays to a single array of objects, but with little succes.

Here’s what I got so far:

function convertToRoman(num) {

  let convertIndex = 
    [
      {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}
      ]
     
  
    //While num => 0, Map for each item.value <= num, return item.key; substract item.value from num and convert the returned keynames to a string
    let romanized = convertIndex.map((item) => {while (num => 0) {if (item <= num) {num -= item.value; return item.key} } }).toString()  //<====== WARNING: Results in a infinite loop!

return romanized;

}

convertToRoman(16);

Anyone has any idea if what I’m trying to do is even possible or if this would solve the plagiarism dilemma?
Any insight is welcome!

You seem to be getting a little tangled in what you’re trying to do here.

Firstly - don’t beat yourself up about the plagiarism thing. Sometimes a quick peak, especially after a week of struggle, is just what you need to break out of the rut. It’s fine; you’re still going to be a good programmer.

On with the gnarly stuff…

Let’s break that one liner map function up with some whitespace a bit so we can reason about it better:

let romanized = convertIndex.map((item) => {
    while (num => 0) {
        if (item <= num) {
            num -= item.value; 
            return item.key
        } 
    }
}).toString()  //<====== WARNING: Results in a infinite loop!

return romanized;

The first thing to ask is: is Array.map() the right tool for the job?

The map() method creates a new array with the results of calling a provided function on every element in the calling array. [source]

What you are running the map over here is your array of objects defining the relationship between roman numerals and integers. This array of key: value pairs can be thought of a bit like a dictionary where we look up the meaning of the characters, or translate them. Is it useful to change that dictionary and return a new array based on that? Probably not. So map might not be the best tool here.

Next up, small detail: don’t confuse the => (‘fat arrow’ ES6 function shorthand) with >= (‘angry eyes’ more than or equal to) symbols.

A quick test in node:

while (num => 0) {
  console.log('something');
}

The above prints a never-ending stream of somethings to the console. So there’s your infinite loop, at least.

Now let’s look closely at this line: if (item <= num)

Our map function is iterating through everything in the array of numeral: integers pairs above. The first time, that if statement looks more like this: if ({M: 1000} <= num)

Let’s assume num === 1000, and compare the two values in the console:

13%20pm

So the code in the if block never gets executed.

So, where from here?

In your little pseudocode snippet in the commented out part, I notice you using some javascript language. The first time you reason about this, try to avoid all syntax all together. Explain it in plain English. If you can get the algorithm right in English, then the Javascript is easier - it might not be the fastest implementation, but it’ll pass the tests.

Good luck, and happy coding :slight_smile: