読者です 読者をやめる 読者になる 読者になる

300億円欲しい

メジャーリーグのデータ解析します

AtCoder016B 音楽ゲーム

ARC016です.
http://arc016.contest.atcoder.jp/tasks/arc016_2
プロコンに興味はないです.
プログラミングの勉強です.

問題文

楽器を演奏できない高橋君は、音楽ゲームが大好きです。
このゲームでは 9 個のボタンが存在し、曲に合わせてボタンをタイミングよく押したり、押しっぱなしにすることによって楽器を演奏してしている気分になります。
あなたには高橋くんがプレイした楽曲の譜面が与えられます。
ボタンを押す場所はx、押しっぱなしにする部分はo で与えられます。他は.です。
高橋くんが譜面をミスなくプレイしたとき、ボタンを押した回数を出力してください。

入力

1 行目に、譜面の行数を表す整数 N(1≦N≦100) が与えられる。
譜面は常に 9 列であることが保証されている。
2 行目からの N 行で、高橋くんが遊ぶ譜面が与えられる。
譜面の種類は x o . の 3 種類である。
譜面が x のとき、高橋くんはボタンを押す。
譜面が o のとき、高橋くんはボタンを押し、同じ列で o が続く限り押しっぱなしにする。
譜面が . のとき、高橋くんは何もしない。

入力例1

15
.........
.x.......
.........
...x.....
.........
.......o.
.......o.
.......o.
.........
..x.....o
........o
........o
....x...o
.x......o
........o

出力例1

7

7回ですね.
ゲームセンターのあれです.

解答例1

Rubyでやります.
入出力操作ならRubyが書きやすいと思っています.

N = gets.to_i
 
# 初期状態

list = ".........".split("")

# 入力を1つの配列にする
while line = gets do
  list = list + line.chomp.split("")
end
 
# ボタンを押す回数
counter = 0

# x なら押す. 
# o の1つ前の状態が o じゃなければボタンを押す 
for i in 0..(list.size) do
  if  list[i]== 'x'
    counter += 1
  elsif i>=9 && list[i] == "o" && list[i-9] !="o"
    counter += 1
  end
end
 
puts counter

これで通りました.

解答例2

頑張れば1行で書ける気がしました.

puts STDIN.read.split("\n").drop(1).map{|item| item.split("")}.transpose.map{|item2| item2.join.squeeze("o").delete(".").size.to_i}.inject(:+)

これで通りました.

よく分からない解説

入力を行列にするところまでは一緒です.

STDINをreadして,

15\n.........\n.x.......\n (続く)

改行で区切るために split("\n") して, drop(1)で先頭を削って,

[".........",".x.......",".........", (続く)]

split("")をmapすることで 各要素を1文字ごとに分割して

[[".", "." , ".",".", "." , "." ,".", "." , "."], (続く) ]

これで入力が行列としてとれました.

ここからが本題です.

行列をtransposeによって転置します.
すると, リストの各要素が9つのボタンそれぞれの動作になります.

各ボタンへの入力がわかりました.
理解のために, あるボタンが

ooo..xxx.x.x..ooo

のように動作するとします.
この場合は, 7回ボタンを押さないといけません.

この文字列で, oの連続列を圧縮して1つにします.
squeeze(".")すればいいです.
x はそのままです.

o..xxx.x.x..o

ここから "."を除きます. delete(".")すればいいです

oxxxo

この文字列の長さが, ボタンを押す回数ですかね.
sizeをとればいいですね.

5

各ボタンへの入力に同じ操作をすれば,

[5,5,5,5,5,5,5,5,5]

のように,
ボタンを押す回数の配列になります.
これの総和をとればいいです.

配列の総和だから最後に .sum をつけて... とやったら怒られました.
.sumなんてなかった. 忘れていました.
Rubyあるあるですかね. 分かりません.
配列の総和は .inject(:+) ですよね.

これでおしまいです.

まとめると,

STDIN
read
split("\n")
drop(1)
map{|item| item.split("")}
transpose
map{|item2|
item2.
join
squeeze("o")
delete(".")
size}
inject(:+)

を上から順番に適用すればいいです.