【文字列処理メニュー】> 表記の訂正 (paizaランク C 相当) [難易度: 1885 ±19]
※リンク先へ移動するためには[paiza]へのログインが必要です。
paiza 研究所では実験データをわかりやすい形式で保存したいのですが、
機械によって得られる数値には、次のような表記ミスがあることがわかっています。
・ ミス 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
解答例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php $s = trim(fgets(STDIN)); $dot = strpos($s, ".", 0); if($dot != FALSE) { $tail_trim = rtrim($s, 0); if($s[$dot - 1] == 0) { $zero = 0; echo $zero; } $head_trim = ltrim($tail_trim, 0); $len = mb_strlen($head_trim); $flag = 0; for($i = 0; $i < $len; $i++) { $c = $head_trim[$i]; if($c == ".") { if($flag == 0) { $ans[] = $c; $flag++; } } else { $ans[] = $c; } } //print_r($ans); foreach($ans as $value) { echo $value; } } else { echo ltrim($s, 0); } ?> |
解説
まず、受け取った値に小数点(ドット)があるか判定します。
1 2 3 4 5 6 7 8 |
<?php $dot = strpos($s, ".", 0); if($dot != FALSE) { } else { echo ltrim($s, 0); } |
strpos()で小数点(ドット)があるか判定します。strpos()は指定した文字を前方から探して、はじめに現れる位置を取得します。
入力値が00.00001000000の場合は、2になります(先頭が0なので、0,1,2)
strpos(検索対象文字列, 検察文字列 [,検索開始位置])
if()で分岐し、小数点(ドット)がなかったら、
ltrim()で先頭にある0を取り除きます。そのまま表示します。
ltrim(文字列 [,取り除く文字])
$dot != FALSE ← もし、小数点判定で小数点(ドット)があったら、rtrim()で末尾にある0を取り除きます。
rtrim(文字列 [,取り除く文字])
1 2 3 4 5 6 |
$tail_trim = rtrim($s, 0); if($s[$dot - 1] == 0) { $zero = 0; echo $zero; } |
そして、入力値[$dot - 1] == 0 だったとき、つまり、はじめに現れる小数点の一つ前が0だったときは、0を表示します。
末尾の0を取り除いた変数$tail_trimから先頭の0を取り除きます。
1 |
$head_trim = ltrim($tail_trim, 0); |
先頭の0を取り除いた$head_trimの文字数を数えておきます。
1 2 |
$len = mb_strlen($head_trim); $flag = 0; |
for()で$head_trimの文字数だけループを回して、一文字ずつ取り出します。
1 2 3 4 5 6 7 8 9 |
<?php for($i = 0; $i < $len; $i++) { $c = $head_trim[$i]; if($c == ".") { if($flag == 0) { $ans[] = $c; $flag++; } |
もし、取り出した文字がドット(.)だったときは、$flagをカウントします。
$flagが0のときは、配列の$ansに追加します。
文字がドットでないときは、そのまま配列$ansに追加します。
1 2 3 4 |
<?php } else { $ans[] = $c; } |
for()ループを抜けて、foreach()で配列を一つずつ取り出して表示します。
1 2 3 4 |
<?php foreach($ans as $value) { echo $value; } |
感想
どうも、力業っぽさがあるので、もう少しスマートなコードにならないかなと考察中です。(*'ω'*)もっとキレイな解答がありましたらぜひ教えてください。