paiza プログラミング

[Ruby]paiza Bランクレベルアップメニュー 文字列を切り取る (paizaランク D 相当)の解説

B-lvup_文字列を切り取る

こんにちは!じゃいごテックのあつしです。

今回はpaiza Bランクレベルアップメニュー から文字列を切り取るという問題を解説します。

この問題集は文字列に関する5個のSTEP問題(D級)FINAL問題(D級)で構成されていて、STEP問題を解いて行けばFINAL問題も解けるはず!となっています。

STEP問題を解いてみる

STEP問題は文字列の基本問題です。
簡単な解説は付けていますが、難しいと感じたら下記の記事も参考にしてみて下さい。

※過去に出題された小問題が出てくることがありますが、チケットに余裕があれば復習のつもりで取り組んでみましょう。

STEP1: 文字列の分割 (paizaランク D 相当)

STEP1 はスペース区切りの2つの文字列を改行区切りの2行で出力する問題です。

解答例

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<<"EOS"
入力例1
Hello World
出力例1
Hello
World
入力例2
0 1
出力例2
0
1
入力例3
a b
出力例3
a
b
EOS
# [解答例1]
a, b = gets.split
puts a
puts b
# [解答例2]
ary = gets.split
puts ary
<<"EOS" 入力例1 Hello World 出力例1 Hello World 入力例2 0 1 出力例2 0 1 入力例3 a b 出力例3 a b EOS # [解答例1] a, b = gets.split puts a puts b # [解答例2] ary = gets.split puts ary
<<"EOS"

入力例1
Hello World

出力例1
Hello
World

入力例2
0 1

出力例2
0
1

入力例3
a b

出力例3
a
b

EOS

# [解答例1]
a, b = gets.split
puts a
puts b

# [解答例2]
ary = gets.split
puts ary

解答例1: 半角スペース区切りの文字列を別の変数に代入して、それぞれ出力しています。

解答例2: 半角スペース区切りの文字列を一旦配列aryに格納して、配列の要素を改行区切りで出力しています。


STEP2: 整数の足し算 (paizaランク D 相当)

STEP2 はスペース区切りの2つの整数を足した値を出力する問題です。

解答例

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<<"EOS"
入力例1
0 0
出力例1
0
入力例2
1 2
出力例2
3
入力例3
10 20
出力例3
30
EOS
# [解答例1]
a, b = gets.split.map(&:to_i)
puts a + b
# [解答例2]
puts gets.split.map(&:to_i).sum
<<"EOS" 入力例1 0 0 出力例1 0 入力例2 1 2 出力例2 3 入力例3 10 20 出力例3 30 EOS # [解答例1] a, b = gets.split.map(&:to_i) puts a + b # [解答例2] puts gets.split.map(&:to_i).sum
<<"EOS"

入力例1
0 0

出力例1
0

入力例2
1 2

出力例2
3

入力例3
10 20

出力例3
30

EOS

# [解答例1]
a, b = gets.split.map(&:to_i)
puts a + b

# [解答例2]
puts gets.split.map(&:to_i).sum

解答例1: 半角スペース区切りの文字列を整数型に変換して別の変数に代入して、足したものを出力しています。

解答例2: 半角スペース区切りの文字列を整数型に変換して配列にして、sumメソッドで合計値を求めて出力しています。


STEP3: 文字列の長さ (paizaランク D 相当)

STEP3 は文字列の長さを出力する問題です。

解答例

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<<"EOS"
入力例1
input
出力例1
5
入力例2
abc123
出力例2
6
入力例3
0123456789
出力例3
10
EOS
s = gets.chomp
puts s.length
<<"EOS" 入力例1 input 出力例1 5 入力例2 abc123 出力例2 6 入力例3 0123456789 出力例3 10 EOS s = gets.chomp puts s.length
<<"EOS"

入力例1
input

出力例1
5

入力例2
abc123

出力例2
6

入力例3
0123456789

出力例3
10

EOS

s = gets.chomp
puts s.length

解答例: lengthメソッドで文字列の長さを取得して出力しています。


STEP4: 文字列の1文字目 (paizaランク D 相当)

STEP4 は文字列の1文字目を出力する問題です。

解答例

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<<"EOS"
入力例1
abc
出力例1
a
入力例2
123
出力例2
1
入力例3
1234567890
出力例3
1
EOS
s = gets.chomp
puts s[0]
<<"EOS" 入力例1 abc 出力例1 a 入力例2 123 出力例2 1 入力例3 1234567890 出力例3 1 EOS s = gets.chomp puts s[0]
<<"EOS"

入力例1
abc

出力例1
a

入力例2
123

出力例2
1

入力例3
1234567890

出力例3
1

EOS

s = gets.chomp
puts s[0]

解答例: 文字列[0]で文字列の1文字目を参照して出力しています。


STEP5: あいだの整数 (paizaランク D 相当)

STEP5 はスペース区切りの2つの整数が与えられ、その区間の整数を改行区切りで出力する問題です。

解答例

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<<"EOS"
入力例1
0 10
出力例1
0
1
2
3
4
5
6
7
8
9
10
入力例2
5 10
出力例2
5
6
7
8
9
10
入力例3
3 3
出力例3
3
EOS
# [解答例1]
a, b = gets.split.map(&:to_i)
(a..b).each {|num| puts num}
# [解答例2]
a, b = gets.split.map(&:to_i)
num = a
while num <= b
puts num
num += 1
end
<<"EOS" 入力例1 0 10 出力例1 0 1 2 3 4 5 6 7 8 9 10 入力例2 5 10 出力例2 5 6 7 8 9 10 入力例3 3 3 出力例3 3 EOS # [解答例1] a, b = gets.split.map(&:to_i) (a..b).each {|num| puts num} # [解答例2] a, b = gets.split.map(&:to_i) num = a while num <= b puts num num += 1 end
<<"EOS"

入力例1
0 10

出力例1
0
1
2
3
4
5
6
7
8
9
10

入力例2
5 10

出力例2
5
6
7
8
9
10

入力例3
3 3

出力例3
3

EOS

# [解答例1]
a, b = gets.split.map(&:to_i)
(a..b).each {|num| puts num}


# [解答例2]
a, b = gets.split.map(&:to_i)
num = a
while num <= b
  puts num
  num += 1
end

解答例1: 整数aから整数bまでの範囲オブジェクトを生成して順番に出力しています。
a以上b以下の範囲オブジェクトを生成する(a..b)は、Range.new(a, b)を省略した書き方です。

解答例2: whileループを使って整数aで初期化したnumが整数b以下の間、numを出力してインクリメント(+1)して繰り返し処理を行なっています。

文字列を切り取る (paizaランク D 相当)を解いてみる

※ paiza Bランクレベルアップメニューより

問題

スペース区切りの2つの整数と、文字列が入力されるので、2つの整数の範囲の部分文字列を出力してください。

入力される値

入力は以下のフォーマットで与えられます。

a b
s

入力値最終行の末尾に改行が1つ入ります。

期待する出力

s の文字列を a 文字目から b 文字目の範囲で切り取った文字列を出力してください。

最後は改行し、余計な文字、空行を含んではいけません。

条件

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

  • 1 ≦ a ≦ b ≦ (文字列 s の長さ) ≦ 100

s は半角英数字で構成された文字列です。

入力例1
2 6
this is a pen
出力例1
his i
入力例2
2 6
Welcome to the paiza! I`m studying ruby!
出力例2
elcom
入力例3
1 1
Welcome to the paiza! I`m studying ruby!
出力例3
W
攻略ポイント

ポイント

  • 文字列を開始位置から終了位置で切り取る

デバッグを楽にするためにメソッドを作成します。メソッドについては下記の記事も参考にしてみて下さい。

問題を解く流れ

入出力例をコピペしてヒアドキュメントで変数に代入し、データを確認します。正しく受け取れていれば確認用コードは削除します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
INPUT1 = <<~"EOS"
2 6
this is a pen
EOS
OUTPUT1 = <<~"EOS"
his i
EOS
INPUT2 = <<~"EOS"
2 6
Welcome to the paiza! I`m studying ruby!
EOS
OUTPUT2 = <<~"EOS"
elcom
EOS
INPUT3 = <<~"EOS"
1 1
Welcome to the paiza! I`m studying ruby!
EOS
OUTPUT3 = <<~"EOS"
W
EOS
p INPUT1
# > "2 6\nthis is a pen\n"
p INPUT2
# > "2 6\nWelcome to the paiza! I`m studying ruby!\n"
p INPUT3
# > "1 1\nWelcome to the paiza! I`m studying ruby!\n"
INPUT1 = <<~"EOS" 2 6 this is a pen EOS OUTPUT1 = <<~"EOS" his i EOS INPUT2 = <<~"EOS" 2 6 Welcome to the paiza! I`m studying ruby! EOS OUTPUT2 = <<~"EOS" elcom EOS INPUT3 = <<~"EOS" 1 1 Welcome to the paiza! I`m studying ruby! EOS OUTPUT3 = <<~"EOS" W EOS p INPUT1 # > "2 6\nthis is a pen\n" p INPUT2 # > "2 6\nWelcome to the paiza! I`m studying ruby!\n" p INPUT3 # > "1 1\nWelcome to the paiza! I`m studying ruby!\n"
INPUT1 = <<~"EOS"
  2 6
  this is a pen
EOS
OUTPUT1 = <<~"EOS"
  his i
EOS

INPUT2 = <<~"EOS"
  2 6
  Welcome to the paiza! I`m studying ruby!
EOS
OUTPUT2 = <<~"EOS"
  elcom
EOS

INPUT3 = <<~"EOS"
  1 1
  Welcome to the paiza! I`m studying ruby!
EOS
OUTPUT3 = <<~"EOS"
  W
EOS

p INPUT1
# > "2 6\nthis is a pen\n"
p INPUT2
# > "2 6\nWelcome to the paiza! I`m studying ruby!\n"
p INPUT3
# > "1 1\nWelcome to the paiza! I`m studying ruby!\n"

続いて問題を解くメソッド( solve メソッドとします)を変数の下に定義します。

まず、入力データを受け取る処理を書きます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
def solve(input_lines)
# 入力データ受け取り
input_lines = input_lines.split("\n")
a, b = input_lines.shift.split.map(&:to_i)
s = input_lines.shift
# 確認用コード
[a, b, s]
end
# 確認用コード
p solve(INPUT1)
# > [2, 6, "this is a pen"]
p solve(INPUT2)
# > [2, 6, "Welcome to the paiza! I`m studying ruby!"]
p solve(INPUT3)
# > [1, 1, "Welcome to the paiza! I`m studying ruby!"]
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") a, b = input_lines.shift.split.map(&:to_i) s = input_lines.shift # 確認用コード [a, b, s] end # 確認用コード p solve(INPUT1) # > [2, 6, "this is a pen"] p solve(INPUT2) # > [2, 6, "Welcome to the paiza! I`m studying ruby!"] p solve(INPUT3) # > [1, 1, "Welcome to the paiza! I`m studying ruby!"]
def solve(input_lines)
  # 入力データ受け取り
  input_lines = input_lines.split("\n")
  a, b = input_lines.shift.split.map(&:to_i)
  s = input_lines.shift

  # 確認用コード
  [a, b, s]
end

# 確認用コード
p solve(INPUT1)
# > [2, 6, "this is a pen"]
p solve(INPUT2)
# > [2, 6, "Welcome to the paiza! I`m studying ruby!"]
p solve(INPUT3)
# > [1, 1, "Welcome to the paiza! I`m studying ruby!"]

データが正しく受け取れていれば、solve メソッドに指定された範囲の文字列を抜き出す処理を追加していきます。

  • a番目の文字を表す添字は[a - 1]、b番目の文字を表す添字は[b - 1]
  • s[a - 1]からs[b - 1]の文字を連結した文字列を作る
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
def solve(input_lines)
# 入力データ受け取り
input_lines = input_lines.split("\n")
a, b = input_lines.shift.split.map(&:to_i)
s = input_lines.shift
# 文字列のa番目からb番目までを参照して result に追加していく
result = ""
(a..b).each { |idx| result << s[idx - 1] }
# 確認用コード
result
end
# 確認用コード
p solve(INPUT1)
# > "his i"
p solve(INPUT1) == OUTPUT1
# > false
p solve(INPUT2)
# > "elcom"
p solve(INPUT2) == OUTPUT2
# > false
p solve(INPUT3)
# > "W"
p solve(INPUT3) == OUTPUT3
# > false
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") a, b = input_lines.shift.split.map(&:to_i) s = input_lines.shift # 文字列のa番目からb番目までを参照して result に追加していく result = "" (a..b).each { |idx| result << s[idx - 1] } # 確認用コード result end # 確認用コード p solve(INPUT1) # > "his i" p solve(INPUT1) == OUTPUT1 # > false p solve(INPUT2) # > "elcom" p solve(INPUT2) == OUTPUT2 # > false p solve(INPUT3) # > "W" p solve(INPUT3) == OUTPUT3 # > false
def solve(input_lines)
  # 入力データ受け取り
  input_lines = input_lines.split("\n")
  a, b = input_lines.shift.split.map(&:to_i)
  s = input_lines.shift

  # 文字列のa番目からb番目までを参照して result に追加していく
  result = ""
  (a..b).each { |idx| result << s[idx - 1] }

  # 確認用コード
  result
end

# 確認用コード
p solve(INPUT1)
# > "his i"
p solve(INPUT1) == OUTPUT1
# > false
p solve(INPUT2)
# > "elcom"
p solve(INPUT2) == OUTPUT2
# > false
p solve(INPUT3)
# > "W"
p solve(INPUT3) == OUTPUT3
# > false

あとは出力形式を整えれば完成です。

p solve(INPUT1)puts solve(STDIN.read)に変更すれば正解となりますが、p solve(INPUT1) == OUTPUT1 -> true を確認するために、結果を改行区切りの文字列に変換して、末尾にも改行を加えます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
def solve(input_lines)
# 入力データ受け取り
input_lines = input_lines.split("\n")
a, b = input_lines.shift.split.map(&:to_i)
s = input_lines.shift
# 文字列のa番目からb番目までを参照して result に追加していく
result = ""
(a..b).each { |idx| result << s[idx - 1] }
# 文字列型に変換して末尾に改行を追加する
result.to_s << "\n"
end
p solve(INPUT1)
# > "his i\n"
p solve(INPUT1) == OUTPUT1
# > true
p solve(INPUT2)
# > "elcom\n"
p solve(INPUT2) == OUTPUT2
# > true
p solve(INPUT3)
# > "W\n"
p solve(INPUT3) == OUTPUT3
# > true
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") a, b = input_lines.shift.split.map(&:to_i) s = input_lines.shift # 文字列のa番目からb番目までを参照して result に追加していく result = "" (a..b).each { |idx| result << s[idx - 1] } # 文字列型に変換して末尾に改行を追加する result.to_s << "\n" end p solve(INPUT1) # > "his i\n" p solve(INPUT1) == OUTPUT1 # > true p solve(INPUT2) # > "elcom\n" p solve(INPUT2) == OUTPUT2 # > true p solve(INPUT3) # > "W\n" p solve(INPUT3) == OUTPUT3 # > true
def solve(input_lines)
  # 入力データ受け取り
  input_lines = input_lines.split("\n")
  a, b = input_lines.shift.split.map(&:to_i)
  s = input_lines.shift

  # 文字列のa番目からb番目までを参照して result に追加していく
  result = ""
  (a..b).each { |idx| result << s[idx - 1] }

  # 文字列型に変換して末尾に改行を追加する
  result.to_s << "\n"
end

p solve(INPUT1)
# > "his i\n"
p solve(INPUT1) == OUTPUT1
# > true
p solve(INPUT2)
# > "elcom\n"
p solve(INPUT2) == OUTPUT2
# > true
p solve(INPUT3)
# > "W\n"
p solve(INPUT3) == OUTPUT3
# > true

確認用コードを標準入力からのデータ受け取りに変更して、動作確認をしたら提出します。
複数行のデータ受け取りなので STDIN.read を使います。(入力終了は Ctrl+D 又は Ctrl+Z)

解答コード
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
def solve(input_lines)
# 入力データ受け取り
input_lines = input_lines.split("\n")
a, b = input_lines.shift.split.map(&:to_i)
s = input_lines.shift
# 文字列のa番目からb番目までを参照して result に追加していく
result = ""
(a..b).each { |idx| result << s[idx - 1] }
# 文字列型に変換して末尾に改行を追加する
result.to_s << "\n"
end
puts solve(STDIN.read)
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") a, b = input_lines.shift.split.map(&:to_i) s = input_lines.shift # 文字列のa番目からb番目までを参照して result に追加していく result = "" (a..b).each { |idx| result << s[idx - 1] } # 文字列型に変換して末尾に改行を追加する result.to_s << "\n" end puts solve(STDIN.read)
def solve(input_lines)
  # 入力データ受け取り
  input_lines = input_lines.split("\n")
  a, b = input_lines.shift.split.map(&:to_i)
  s = input_lines.shift

  # 文字列のa番目からb番目までを参照して result に追加していく
  result = ""
  (a..b).each { |idx| result << s[idx - 1] }

  # 文字列型に変換して末尾に改行を追加する
  result.to_s << "\n"
end

puts solve(STDIN.read)
他の解答例
  • 文字列[開始位置..終了位置]sliceメソッドで文字列を抜き出す。
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
def solve(input_lines)
# 入力データ受け取り
input_lines = input_lines.split("\n")
a, b = input_lines.shift.split.map(&:to_i)
s = input_lines.shift
# 文字列[開始位置..終了位置] で文字列を抜き出す
result = s[a - 1..b - 1]
# sliceメソッドで文字列を抜き出す
# result = s.slice(a - 1..b - 1)
# 末尾に改行を追加する
result << "\n"
end
puts solve(STDIN.read)
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") a, b = input_lines.shift.split.map(&:to_i) s = input_lines.shift # 文字列[開始位置..終了位置] で文字列を抜き出す result = s[a - 1..b - 1] # sliceメソッドで文字列を抜き出す # result = s.slice(a - 1..b - 1) # 末尾に改行を追加する result << "\n" end puts solve(STDIN.read)
def solve(input_lines)
  # 入力データ受け取り
  input_lines = input_lines.split("\n")
  a, b = input_lines.shift.split.map(&:to_i)
  s = input_lines.shift

  # 文字列[開始位置..終了位置] で文字列を抜き出す
  result = s[a - 1..b - 1]

  # sliceメソッドで文字列を抜き出す
  # result = s.slice(a - 1..b - 1)

  # 末尾に改行を追加する
  result << "\n"
end

puts solve(STDIN.read)

今回のまとめ

文字列の位置指定、範囲指定、文字長さの取得などを扱いました。

配列の位置指定・範囲指定・要素数の取得と同じ書き方なので、セットで覚えておくとお得ですね!



【PR】アルゴリズム学習でお世話になった本


アルゴリズム関連の技術書は大抵C/C++で書かれていますが、ある程度プログラムが出来れば、処理の流れは理解することが出来ます。






通称: 螺旋本。C++で解説されています。AOJ(Aizu Online Judge)を運営している会津大学の渡辺准教授が書いた本です。データ構造や計算量の内容から丁寧に書いてありますのでアルゴリズム学習の最初の参考書としてオススメです。







通称: 蟻本。C++で解説されています。競技プログラミング中級者の定番書と言われていて、競技プログラミングで利用できる色々なアルゴリズムを学ぶことが出来ます。かなり高度な内容も含まれているので1冊分を完全に理解するのにはかなりの時間がかかりそうですが、手元に置いて何度も読み返しています。







通称: チーター本。C#, C++, JAVAでTopcoderの問題を解説しています。初心者~中級者向けに書かれているので解説が非常に丁寧です。







Python3でアルゴリズムを解説している本です。講義スタイルの本で、図やフローチャートを使ってアルゴリズムとデータ構造についてしっかりと説明されています。代わりにコードは少なめです。Pythonコードが読めなくても十分理解できると思います。


-paiza, プログラミング
-, , , ,

S