JavaScriptで「美しい数値文字列」を判定する方法を解説
数値のみで構成された文字列 str が「美しい文字列(Beautiful String)」であるとは、その文字列を2つ以上の正の整数からなるシーケンス arr に分割でき、かつ次の条件をすべて満たすことを指します。
連続する整数であること: 任意のインデックス i に対して arr[i] − arr[i − 1] = 1 が成り立つこと。つまり、シーケンス内の各要素は必ず直前の要素よりちょうど1大きくなければなりません。
先頭に0を含まないこと: シーケンスのどの要素にも先行ゼロ(leading zero)があってはなりません。たとえば、'50607' を [5, 06, 07] と分割することはできますが、「06」「07」に先頭ゼロが付いているため、これは美しい文字列とは認められません。
要素の並べ替え禁止: 一度分割した要素を並べ替えることはできません。元の文字列に現れる順序をそのまま保つ必要があります。
具体例
入力として次の文字列が与えられたとしましょう。
const str = '91011';
このとき期待される出力は次のとおりです。
const output = true;
理由はシンプルです。この文字列は [9, 10, 11] という連続した整数のシーケンスにきれいに分割できるからです。9 の次に 10、さらにその次に 11 と、各要素が直前の要素より1ずつ増えており、上記の条件をすべて満たしています。
実装コード
この問題を解くためのJavaScriptコードは以下のとおりです。
const str = '91011';
const isBeautiful = (str) => {
let i = 1;
let count = 0;
const { length } = str;
while (i <= length / 2) {
let check = true;
let j = i;
let left = BigInt(str.substring(0, j));
let nextRange = (left + 1n).toString().length;
while (j + nextRange <= length) {
let right = BigInt(str.substring(j, j + nextRange));
if (left === right - 1n) {
left = right;
j += nextRange;
nextRange = (left + 1n).toString().length;
count = j;
} else {
check = false;
break;
}
};
if (check === true && count === length) {
return true;
}
i++;
};
return false;
};
console.log(isBeautiful(str));
アルゴリズムの解説
このコードで重要なポイントは、BigInt を使用している点です。桁数の多い数値文字列を扱う場合、通常の Number 型では安全な整数範囲を超えて精度が低下する恐れがあります。BigInt を使えば、任意の長さの整数を誤差なく正確に比較できます。
処理の流れは次のとおりです。まず、先頭部分の桁数(変数 i)を 1 から文字列長の半分まで順番に試します。先頭部分を BigInt として取り出し、「次に来るべき数値(left + 1)」の桁数を計算します。その桁数ぶんだけ続く部分文字列を切り出して比較し、期待どおりの連続値であれば読み進めます。途中で不整合が見つかった場合は打ち切り、次の先頭桁数での検証へ移ります。そして、文字列の末尾まで余りなく消費できた場合にのみ true を返します。
出力結果
コンソールには次のように表示されます。
true
-
マジックストリング(魔法の文字列)問題をJavaScriptで解く方法
マジックストリングの問題概要マジックストリング(魔法の文字列)とは、「1」と「2」だけから構成され、次の性質を持つ特別な文字列です。この文字列が「マジック(魔法)」と呼ばれるのは、連続する「1」や「2」のかたまり(グループ)ごとの出現回数をつなぎ合わせると、元の文字列そのものが再現されるからです。文字列 str の最初の部分は次のようになっています。str = 1221121221221121122……str 内の連続した「1」「2」をそれぞれグループに分けると、次のようになります。1 22 11 2 1 22 1 22 11 2 11 22 ……さらに、各グループにおける「1」または「2」の
-
JavaScriptで数値文字列を0と1のビット列にエンコードする方法
問題 10進数を表す文字列を受け取り、決められたルールに従って「0」と「1」だけで構成される文字列へエンコードするJavaScript関数を実装します。 エンコードのルール 入力文字列の各桁の数字 d に対して、次の手順で符号語を作ります。 d を2進数で表したときのビット数を k とする 「0」を k−1 個並べ、その後ろに「1」を1つ付けた文字列をプレフィックスとする 数字 d 自身を2進数の文字列として表す(最右ビットが最下位ビット) プレフィックスと2進表現を連結したものが d の符号語になる 最後に、すべての桁について得られた符号語を順番に連結したものが、全体のエンコード結果と