CodeIQ:進捗はいいぞマーク

私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「進捗はいいぞマーク」(CodeIQ)を参照してください。

問題の概要

問題を引用します。
進捗のよさ具合をひと目で知らせるために「進捗はいいぞマーク」を作ることにしました。
「進捗はいいぞマーク」は高さ X 幅 X の正方形の中に高さが X 幅が X の菱形を半角小文字の「o」で描きます。
この菱形を丸に見立てて「いいぞマーク」ということでひとつ。
それ以外を半角ドット「.」にします。

例 高さ 1 幅 1 の進捗はいいぞマーク

o

例 高さ 3 幅 3 の進捗はいいぞマーク

.o.
o.o
.o.

例 高さ 5 幅 5 の進捗はいいぞマーク

..o..
.o.o.
o...o
.o.o.
..o..

「進捗はいいぞマーク」を手入力するのはしんどいのでプログラムで出力することにしました。
「進捗はいいぞマーク」を出力するプログラムを実装してください。

仕様
・標準入力の高さ(=幅)を元に「進捗はいいぞマーク」を出力する

標準入力
・標準入力の高さが 1-100 の整数で与えられます

例:
5

標準出力
・高さが奇数の場合は「進捗はいいぞ」を出力する
・高さが偶数の場合は「invalid」を出力する

例(入力の例に対する出力の例)

..o..
.o.o.
o...o
.o.o.
..o..

その他の仕様
・標準入力の末尾には改行があります
・標準出力の末尾に改行をつけてください
・標準入力の仕様で説明した内容以外の入力は行われません(不正入力に対するチェックは不要)

Samples
Sample1
Input
1

o

Sample2
Input
3

.o.
o.o
.o.

Sample3
Input
5

..o..
.o.o.
o...o
.o.o.
..o..
Sample4
Input
2

invalid

私のプログラム

Rubyで解答しています。

#!/usr/bin/ruby

def solve(n)
	if n%2 == 0
		puts "invalid"
		return
	end

	for i in 0...n
		str = "." * n

		x = (i <= n/2) ? i : n-1-i
		str[n/2-x] = "o"
		str[n/2+x] = "o"
		puts str
	end
end

# main
while line = gets
	line.strip!
	next if line.empty?

	solve(line.to_i)
end

解説

以前の「進捗ダメですマーク」と同じような問題です。
こちらの方が少しだけ難しいです。

main

入力値を数値にしてsolve()に渡します。

solve(n)

nが偶数なら'invalid'なので先にチェックしてしまいます。
nが奇数ならn行出力する必要があるのでそれだけループし、ループ1回ごとに1行ずつ出力します。
まず、'.'がn個の文字列を用意します。
oの位置は最初が真ん中でn/2まで1個ずつ外側にずれてゆき、そのあとは1個ずつ真ん中に寄ってきます。この真ん中から左右に何個外側かの計算を12行目でやっています。
13〜14行目で真ん中からx個外側をoに置き換えて、15行目で印字します。

雑感

「進捗ダメですマーク」は左上から始まるxは単純に右下に、右上から始まるxは単純に左下に向かうだけなので条件が不要でしたが、「進捗はいいぞマークは」真ん中の行以降が折り返しになるので条件が必要になります。そのぶんだけ少し難しいです(大した話ではありませんが)。