このページについて
このページは、paiza ラーニング内に開設されているコンテンツ「レベルアップ問題集」で取り扱われているプログラミング課題について、独自の見解を述べたものです。
見解については、paizaラーニングの規約に基づき、許可されている範囲でのみ公開していますが、その内容については paiza とは一切関係なく、また paiza の立場を反映したものではありませんのでご注意ください。
挑戦する課題
レベルアップ問題集の戦セットから「【挑戦9】線対称と点対称 (paizaランク B 相当)」を取り上げます。
以下は、問題公開 Web ページからの引用です。
問題
この問題は、弊社営業社員が競技プログラミングに挑戦したものです。
ある図形に対し、線対称、点対称は次のように定義されます。
- 線対称:ある直線を折り目にして折りたたんだとき、折り目の両側がぴったり重なること
- 点対称:ある一点で180度回転させたとき、もとの図形とまったく同じ形になること
この問題では、ドット絵に対する線対称、点対称を以下のように定義します。
- 線対称:ドット絵の中心を通る垂直、または水平な直線で折りたたんだとき、折り目の両端がぴったり重なること(斜めの直線を折り目にすることは考えません。)
- 点対称:ドット絵の中心で180度回転させたとき、もとの図形とまったく同じ形になること
n×mのドット絵が入力されるので、そのドット絵が線対称であるか、点対称であるか、その両方か、そのどちらかでもないかを判定するプログラムを作成してください。
入力される値
入力は以下のフォーマットで与えられます
1 2 3 4 5 |
n m d_1 d_2 ... d_n |
- 入力される文字列数n
- d_1, d_2, …, d_n は # または . で構成される長さmの文字列
- 入力はn + 1行となり、末尾に改行を一つ含みます。
期待する出力
ドット絵が
- 線対称であるとき、line symmetry
- 点対称であるとき、point symmetry
- 線対称かつ点対称であるとき、line point symmetry
- 線対称でも点対称でもないとき、none
を出力してください。
考え方
- 垂直線(画像中央を通る縦の線)での線対称の場合
- 全ての行において、ある行とその行のを逆順にしたものが一致すれば線対称となる。
- つまり、 #.#.# と、その逆順である #.#.# は一致するので線対称
- 一方、 ###.. と、その逆順である ..### は一致しないため線対称ではない
- 水平線(画像中央を通る横の線)での線対称の場合
- 画像の行数を l としたとき、全ての行において i 番目の行と l - i 番目の行が一致すれば線対称
- 点対称の場合
- 今回の場合は、180度回転させた場合のみ考慮すれば良い。
- 画像の行数を l としたとき、全ての行において i 番目の行と l - i 番目の行の逆順が一致すれば点対称
- i 行目が ##... で、 l - i 行目が ...## の場合、 l - i行目の逆順は #... となるため点対称。
- i 行目が #.... で、 l - i 行目が ...## の場合、 l - i行目の逆順は ##... となるため一致せず、点対称とは言えない。
解答例
ブラッシュアップ中。
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 |
// 最初の行は読み飛ばす _ = readLine()! // ドット絵の情報を Array<String> に入れる let sa = Array(AnyIterator { readLine() }) // 行数 var l = sa.count // 点対称 (point symmetry) フラグ var ps = true // 垂直線で線対称 (line symmetry) フラグ var ls = true // 水平線で戦隊種 var lsh = true // 図形の水平中央まで走査すれば良い for i in 0..<(l / 2) { // 計算中の先頭行 (first line = fl) と最終行 (last line = ll) let fl = sa[i] let ll = sa[l - i - 1] // 点対称 // fl を 180 度回転させたのが ll と異なっていると点対称ではない if fl != String(ll.reversed()) { ps = false } // 水平軸で線対称 // fl と ll が異なっていると水平軸で線対称ではない if fl != ll { lsh = false } // 垂直軸で線対称 // fl と fl の逆順、もしくは ll と ll の逆順が異なっていると垂直軸で線対称ではない if fl != String(fl.reversed()) || ll != String(ll.reversed()) { ls = false } } // 結果表示 if ps && (ls || lsh) { print("line point symmetry") } else if ps { print("point symmetry") } else if ls || lsh { print("line symmetry") } else { print("none") } |