【挑戦9】線対称と点対称 (paizaランク B 相当) 解答例 – PHP編【戦セット】
【戦セット】 > 【挑戦9】線対称と点対称 (paizaランク B 相当)
※リンク先へ移動する為には「paiza」へのログインが必要です。
解答例
|
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
<?php $input = explode(" ",trim(fgets(STDIN))); $n = $input[0]; $m = $input[1]; $linecouter = 0; $linecouter_r = 0; $pointcounter = 0; $lineflag = false; $pointflag = false; for($i = 0;$i <$n;$i++){ $array[] = str_split(trim(fgets(STDIN))); } for($i =0;$i < $n;$i++){ for($j =0;$j < $m;$j++){ if($array[$i][$j] != $array[$i][$m-1-$j]){ $linecouter++; } } } for($i =0;$i < $n;$i++){ for($j =0;$j < $m;$j++){ if($array[$i][$j] != $array[$n -1 - $i][$j]){ $linecouter_r++; } } } if($linecouter == 0 || $linecouter_r == 0){ $lineflag =true; } for($i =0;$i < $n;$i++){ for($j =0;$j < $m;$j++){ if($array[$i][$j] != $array[$n -1 - $i][$m-1-$j]){ $pointcounter++; } } } if($pointcounter == 0){ $pointflag =true; } if($lineflag == true && $pointflag == true){ echo "line point symmetry"; } elseif($lineflag == true){ echo "line symmetry"; } elseif($pointflag == true){ echo "point symmetry"; } else { echo "none"; } ?> |
攻略方針
この問題は与えられた図形が「線対称である」のか、「点対称である」のか、「線対称であり、点対称である」のか、「どちらでもない」のかの、4つの選択肢から1つの解答を導く問題と言えます。線対称と点対称の定義は次のように与えられています。
定義・線対称:ドット絵の中心を通る垂直、または水平な直線で折りたたんだとき、折り目の両端がぴったり重なること
(斜めの直線を折り目にすることは考えません。)
・点対称:ドット絵の中心で180度回転させたとき、もとの図形とまったく同じ形になること
(斜めの直線を折り目にすることは考えません。)
・点対称:ドット絵の中心で180度回転させたとき、もとの図形とまったく同じ形になること
まあ想像した通りの定義ではありますね(;^ω^) この定義に沿って、図形が線対称か点対称であるかを判定しなくてはなりません。多次元配列でマップの各座標を格納し、線対称、または点対称に対応する二つの座標を、二重ループを用いて総当たりで調べていきます。線対称に関しては、平行の場合と垂直の場合、2パターン調べなければならない点は注意してください。
・線対称の比較
線対称と点対称のフラグを用意し、図の用に総当たり比較していきます。線対称(垂直の場合と平行の場合)を調べている中で「違う要素が1つ以上あった場合はfalse」、「0ならば線対称なのでtrue」とします。点対称の場合も同様に調べていきます。それでは早速コード別にみていきます。
縦列「$n」、横列「$m」、各カウンターとフラグの用意、マップ取得
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$input = explode(" ",trim(fgets(STDIN))); //標準入力で情報取得 $n = $input[0]; //縦座標 $m = $input[1]; //横座標 $linecouter = 0; //線対称用(平行)カウンター $linecouter_r = 0; //線対称用(垂直)カウンター $pointcounter = 0; //点対称用カウンター $lineflag = false; //線対称のフラグ $pointflag = false; //点対称のフラグ for($i = 0;$i <$n;$i++){ $array[] = str_split(trim(fgets(STDIN))); //マップ取得 } |
線対称の判定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
for($i =0;$i < $n;$i++){ for($j =0;$j < $m ;$j++){ if($array[$i][$j] != $array[$i][$m-1-$j]){ //もし、線対称(平行)に位置する値が違う値だったら… $linecouter++; //カウンターを増やす } } } for($i =0;$i < $n;$i++){ for($j =0;$j < $m;$j++){ if($array[$i][$j] != $array[$n -1 - $i][$j]){ //もし、線対称(垂直)に位置する値が違う値だったら… $linecouter_r++; //カウンターを増やす } } } if($linecouter == 0 || $linecouter_r == 0){ //線対称カウンター(垂直、または平行)が0ならば $lineflag =true; //線対称フラグをtrueにする(線対称である) } |
点対称の判定
|
1 2 3 4 5 6 7 8 9 10 11 |
for($i =0;$i < $n;$i++){ for($j =0;$j < $m;$j++){ if($array[$i][$j] != $array[$n -1 - $i][$m-1-$j]){ //もし点対称に位置する値が違う値だった場合… $pointcounter++; //カウンターを一つ上げる } } } if($pointcounter == 0){ //もし点対称カウンターが0だったら… $pointflag =true; //点対称のフラグにtrueを入れる } |
判定結果を出力する
|
1 2 3 4 5 6 7 8 |
if($lineflag == true && $pointflag == true){ //もし線対称フラグと点対称フラグが「true」ならば… echo "line point symmetry"; //「"line point symmetry"」を出力する } elseif($lineflag == true){ //もし線対称フラグだけが「true」ならば echo "line symmetry"; //「"line symmetry"」を出力する } elseif($pointflag == true){ //もし点対称フラグだけが「true」ならば echo "point symmetry"; //「"point symmetry"」を出力する } else { //どちらのフラグも「false」のままならば echo "none";「"none"」を出力する |
終わりに
プログラム初心者である私にとって、苦労した問題だったと思いますが、難しい関数を使用するわけでもなく考え方次第で解けるとてもいい問題だと感じます。paizaの問題集は楽しくプログラミングの練習ができるのがいいです(*’ω’*)
さて、長くなりましたが今日はここまでです。お疲れ様でした(・ω・)ノシ