Paizaの「実験データの修正」という問題、甘く見てました。見た目はただの文字列操作。でも実際は、「0
」と「.
」のカオス。
🔍 問題の概要
実験データとして与えられる文字列には、次のようなミスがある。
・ ミス 1
先頭に必要のない 0 がいくつかついてしまう
例:本来 1 である数値が 0001 と表記されてしまう
例:本来 0.001 である数値が 00.001 と表記されてしまう
・ ミス 2
小数である数値の末尾に必要のない 0 がいくつかついてしまう
例: 本来 0.1 である数値が 0.10 と表記されてしまう
・ ミス 3
小数である数値に小数点が複数個ついてしまう
ただし、 1 つめの小数点の位置が正しい小数点の位置であるもの
例: 本来 0.123 である数値が 0.1.2.3 と表記されてしまう
表記が正しくない可能性のある数値を表す文字列 S が与えられるので、その数値を正しい表記にしてください
※S を数値として扱うと上手く処理が行えないので気をつけてください
//入力例:
00.00001000000
//出力例:
0.00001
🔧 修正すべき3つのミスと処理手順
◆ ミス①:先頭に不要な0がついてしまう
例:
"0001" → "1"
"00.001" → "0.001"
対応手順:
- 小数点の位置を見つけて分割
let [intPart, fracPart] = s.split(".");
- 整数部の先頭の0を削除
intPart = intPart.replace(/^0+/, '');
// 空文字にならないように補正
if (intPart === '') intPart = '0';
※"0001"のような整数のみの場合は別途解説↓
◆ ミス②:小数部の末尾に不要な0がついてしまう
例:
"0.10" → "0.1"
"0.1000" → "0.1"
対応手順:
- 小数点がある場合のみ処理
- 小数部の末尾の0を削除
fracPart = fracPart.replace(/0+$/, '');
◆ ミス③:小数点が複数ついてしまう
例:
"0.1.2.3" → "0.123"
"1.0.0" → "1.00"
対応手順:
- split('.') で分割
const parts = s.split(".");
const intPart = parts[0];
const fracPart = parts.slice(1).join("");
🧠 補足事項・注意点
数値として処理すると “00.001” → 0.001 → 1e-3 になるなど、意図しない変換が起きる可能性があるので、文字列での処理が必須。
小数点がない場合(整数のみ)にも対応できるよう、includes(".")
で分岐しておくと安全。
✅ これで全ミスの処理方針がそろいました!
⭐完成コード:
const rl = require('readline').createInterface({input:process.stdin});
rl.once('line',(input) => {
//整数のみか判断
if (!input.includes('.')){
console.log(String(Number(input)));
rl.close(); // 処理終了!
return; // ここで関数を終了させる
}
//ミス③:小数点が複数ついてしまうの処理 (+ 整数部分と小数部分を分ける)
const part = input.split('.');
let intPart = part[0];
let fracPart = part.slice(1).join('');
//ミス①:先頭に不要な0がついてしまうの処理
intPart = intPart.replace(/^0+/, ''); //先頭部の"0"を削除
if (intPart === '') intPart = "0"; // 空文字にならないように補正
//ミス②:小数部の末尾に不要な0がついてしまうの処理
fracPart = fracPart.replace(/0+$/, ''); //末尾の"0"を削除
// 小数部が空になった場合、小数点を取り除く
const result = fracPart ? `${intPart}.${fracPart}` : intPart;
console.log(result); //小数部と整数部を結合して出力 訂正完了!
rl.close();
});
❌ NGコード例:return 書かずに二重出力💥
if (!input.includes('.')) {
console.log(String(Number(input)));
rl.close(); // ←これだけじゃプログラムは終了しない
}
// ↓ここも実行されちゃう!
console.log("もう1個出力されちゃった!");
🔥 このコード、input
が小数点を含まないときに「2回出力」されてしまう。
理由:
-
rl.close()
は 標準入力の受付を終了するだけ。実行中のプログラムそのものは止まらない。 -
return
を書かないと、そのあとのコード(小数用の処理)も実行されてしまう。
✅ どうして return が必要だったか?
if (!input.includes('.')) {
console.log(String(Number(input)));
rl.close();
return; // ←これで「残りの処理をスキップ」して終了!
}
if
ブロック内で return
を使うことで、条件が満たされた時点でそれ以降の処理が実行されないようにできる。
これにより、小数用の処理に入ってしまうミスを防ぎ、プログラムをスッキリ終了させることができる🚀
✨ 結果的にこうなる:
-
rl.close()
→ 標準入力を終了 -
return
→ その後のコードの実行を止めて、プログラム(関数)を終了
💡 気づきメモ&学び
- 表示が科学記法 (指数表記)になって意図通りにいかないことがある
-
split('.')
やreplace()
で文字列処理の柔軟さを学べた -
rl.close()
だけではプログラム終了しない!→return
必須! - 整数と小数で処理を分けることでコードの見通しが良くなった