2 votes

Roman en Int convertit incorrectement dans certains cas

Ma fonction ressemble à ceci :

let romanToInt = romanNumber => {
    if(typeof romanNumber !== 'string') throw new TypeError('L'argument doit être de type String');

    const values = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 };
    let sum = 0;

    romanNumber.split('').map(n => n.toUpperCase()).forEach(n => sum = (sum >= values[n]) ? sum + values[n] : values[n] - sum);

    return sum;
}

console.log(romanToInt("MCMXCVI"));

La plupart des entrées sur lesquelles je teste sont correctes, mais le nombre romain MCMXCVI par exemple, devrait me donner 1996, et pas 2216, ce que j'obtiens.

J'ai trouvé ceci, mais je ne suis pas sûr comment l'implémenter :

Vous devez séparer les unités, dizaines, centaines et milliers en tant qu'éléments séparés. Cela signifie que 99 est XCIX, 90 + 9, mais ne doit jamais être écrit comme IC. De même, 999 ne peut pas être IM et 1999 ne peut pas être MIM.

1voto

Matt Way Points 4301

Selon votre question, vous devez vous occuper des éléments séparément. Une façon simple de le faire est de simplement rendre votre ensemble de valeurs plus grand, et de chercher des correspondances multi-char. C'est possible car il n'y a que quelques combinaisons autorisées avec les chiffres romains. J'ai mis en place un exemple ici

const valeurs = { 
  'I': 1, 
  'V': 5, 
  'X': 10, 
  'L': 50, 
  'C': 100, 
  'D': 500, 
  'M': 1000,
  'CM': 900,
  'CD': 400,
  'XC': 90,
  'XL': 40,
  'IX': 9,
  'IV': 4
};

let somme = 0;

while(nombreRomain.length > 0){
  let morceau = nombreRomain.substring(0,2);
  if(valeurs[morceau]){
    somme += valeurs[morceau];
    nombreRomain = nombreRomain.substring(2);
  }else if(valeurs[morceau[0]]){
    somme += valeurs[morceau[0]];
    nombreRomain = nombreRomain.substring(1);
  }
}

return somme;

0voto

Ruslan Batdalov Points 713

Vous ne devriez pas espérer résoudre le problème avec une simple correspondance, car dans les chiffres romains, le sens d'un chiffre dépend du contexte. Je pense que de nombreux cas peuvent être gérés avec quelque chose comme ça (au lieu de votre ligne avec split et map) :

var digits = romanNumber.split('');
var i = 0;
while (i < digits.length) {
    if (i == digits.length - 1 || values[digits[i]] >= values[digits[i+1]]) {
        sum += values[digits[i]];
        i++;
    }
    else {
        sum += values[digits[i+1]] - values[digits[i]];
        i += 2;
    }
}

Mais je ne suis pas sûr que cela fonctionnera dans tous les cas. Il serait préférable de voir comment il est implémenté dans des bibliothèques prêtes à l'emploi, peut-être pour d'autres langues. Par exemple, voici une implémentation pour Perl : http://search.cpan.org/~chorny/Roman-1.24/lib/Roman.pm

0voto

J S Points 338

Je ne pense pas que vous puissiez implémenter avec un mappage en une seule ligne, car l'opération dépend des comparaisons de caractères l'un à côté de l'autre. Cependant, avec une simple boucle for

var chars = romanNumber.split('');
var sum = values[chars[chars.length - 1]];
for (var i = chars.length - 2; i >= 0; i--) {
    if (values[chars[i + 1]] <= values[chars[i]]) {
        sum += values[chars[i]];
    } else {
        sum -= values[chars[i]];
    }
}

La chose est que quand un chiffre romain est plus petit en valeur que celui à sa droite, vous voulez le soustraire de la somme au lieu d'ajouter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X