JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptでバラバラの数字名から数字を復元する方法


問題

次のように、数字の英語名の文字が混ぜ込まれた文字列があるとします。

const str = 'TOWNE';

この文字列をよく観察すると、文字を組み合わせることで「TWO(2)」と「ONE(1)」という2つの数字名が見つけられます。

したがって、この場合に期待される出力は「21」です。

今回の課題は、このような文字列を引数として受け取り、その中に隠れている数字を検出して返すJavaScript関数を記述することです。

解き方のアプローチ

この問題は、以下の手順で解決できます。

  • 0〜9の各数字名(ZERO、ONE、TWOなど)について、考えられるすべての並べ替え(順列)を生成する
  • 各順列を構成する文字が、すべて入力文字列に含まれているかどうかをチェックする
  • マッチした数字名を、その先頭文字が入力文字列内で現れる位置(インデックス)とともに記録する
  • インデックス順に並べ替え、対応する数字を連結して最終的な結果を組み立てる

コード例

以下が実際の実装コードです。

const str = 'TOWNE';
const findNumber = (str = '') => {
   function stringPermutations(str) {
      const res = [];
      if (str.length == 1) return [str];
      if (str.length == 2) return [str, str[1]+str[0]];
      str.split('').forEach((chr, ind, arr) => {
         let sub = [].concat(arr);
         sub.splice(ind, 1);
         stringPermutations(sub.join('')).forEach(function (perm) {
            res.push(chr+perm);
         });
      });
      return res;
   }
   const legend = {
      'ONE': 1, 'TWO': 2, 'THREE': 3, 'FOUR': 4,
      'FIVE': 5, 'SIX': 6, 'SEVEN': 7, 'EIGHT': 8,
      'NINE': 9, 'ZERO': 0
   };
   const keys = Object.keys(legend);
   const res = {};
   const resArr = [];
   let result = '';
   keys.forEach(key => {
      const match = stringPermutations(key).find(el => el.split('').every(char => str.includes(char)));
      if(match){
         const index = str.indexOf(match[0]);
         if(!res.hasOwnProperty(key)){
            res[key] = [index];
         }else if(!res[key].includes(index)){
            res[key].push(index);
         };
      };
   });
   Object.keys(res).forEach(word => {
      resArr.push([word, ...res[word]]);
   });
   resArr.sort((a, b) => a[1] - b[1]);
   resArr.forEach(sub => {
      result = result + String(legend[sub[0]]).repeat(sub.length - 1);
   });
   return +result;
};
console.log(findNumber(str));

出力

コンソールには次のように表示されます。

21

コードのポイント

  • stringPermutations():再帰処理によって文字列の全順列を生成するヘルパー関数です。文字列の長さが1または2の場合は直接結果を返し、それ以外は再帰的に組み合わせを展開していきます。
  • legendオブジェクト:数字名(ONE〜NINE、ZERO)と対応する数値のマッピングを保持しています。
  • マッチング判定every()includes()を組み合わせ、順列の各文字が入力文字列にすべて存在するかを確認しています。
  • 並べ替えと復元:見つかった数字名を出現位置順にソートし、repeat()で同じ数字が複数回現れるケースにも対応しながら、最終的な数値を文字列として組み立てています。
  1. JavaScriptで小数を検証するには?正規表現を使った実装例を解説

    JavaScriptで小数を検証する方法 JavaScriptで、ユーザーが入力した値が正しい小数(小数点を含む数値)かどうかを判定したい場面はよくあります。そんなときに便利なのが正規表現です。本記事では、match()メソッドと正規表現を組み合わせて、入力値が小数かどうかを検証する方法を、具体的なコード例とともにわかりやすく解説します。 使用する正規表現パターン 今回の検証では、以下の正規表現を使用します。 /^[-+]?[0-9]+\.[0-9]+$/ このパターンの各要素の意味は次のとおりです。 ^[-+]?:文字列の先頭に符号(+ または -)が付いていても、付いていなくてもマッチ

  2. JavaScriptで1からnまでのすべての数値で割り切れる最小の数値を求める方法

    問題 数値 n を引数として受け取る JavaScript 関数を作成する必要があります。この関数は、1 から n までのすべての整数で割り切れる最小の正の整数を求めて返します。 実は、この問題は数学における「最小公倍数(LCM)」を求める問題と同じです。1 から n までのすべての数値の最小公倍数こそが、求めるべき答えとなります。 例 n = 10 の場合を考えてみましょう。2520 という数値は、1・2・3・…・10 のすべての数値で余りなく割り切ることができる、最も小さい数値です。 以下のコードを見てみましょう − const num = 11; const smallestDivis