【ソート】STEP: 3 辞書式ソート (paizaランク D 相当) 解答例 – PHP編【Cランクレベルアップメニュー】
【Cランクレベルアップメニュー】 > 【ソート】STEP: 3 辞書式ソート (paizaランク D 相当)
※リンク先へ移動する為には「paiza」へのログインが必要です。
この「Cランクレベルアップメニュー」の中で躓く問題があるとすれば、恐らくこの問題だと思います。半角スペース区切りの数値を降順に並べ直す問題なのです。他の言語はどうなのか分かりませんが、PHPは「sort」、「rsort」で並べ替える要素が文字列の場合、「最初の一文字だけを参照して並べる」という特徴があるため、多次元配列で保存し直す必要があります。このことを理解していないと解けない問題なので、Dランク問題とありますが、私はこの謎が解けず、結果的に「Bランクレベルアップメニュー」が先に全問クリアできてしまったという(;^ω^)
解答例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php $n = trim(fgets(STDIN)); $array = array(); for ($i = 0; $i < $n; $i++) { $test = explode(" ", trim(fgets(STDIN))); $a = $test[0]; $b = $test[1]; $array[$i][0] = $a; $array[$i][1] = $b; } rsort($array); for ($i = 0; $i < $n; $i++) { echo $array[$i][0] . ' ' . $array[$i][1] . "\n"; } ?> |
解答方針
一番目の数字がリンゴの数、二番目の数がバナナの数を表し、リンゴの数が多い順番に並び替える問題です。ただし、リンゴの数が同じ場合、バナナの数が多い順番に並んでいることが条件として与えられています。
この問題はPHPで文字列数値を並べ替える際、PHPの挙動を理解していないと解けません。重要なことは今回扱う要素が「文字列数値」だということです。例を見てみましょう。
|
1 2 3 4 5 6 7 8 9 10 |
<?php $array = ["3 1", "2 1", "2 2", "10 2", "10 10" ]; rsort($array); print_r($array); ?> |
こんな配列があったとして「rsort()」で降順に並べてみます。実行結果は次の通りです。
[0] => 3 1
[1] => 2 2
[2] => 2 1
[3] => 10 2
[4] => 10 10
)
降順に並べ直したつもりが…リンゴの数「10」が上位のほうに並べ変っていませんね。それに「2 1」と「2 2」はちゃんと降順に並んでいるのに「10 2」と「10 10」は並べ変わっていませんね…。
これはどうしてこのような結果になってしまったのでしょうか?
実はPHPでは「文字数値を並べ替える時、頭文字1文字だけを数値化し並べ替える」という特徴があります。この場合、リンゴの数「10」が、頭文字一文字だけの「1」として扱われ、結果的に「2」より下に並べられているのです。
「10 2」と「10 10」の並べ替えも同様で、この場合「1 2」、「1 1」として比べられ、バナナの数を正常に並べ替えることができないのです。
このことを頭に入れ、「sort()」でも試してみましょう。
|
1 2 3 4 5 6 7 8 9 10 |
<?php $array = ["3 1", "2 1", "2 2", "10 2", "10 10" ]; sort($array); print_r($array); ?> |
実行結果は次の通りです。
[0] => 10 10
[1] => 10 2
[2] => 2 1
[3] => 2 2
[4] => 3 1
)
リンゴの数「10」が「1」として認識されるせいで「10」が一番最初に並んでしまっていますね。「10 10」と「10 2」も、「1 1」と「1 2」に認識されることでこのような結果になってしまいます。
なんとなくこのPHPの挙動が理解して頂けたのではないかと思います。この問題を解決する為には、スペース区切りで各数値を分けて配列に保存することです。
それでは各コードについて説明していきます。
各情報の取得
|
1 2 3 4 5 6 7 8 9 10 |
$n = trim(fgets(STDIN)); //標準入力からデータの個数「N」取得 $array = array(); //空配列の作成 for ($i = 0; $i < $n; $i++) { $test = explode(" ", trim(fgets(STDIN))); //「$test」にデータをスペース区切りで分割し配列として保存 $a = $test[0]; //リンゴの数を入れる $b = $test[1]; //バナナの数を入れる $array[$i][0] = $a; //「$array」の[$i][0]にリンゴの数を入れる $array[$i][1] = $b; //「$array」の[$i][1]にバナナの数を入れる } |
要素を並べ替えて出力
|
1 2 3 4 5 |
rsort($array); for ($i = 0; $i < $n; $i++) { echo $array[$i][0] . ' ' . $array[$i][1] . "\n"; } |