Lv-up」カテゴリーアーカイブ

PaizaAランクLvアップ問題と解説(Ruby)その6

3から続きます

※スキルチェック問題ではありません。
規約により公式の解答コードそのままはよろしくないので、
オリジナルのコードにしています。

詳しくはコチラ

なるべくわかりやすい解説を付けました。

マップの判定・縦横

1:移動が可能かの判定・方角 (paizaランク B 相当)

マップの行数 H と列数 W , 障害物を ‘#’ で、移動可能な場所を ‘.’ で表した H 行 W 列のマップ S_1 … S_H が与えられます。
続けて現在の座標 sy , sx ,1マス移動する方角 m が与えられるので、移動が可能かどうかを判定してください。

移動が可能であるということは、以下の図の通り
「移動先が障害物でない かつ 移動先がマップの範囲外でない」
ということを意味します。

なお、マスの座標系は左上端のマスの座標を ( y , x ) = ( 0 , 0 ) とし、
下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。


入力される値

H W sy sx m     
S_0    
...     
S_(H-1)
・ 1 行目にはマップの行数を表す整数 H , マップの列数を表す整数 W , 現在の y, x 座標を表す sy sx , 1 マス移動する方角 m が与えられます。
・ 続く H 行のうち i 行目 (0 ≦ i < H) には、マップの i 行目の文字をまとめた文字列 S_i が与えられ、 S_i の j 文字目は、マップの i 行目の j 列目に書かれている文字を表します。(0 ≦ j < W)入力値最終行の末尾に改行が1つ入ります。
期待する出力
移動が可能である場合 “Yes” を、不可能である場合 “No” を出力してください。

Yes

または

No

条件

すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ H, W ≦ 20
・ 0 ≦ sy < H , 0 ≦ sx < W
・ S_i は W 文字の文字列
・ マップ上の(sy, sx)のマスは必ず '.'
・ S の各文字は '.' または '#'
・ m は、N, S, E, W のいずれかであり、それぞれ 北・南・東・西 を意味します。
入力例1

3 3 1 1 E
..#
..#
...
出力例1

No
入力例2

9 2 4 0 S
#.
#.
..
##
..
..
.#
..
.#
出力例2

Yes

解答と解説(入力例1で行います)

#方角のみ文字列なので、それ以外を数値として変数に代入して、mに文字列として代入する
h,w,y,x,m = gets.split.map.with_index { |val, i| i == 4 ? val : val.to_i }

#盤面の情報をバラバラにして代入する 結果→[[".", ".", "#"], [".", ".", "#"], [".", ".", "."]]
chart = h.times.map { gets.chomp.chars}

#移動操作した時の座標の移動パターンを作成する。
direction = { N: [-1, 0], S: [1, 0], E: [0, 1], W: [0, -1] } 
#入力例1の場合mがEなので[0, 1]yとxに加算する
y += direction[m.to_sym][0]
x += direction[m.to_sym][1]

#画面外だとアウトなのでyとxが0以上でyがh未満xがw未満であることを記述する
#移動後の座標の現在地(chart[y][x])が"."であることを満たしたときに"Yes"
  if y >= 0 && x >= 0 && y < h && x < w && chart[y][x] == "."
    puts "Yes"
  それ以外を"No"と出力する
  else puts "No"
end

2:移動が可能かの判定・方向 (paizaランク B 相当)

マップの行数 H と列数 W , 障害物を ‘#’ , 移動可能な場所を ‘.’ で表した H 行 W 列のマップ S_1 … S_H が与えられます。
続けて現在の座標 sy , sx , 現在向いている方角 d , 1マス移動する方向 m が与えられるので、移動が可能かどうかを判定してください。

移動が可能であるということは、以下の図の通り
「移動先が障害物でない かつ 移動先がマップの範囲外でない」
ということを意味します。

なお、マスの座標系は左上端のマスの座標を ( y , x ) = ( 0 , 0 ) とし、
下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。


入力される値

H W sy sx d m      
S_0     
...     
S_(H-1)
・ 1 行目にはマップの行数を表す整数 H , マップの列数を表す整数 W , 現在の y, x 座標を表す sy sx , 現在向いている方角 d , 1 マス移動する方向 m が与えられます。
・ 続く H 行のうち i 行目 (0 ≦ i < H) には、マップの i 行目の文字をまとめた文字列 S_i が与えられ、 S_i の j 文字目は、マップの i 行目の j 列目に書かれている文字を表します。(0 ≦ j < W)
入力値最終行の末尾に改行が1つ入ります。
期待する出力
移動が可能である場合 “Yes” を、不可能である場合 “No” を出力してください。

Yes

または

No
条件

すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ H, W ≦ 20
・ 0 ≦ sy < H , 0 ≦ sx < W
・ S_i は W 文字の文字列
・ マップ上の(sy, sx)のマスは必ず '.'
・ S の各文字は '.' または '#'
・ d は、N, S, E, W のいずれかであり、それぞれ 北・南・東・西 を意味します。
・ m は、L, R のいずれかであり、それぞれ 左・右 を意味します。
入力例1

2 6 0 4 E L
####..
##..#.
出力例1

No
入力例2

7 9 6 0 S R
..#.#..##
..#..#...
#.......#
#.#...###
#.##....#
.....#...
..##..#.#
出力例2

No

解答と解説(入力例1で行います)

#dとmが文字列なので、それ以外を数値として変数に代入して、dとmに文字列として代入する 
h,w,y,x,d,m = gets.split.map.with_index { |val, i| i >= 4 ? val : val.to_i }

#盤面の情報をバラバラにして代入する  結果→[["#", "#", "#", "#", ".", "."], ["#", "#", ".", ".", "#", "."]]
chart = h.times.map { gets.chomp.chars}

#Rが来たときの移動パターンを設定する
operateR = { N: [0, 1], S: [0, -1], E: [1, 0], W: [-1, 0] } 
#Lが来たときの移動パターンを設定する
operateL ={ N: [0, -1], S: [0, 1], E: [-1, 0], W: [1, 0] } 

#入力例1の場合mがLで向いている方向がEなので[-1, 0]yとxに加算する
if m == "R"
  y += operateR[d.to_sym][0] 
  x += operateR[d.to_sym][1] 
elsif m == "L"
  y += operateL[d.to_sym][0] 
  x += operateL[d.to_sym][1] 
end

#画面外だとアウトなのでyとxが0以上でyがh未満xがw未満であることを記述する
#移動後の座標の現在地(chart[y][x])が"."である条件を満たしたときに"Yes"
  if y >= 0 && x >= 0 && y < h && x < w && chart[y][x] == "."
    puts "Yes"
  else puts "No"
end

※移動後の座標が[-1,4]で画面外なので”No”が出力された

3:移動が可能かの判定・複数回の移動 (paizaランク B 相当)

マップの行数 H と列数 W , 現在の座標 sy , sx , 移動の回数 N が与えられます。
続けて、障害物を ‘#’ で、移動可能な場所を ‘.’ で表した H 行 W 列 のマップ S_1 … S_H と N 回の移動の向き d_1 … d_N が与えられます。

移動者ははじめ北を向いています。移動者は、1 回の移動で次の行動を行います。

「移動の向きに方向転換したのち、1 マス進む。」

各移動が可能である場合、移動後の y , x 座標を出力してください。
移動が可能でない場合、移動後の座標を出力する代わりに “Stop” を出力して、以降の移動を打ち切ってください。

各移動が可能であるということは、以下の図の通り
「移動先が障害物でない かつ 移動先がマップの範囲外でない」
ということを意味します。

なお、マスの座標系は左上端のマスの座標を ( y , x ) = ( 0 , 0 ) とし、
下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。


右に移動

入力される値

H W sy sx N     
S_0     
...     
S_(H-1)     
d_1     
...     
d_N
・ 1 行目にはマップの行数を表す整数 H , マップの列数を表す整数 W , 現在の y, x 座標を表す sy sx , 移動する回数 N が与えられます。
・ 続く H 行のうち i 行目 (0 ≦ i < H) には、マップの i 行目の文字をまとめた文字列 S_i が与えられ、 S_i の j 文字目は、マップの i 行目の j 列目に書かれている文字を表します。(0 ≦ j < W)
・ 続く N 行のうち i 行目 (1 ≦ i ≦ N) には、i 回目の移動の向き d_i が与えられます。
入力値最終行の末尾に改行が1つ入ります。
期待する出力
M (1 ≦ M ≦ N) 行の出力

・ k (1 ≦ k ≦ M) 回目の移動後の y , x 座標、y_k, x_k を出力してください。
・ ただし、M 回目で移動しきれない場合、”Stop” を出力してください。

y_1 x_1
...
y_k x_k
...
y_M x_M

または

y_1 x_1
...
y_k x_k
...
y_(M-1) x_(M-1)
Stop
条件

すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ H, W ≦ 20
・ 1 ≦ N ≦ 100
・ 0 ≦ sy < H , 0 ≦ sx < W
・ S_i は W 文字の文字列
・ マップ上の(sy, sx)のマスは必ず '.'
・ S_i の各文字は '.' または '#'
・ d_i は、L, R のいずれかであり、それぞれ 左・右 を意味します。
入力例1

7 3 2 1 5
..#
...
...
...
..#
.#.
##.
L
L
L
L
L
出力例1

2 0
3 0
3 1
2 1
2 0
入力例2

7 11 1 5 43
.##........
.#......##.
.#....#...#
.###......#
#......###.
..#....###.
#.#........
L
L
R
L
R
L
R
L
L
R
L
R
L
L
L
L
R
R
R
L
R
L
R
L
L
R
L
L
R
L
R
L
R
R
R
R
L
R
L
L
L
R
R
出力例2

1 4
2 4
2 3
Stop

解答と解説(入力例2で行います)

直感的でわかりやすいけどあまりよろしくないかも

#数値として各変数に代入する
h,w,y,x,n = gets.split.map(&:to_i)

#盤面の情報をバラバラにして代入する 実行 → [[".", "#", "#", ".", ".", ".", ".", ".", ".", ".", "."], [".", "#", ".", ".", ".", ".", ".", ".", "#", "#", "."], [".", "#", ".", ".", ".", ".", "#", ".", ".", ".", "#"], [".", "#", "#", "#", ".", ".", ".", ".", ".", ".", "#"], ["#", ".", ".", ".", ".", ".", ".", "#", "#", "#", "."], [".", ".", "#", ".", ".", ".", ".", "#", "#", "#", "."], ["#", ".", "#", ".", ".", ".", ".", ".", ".", ".", "."]]
chart = h.times.map { gets.chomp.chars}

# Rが来たときの移動パターンを設定する
operateR = { N: [0, 1], S: [0, -1], E: [1, 0], W: [-1, 0] } 

#Lが来たときの移動パターンを設定する
operateL ={ N: [0, -1], S: [0, 1], E: [-1, 0], W: [1, 0] } 

#最初は北を向いているのでdに”N”を代入する
d = "N"

#コマンドがn回あるのでn回繰り返す
n.times do
  #RかLの入力値を受け取り代入する
  command = gets.chomp

#自分が向いている向きdとコマンドL,Rによってyとxを加算する
  if command == "R"
     y += operateR[d.to_sym][0] 
     x += operateR[d.to_sym][1] 
  elsif command == "L"
     y += operateL[d.to_sym][0] 
     x += operateL[d.to_sym][1] 
  end

#自分の向いている向きとコマンドのLかRかで自分の向いている向きを変更する。
  if d == "N" && command == "L" || d == "S" && command == "R"
     d = "W"
  elsif d == "W" && command == "L" || d == "E" && command == "R"
     d = "S"
  elsif d == "E" && command == "L" || d == "W" && command == "R"
     d = "N"
  elsif d == "S" && command == "L" || d == "N" && command == "R"
     d = "E"
  end

#画面外だとアウトなのでyとxが0以上でyがh未満xがw未満であることを記述する
#移動後の座標の現在地(chart[y][x])が"."である条件を満たしたときに"Yes"
  if y >= 0 && x >= 0 && y < h && x < w && chart[y][x] == "."
     puts y.to_s + " " + x.to_s

条件を満たさなかったときに”Stop”を出力して繰り返しを終わらせる(break)
  else puts "Stop"
     break
  end
end

別解

#数値として各変数に代入する
h, w, y, x, n = gets.split.map(&:to_i)

#盤面の情報をバラバラにして代入する 実行 → [[".", "#", "#", ".", ".", ".", ".", ".", ".", ".", "."], [".", "#", ".", ".", ".", ".", ".", ".", "#", "#", "."], [".", "#", ".", ".", ".", ".", "#", ".", ".", ".", "#"], [".", "#", "#", "#", ".", ".", ".", ".", ".", ".", "#"], ["#", ".", ".", ".", ".", ".", ".", "#", "#", "#", "."], [".", ".", "#", ".", ".", ".", ".", "#", "#", "#", "."], ["#", ".", "#", ".", ".", ".", ".", ".", ".", ".", "."]]
chart = h.times.map { gets.chomp.chars }

#移動するパターンを作成する 北 東 南 西 の順番
direction = [[-1, 0], [0, 1], [1, 0], [0, -1]]

#状態を定義する。最初は0
current = 0

#コマンドがn回あるのでn回繰り返す
n.times do
 #RかLの入力値を受け取り代入する
  d = gets.chomp
 #Lの時−1してRのときに+1する
  d == "L" ? current -= 1 : current += 1
  y += direction[current % 4][0]
  x += direction[current % 4][1]

  if y >= 0 && x >= 0 && y < h && x < w && chart[y][x] == "."
    puts y.to_s + " " + x.to_s
# 条件を満たさなかったときに”Stop”を出力して繰り返しを終わらせる(break)
  else puts "Stop"
    break
  end
end

入力例2

1ループ目

最初の状態はcurrent = 0でコマンドがL、yとx が[1,5]
currentが  -1になり
-1 % 4 は 3なので
direction[3]は[0,-1]
yとxに [0,-1]を加算して
yとx が[1,4]

2ループ目

最初の状態はcurrent = -1でコマンドがL、yとx が[1,4]
currentが  -2になり
-2 % 4 は 2なので
direction[2]は[1,0]
yとxに [1,0]を加算して
yとx が[2,4]

3ループ目

最初の状態はcurrent = -2でコマンドがR、yとx が[2,4]
currentが  -1になり
-1 % 4 は 3なので
direction[3]は[0,-1]
yとxに [0,-1]を加算して
yとx が[2,3]

4ループ目

最初の状態はcurrent = -2でコマンドがL、yとx が[2,3]
currentが  -2になり
-2 % 4 は 2なので
direction[2]は[1,0]
yとxに [1,0]を加算して
yとx が[3,4]
移動先が”#”があるので”Stop”を出力してループを抜ける

※ポイント

d == ‘L’ ? current -= 1 : current += 1
でcurrentの値を変えるだけで移動操作が表現できる。

4:移動が可能かの判定・幅のある移動 (paizaランク B 相当)

マップの行数 H と列数 W , 障害物を ‘#’ で移動可能な場所を ‘.’ で表した H 行 W 列のマップ S_1 … S_H , 現在の座標 sy, sx, 移動の回数 N が与えられます。
続けて、 N 回の移動の向き d_1 … d_N と移動するマス数 l_1 … l_N が与えられます。

プレイヤーははじめ北を向いています。

各移動が可能である場合、移動後の y , x 座標 を出力してください。
移動が可能でない場合(移動しきれない場合)、移動できるところまで移動した後の座標を出力した後に “Stop” を出力して、以降の移動を打ち切ってください。

各移動が可能であるということは、以下の図の通り
「今いるマスから移動先のマスまでに障害物がない かつ 移動先がマップの範囲外でない」
ということを意味します。

なお、マスの座標系は左上端のマスの座標を ( y , x ) = ( 0 , 0 ) とし、
下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。


入力される値

H W sy sx N        
S_0         
...     
S_(H-1)     
d_1 l_1     
...     
d_N l_N
・ 1 行目にはマップの行数を表す整数 H , マップの列数を表す整数 W , 現在の y, x 座標を表す sy sx , 移動する回数 N が与えられます。
・ 続く H 行のうち i 行目 (0 ≦ i < H) には、マップの i 行目の文字をまとめた文字列 S_i が与えられ、 S_i の j 文字目は、マップの i 行目の j 列目に書かれている文字を表します。(0 ≦ j < W)
・ 続く N 行のうち i 行目 (1 ≦ i ≦ N) には、i 回目の移動の向き d_i と移動するマス数 l_i が与えられます。入力値最終行の末尾に改行が1つ入ります。
期待する出力
M (1 ≦ M ≦ N+1) 行の出力

・ k (1 ≦ k ≦ M) 回目の移動後の y , x 座標、y_k, x_k を出力してください。
・ M 回目で移動しきれない場合、移動できるところまで移動した後の y , x 座標、y_M, x_M を出力した後に “Stop” を出力してください。

y_1 x_1
...
y_k x_k
...
y_M x_M

または

y_1 x_1
...
y_k x_k
...
y_M x_M
Stop
条件

すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ H, W ≦ 20
・ 1 ≦ N ≦ 100
・ 0 ≦ sy < H, 0 ≦ sx < W
・ 1 ≦ l_i ≦ 20
・ S_i は W 文字の文字列
・ マップ上の(sy, sx)のマスは必ず '.'
・ S の各文字は '.' または '#'
・ d_i は、L, R のいずれかであり、それぞれ 左・右 を意味します。
入力例1

10 10 6 4 3
..#.....#.
..........
##.#......
#.##....#.
.##.#.....
........#.
.#......#.
.#........
...#......
#.#.......
L 2
R 1
L 4
出力例1

6 2
5 2
5 0
Stop
入力例2

15 15 6 4 7
.......#.......
....#.......#.#
.......#.....#.
.......#.#...#.
#......#.......
#.........#....
..............#
..#...#....#..#
............#..
..#...##......#
##..#..#.#.....
#..............
............#..
...#...........
.#.........#.#.
L 4
L 3
R 4
R 5
L 3
L 2
R 1
出力例2

6 0
9 0
9 0
Stop

解答と解説

少し無駄な部分があるがとりあえずできたほう

#数値として各変数に代入する
h, w, y, x, n = gets.split.map(&:to_i)

#盤面の情報をバラバラにして代入する
chart = h.times.map { gets.chomp.chars }

#移動するパターンを作成する 北 東 南 西 の順番
direction = [[-1, 0], [0, 1], [1, 0], [0, -1]]

#状態をそれぞれ定義する。最初は0
current,stop = 0,0

#コマンドがn回あるのでn回繰り返す
n.times do

 #文字列と数値をそれぞれの変数に代入
  d,move = gets.split.map.with_index { |val, i| i == 0 ? val : val.to_i }

 #Lの時−1してRのときに+1する
  d == 'L' ? current -= 1 : current += 1

 #移動する回数繰り返す
  move.times do |i|

#currentの状態によってyとxを加算する
  y += direction[current % 4][0]
  x += direction[current % 4][1]

#画面外だとアウトなのでyとxが0以上でyがh未満xがw未満であることを記述する
#移動後の座標の現在地(chart[y][x])が"."で繰り返しの最後のときに出力
  if y >= 0 && x >= 0 && y < h && x < w && chart[y][x] == "."
    puts y.to_s + " " + x.to_s if move == i + 1

#画面外や現在地が”#”のとき前の状態に戻してStopを1にして繰り返しを終わらせる
  else y -= direction[current % 4][0]
       x -= direction[current % 4][1]
       stop = 1
       break
  end
  end
# stopが1のときに現在地を出力してから改行して”Stop”を出力して繰り返しを終わらせる
  if stop == 1
     puts y.to_s + " " + x.to_s + "\n" +"Stop"
  break
end
end

PaizaAランクLvアップ問題と解説(Ruby)その4

その3から続いてます

※スキルチェック問題ではありません。

規約により公式の解答コードそのままはよろしくないので、
オリジナルのコードにしています。

詳しくはコチラ

なるべくわかりやすい解説を付けました。

3:座標系での移動・向き (paizaランク B 相当)

開始時点の y , x 座標 と向いている方角 D が与えられます。
続く 1 行で移動の向き d が与えられるので、その向きに移動した後の y , x 座標 を答えてください。
移動前に向いている方角によって同じ移動の向きでも座標の変化が違うことに気をつけてください。

なお、マスの座標系は左上端のマスの座標を ( y , x ) = ( 0 , 0 ) とし、
下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。
以下の図を参考にしてみてください。




入力される値
Y X D       
d

・ 1 行目には、開始時点の y , x 座標を表す Y , X, 現在の向いている方角を表す文字 D が与えられます。
・ 2 行目には、移動の向きを表す文字 d が与えられます。

期待する出力
1 行での出力

・ 移動した後の y , x 座標を出力してください。

y x

 条件

すべてのテストケースにおいて、以下の条件をみたします。
・ -100 ≦ X, Y ≦ 100
・ D は、N, S, E, W のいずれかでそれぞれ 北・南・東・西 を意味する。
・ d は、L, R のいずれかでそれぞれ 左・右 に 1 マス進むことを表す。

入力例1

4 2 N
R

出力例1

4 3

入力例2

6 9 E
R

出力例2

7 9

解答と解説

#1行目の入力値を各変数に代入yとxは数値に変換してDは文字列として代入
y, x, D = gets.split.map.with_index { |val, i| i != 2 ? val.to_i : val }

#移動の向きを表す文字を代入
d = gets.chomp

#Rが来たときの移動パターンを設定する
operateR = { N: [0, 1], S: [0, -1], E: [1, 0], W: [-1, 0] } 
#Lが来たときの移動パターンを設定する
operateL ={ N: [0, -1], S: [0, 1], E: [-1, 0], W: [1, 0] } 
  if d == "R"
    y += operateR[D.to_sym][0] 
    x += operateR[D.to_sym][1] 
  elsif d == "L"
    y += operateL[D.to_sym][0] 
    x += operateL[D.to_sym][1] 
  end
#移動後の座標を出力する
puts y.to_s + ' ' + x.to_s

別解 3項演算子でLとRのときに値を変数に代入するだけ

y, x, now = gets.split.map.with_index { |val, i| i != 2 ? val.to_i : val }
d = gets.chomp
d == 'L' ? direction = -1 : direction = 1
if now == 'N'
  x += direction
elsif now == 'S'
  x -= direction
elsif now == 'E'
  y += direction
elsif now == 'W'
  y -= direction
end
puts y.to_s + ' ' + x.to_s

4:座標系での規則的な移動 (paizaランク B 相当)

開始時点の x , y 座標と移動の歩数 N が与えられます。
以下の図のように時計回りに渦を巻くように移動を N 歩行った後の x , y 座標 を答えてください。

なお、マスの座標系は下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。

入力される値
X Y N

・ 1 行で、開始時点の x , y 座標を表す X , Y, 移動の歩数 N が与えられます。
入力値最終行の末尾に改行が1つ入ります。

期待する出力
1行での出力

・ 移動を N 歩行った後の x , y 座標を出力してください。

x y
条件
すべてのテストケースにおいて、以下の条件を満たします。
・ -100 ≦ X, Y ≦ 100
・ 0 ≦ N ≦ 100
入力例1

0 0 3
出力例1

0 1
入力例2

38 47 27
出力例2

41 47

解答

 

 

 

その5に続きます

PaizaAランクLvアップ問題と解説(Ruby)その3

その2から続いています

※スキルチェック問題ではありません。

規約により公式の解答コードそのままはよろしくないので、
オリジナルのコードにしています。

詳しくはコチラ

なるべくわかりやすい解説を付けました。

1:マップからの座標取得 (paizaランク C 相当)

マップの行数 H と列数 W とマップを表す H 行 W 列の文字列 S_1 …S_H が与えられます。
要素が ‘#’ になっているマスが 1 つあるので、その y , x 座標 を答えてください。

なお、マスの座標系は左上端のマスの座標を ( y , x ) = ( 0 , 0 ) とし、
下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。

入力される値

H W     
S_0     
...     
S_(H-1)

・ 1 行目には盤面の行数を表す整数 H , 盤面の列数を表す整数 W が与えられます。
・ 続く H 行のうち i 行目 (0 ≦ i < H) には、盤面の i 行目の文字をまとめた文字列 S_i が与えられ、 S_i の j 文字目は、盤面の i 行目の j 列目に書かれている文字を表します。(0 ≦ j < W)
入力値最終行の末尾に改行が1つ入ります。

期待する出力
1行の出力

・ 要素が ‘#’ になっているマスの y , x 座標を 1 行で出力してください。

y x
条件
すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ H, W ≦ 20
・ S は W 文字の文字列
・ S の各文字は '.' または '#'
・ '#' のマスは必ず1つ
入力例1

1 1
#
出力例1

0 0
入力例2

3 3
.#.
...
...
出力例2

0 1

解答と解説(入力例2の場合)

#1行目の入力値を各変数に代入
h,w = gets.split.map(&:to_i)

#縦(盤面の行数)の回数分繰り返す
h.times do |i|

#入力値を受け取り改行を打ち消しバラバラにする(例;[".", "#", "."])
  line = gets.chomp.chars
 
  #横(盤面の列数)の回数分繰り返す
  w.times do |j|
  #"#"のときに現在地を出力する(後置if)
    puts i.to_s + " " + j.to_s if line[j] == "#"
  end
end

2:座標系での移動・方角 (paizaランク C 相当)

開始時点の y , x 座標 と移動の回数 N が与えられます。
続く N 行で移動の方角 d_1 … d_N が与えられるので、与えられた順に移動をしたときの各移動後の y , x 座標 を答えてください。

ただし、図の通り、上側( y 軸の負の向き)を北とします。

なお、マスの座標系は左上端のマスの座標を ( y , x ) = ( 0 , 0 ) とし、
下方向が y 座標の正の向き、右方向が x 座標の正の向きとします。

入力される値
Y X N       
d_1     
...     
d_N

・ 1 行目には、開始時点の y , x 座標を表す Y , X, 移動の回数 N が与えられます。
・ 続く N 行 (1 ≦ i ≦ N) には、盤面の i 回目の移動の方角を表す文字 d_i が与えられます。入力値最終行の末尾に改行が1つ入ります。

期待する出力
N 行での出力

・ 各移動後の y , x 座標を出力してください。

y_1 x_1
...
y_N x_N
条件
すべてのテストケースにおいて、以下の条件をみたします。

・ 0 ≦ Y, X, N ≦100
・ d_i は、N, S, E, W のいずれかでそれぞれ 北・南・東・西 を意味する。
入力例1

0 0 1
N
出力例1

-1 0
入力例2

5 10 4
N
W
E
S
出力例2

4 10
4 9
4 10
5 10

解答 普通にやる場合

y,x,n = gets.split.map(&:to_i)
command = readlines.map(&:chomp)
command.size.times do |i|
  if command[i] == "N"
     puts (y-1).to_s + " " + x.to_s 
      y += - 1
  elsif command[i] == "W"
     puts y.to_s + " " + (x-1).to_s
     x += - 1
  elsif command[i] == "E"
     puts y.to_s + " " + (x+1).to_s 
     x += + 1
  elsif command[i] == "S"
     puts (y + 1).to_s + " " + x.to_s 
     y += + 1
  end
end

別解 ハッシュを使う場合(こっちのほうがいいかも)

y, x, n = gets.split.map(&:to_i)
direction = { N: [-1, 0], S: [1, 0], E: [0, 1], W: [0, -1] }
n.times do
  command = gets.chomp
  y += direction[command.to_sym][0]
  x += direction[command.to_sym][1]
  puts y.to_s + ' ' + x.to_s
end

その4に続きます

paizaLvアップ問題と解答(標準入力1)Ruby

※スキルチェック問題ではありません。
規約により公式の解答コードそのままはよろしくないので、
オリジナルのコードにしています。

詳しくはコチラ

なるべくわかりやすい解説を付けました。

問題0:1行の入力 (paizaランク D 相当)

文字列 s が 1 行で与えられるので s をそのまま出力してください。

入力例1

paiza

出力例1

paiza

解答  putsで出力できます。

# 文字列を変数に代入する(このとき改行コードを打ち消す)
strings = gets.chomp
puts strings

問題1 2 行の入力

文字列 s と t が 2 行で与えられるので、s と t の 2 行をそのまま出力してください。

入力例2
heisei31
reiwa1
出力例2
heisei31
reiwa1

解答 readlines(chomp: true)で入力を受け取って出力するだけ

# 文字列を変数に代入する(このとき改行コードを打ち消す)
strings = readlines(chomp: true)
puts strings

別解 2行だけならこちらのほうがパフォーマンスは良いです

a = gets.chomp
b = gets.chomp
puts a,b

問題2 3 行の入力 (paizaランク D 相当)

文字列 s, t, u が 3 行で与えられるので、s, t, u の 3 行をそのまま出力してください。

入力例1

abc
def
ghi

出力例1

abc
def
ghi

解答 2行のときと同じでreadlines(chomp: true)を使うと良い

strings = readlines(chomp: true)
puts strings

別解  3行だけならこちらのほうがパフォーマンスは良いです

a = gets.chomp 
b = gets.chomp
c = gets.chomp
puts a,b,c

問題3 5つの文字列の半角スペース区切りでの分割

入力される値

なし

期待する出力

one
two
three
four
five

解答 \nでむりやり改行させる(とても読みにくい)

puts "one\ntwo\nthree\nfour\nfive"

別解  配列を作成してputsで出力する。

puts ["one","two","three","four","five"]

PaizaCランクLvアップ問題集(Ruby)

※スキルチェック問題ではありません。
規約により公式の解答コードそのままはよろしくないので、
オリジナルのコードにしています。

詳しくはコチラ

なるべくわかりやすい解説を付けました。

問題1 数字の文字列操作(時刻2)

時刻を表す長さ 5 の文字列 S が “XX:XX” の形式で与えられます。与えられた時刻の 30 分後の時刻を同じ形式で出力してください。

1 行目に文字列 S が与えられます。
S は “XX:XX” という形をしており、 “:” の左側は時を、右側は分を表します。時や分が一桁である場合、十の位は 0 で埋められます。また、 00:00 から 23:59 までの 24 時間表記を採用しています。

入力例1
01:02
出力例1
01:32
入力例2
12:31
出力例2
13:01

解答  入力例1で解説

  1. 入力された時刻を受け取る(数値としてこのとき:は消える)
  2. hは1が入っている
  3. mには2が入っている
  4. mに30を加算する
  5. 条件分岐でmが60以上のとき、mに−60して、hを1増やす
  6. hとmを文字列に変換する
  7. hとmが一桁の時に”01″となるように’0’を追加する
  8. hとmの間に:をつけて出力する
s = gets.split(':').map(&:to_i)
h = s[0]
m = s[1]
m += 30
if m > 59
  m -= 60
  h += 1
end

h = h.to_s
m = m.to_s

h = '0' + h if h.size == 1
m = '0' + m if m.size == 1

puts h + ':' + m

問題  文字列(工事)

工事がN週間続く
各週日曜日の工事が始まる時刻と、
工事が何時間何分続くのかに関する情報が与えられるので、
工事が終わる時刻を00:00から23:59までの24時間表記で出力してください
工事がh時入力は以下のフォーマットで与えられます。

入力される値

N(工事が続く週の数を表す整数)
t_1 工事が始まる時間
h_1 工事が続く時間
m_1 工事が続く分
半角スペース区切りで与えられます。

t_iは24時間表記の時刻を表す文字列で、”AB:XY”という形をしており、これはAB時XY分を表す。
今回は00:00〜23:59までの24時間表記を採用し、時・分を表す数字が1桁の場合には十の位を0で埋めます。
入力値最終行の末尾に改行が1つ入ります。
t_N h_N m_N間m分続くとした場合、工事が始まった時刻のh時間m分後を指します)。

各週の工事が終わる時刻をN行出力してください。
時や分を表す数字が1桁の場合には十の位を0で埋めてください。たとえば24時は00:00、27時は03:00となります。

入力例2
2
15:59 0 1
23:20 1 0
出力例2
16:00
00:20

解答

  1. 入力Nを受け取る
  2. N回繰り返したいのでn.times
  3. 変数t, a_h, a_mにそれぞれ文字列を代入していく
  4. 変数h, mに時刻の部分の:で分割して数値を代入する。
  5. a_hとa_mを数値に変換して自己代入する
  6. mにa_m, hにa_hを加算する
  7. 条件分岐でmが60以上のとき、mに−60して、hを1増やす
  8. hが24以上のときhを−24する
  9. hとmを文字列に変換する
  10. hとmが一桁の時に”01″となるように’0’を追加する
  11. hとmの間に:をつけて出力する
n = gets.to_i

n.times do
  t, a_h, a_m = gets.split(' ')
  h, m = t.split(':').map(&:to_i)
  a_h = a_h.to_i
  a_m = a_m.to_i

  m += a_m
  h += a_h
  if m > 59
    m -= 60
    h += 1
  end
  h -= 24 if h > 23

  m = m.to_s
  h = h.to_s
  m = '0' + m if m.size == 1
  h = '0' + h if h.size == 1

  puts h + ':' + m
end

※ポイント

a, b, c = 長さ3の配列 のように書くと a, b, c に 長さ3の配列 の要素が先頭から順に代入される

たとえばa, b, c= [1, 2, 3]と書くと a に 1 が、b に 2 が、c に 3 がそれぞれ代入される。

配列の長さと同じ数の変数を左辺に用意する必要があります。

日付を跨ぐ場合、h > 23 のときh -= 24を実行する

h の長さが 1 であるとき、h の先頭に 0 を付ける
m の長さが 1 であるとき、m の先頭に 0 を付ける

先に分の方の計算を先にすること!

m > 59 の操作で h > 23 になる可能性があるため。

PaizaLvアップ問題集(標準出力)

※スキルチェック問題ではありません。
規約により公式の解答コードそのままはよろしくないので、
オリジナルのコードにしています。

詳しくはコチラ

なるべくわかりやすい解説を付けました。

問題1

実数 N、自然数 M が入力されます。N を丸めて小数第 M 位まで出力してください。
また、N の小数部が小数第 M 位に満たない場合は 0 で埋めて出力してください。

なお、小数第 M 位が 5 になることはありません。
自然な丸め処理を行って出力すると正解になります。

入力例
0.813 4

出力例4
0.8130

解答

n,m = gets.split(' ').map(&:to_f)
# 小数点以下の桁数を指定しています
printf("%.#{m.to_i}f", n)

問題2 複数の実数を出力 (paizaランク C 相当)

自然数 Q が与えられます。Q 回以下の問題に答えてください。
実数 N、自然数 M が入力されます。N を丸めて小数第 M 位まで出力してください。また、N の小数部が小数第 M 位に満たない場合は 0 で埋めて出力してください。

なお、小数第 M 位が 5 になることはありません。
自然な丸め処理を行って出力すると正解になります。

入力例1

4
0.813 1
0.813 2
0.813 3
0.813 4

出力例1

0.8
0.81
0.813
0.8130

問題3 直角三角形の出力

自然数 N が与えられます。1 ≦ i ≦ N の各 i について、i 行目には以下の数列を出力してください。* 1 以上 i 以下の数値をすべて、半角スペース区切りで出力してください

入力例1
4

出力例1

1
1 2
1 2 3
1 2 3 4

解答

  1. 入力Nを代入

  2. 配列[1, 2, 3, 4]を作る

  3. timesで繰り返し処理をする

  4. a.takeを使うことで配列をiずつ取り出して半角スペースを間に入れて出力する

n = gets.to_i
a = *(1..n)
1..n.times do |i|
  puts a.take(a[i]).join(' ')
end

 

問題4 すべての行の長さが不定な 2 次元配列の出力

自然数NとN個の要素の数列Mが与えられます。
1 ≦ i ≦ N の各 i について、i 行目には以下の数列を出力してください。
1 以上 M_i 以下のすべての自然数を昇順、半角スペース区切りで出力してください。

入力例1

4
2 4 3 1

出力例1

1 2
1 2 3 4
1 2 3
1

入力例2

1
1

出力例2

1

 

解答  入力例1で解説

  1. 入力Nを受け取る

  2. 数列Mを受け取る

  3. N回繰り返す

  4. mの配列の数字−1回繰り返し(m[0]のときは2−1で1回)、1から初めて

  5. 繰り返しが終わったら、mの配列を加える1 2

  6. 2回目は(m[1]なので4−1で3回繰り返し)1 2 3までやったら

  7. puts m[i]で1 2 3 4が出力されて

  8. 以下繰り返していく

n = gets.to_i
m = gets.split(' ').map(&:to_i)
n.times do |i|
# ここで先に1,2,3,とやってから
  (m[i]-1).times { |j| print "#{j +1 } "}
# 最後にmの配列を足す
  puts m[i]
end