Ruby プログラミング

[Ruby] 文字列の連結・繰り返し・インデックス指定・置き換え

string_1

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

paizaスキルアップ問題集でよく出題されている文字列の操作を調べてみました。
その中でも基本操作である文字列の連結や繰り返し、インデックスでの指定や置き換えについてご紹介します。

文字列の連結と繰り返し

文字列の連結1

+ 演算子を使うと、文字列を足し算のように扱うことが出来ます。

family_name = "Yamada"
first_name = "Taro"
full_name = family_name + first_name

p full_name
# > "YamadaTaro"
p family_name
# > "Yamada"
p first_name
# > "Taro"
文字列の連結2

<< 演算子を使うと、元の文字列に連結することが出来ます。元の文字列が書き換えられてしまいますが、+ 演算子より高速です。

family_name = "Yamada"
first_name = "Taro"
family_name << first_name

p family_name
# > "YamadaTaro"
文字列の繰り返し

* 演算子を使うと、文字列を繰り返すことが出来ます。

name = "sakura"

p name * 2
# > "sakurasakura"
文字列の連結と繰り返しを組み合わせて使う
p "す" << "も" * 8 << "のうち"
# > "すもももももももものうち"
() カッコで計算の優先順位を変更
p "な" << "つ" * 4 << "コ" * 2 << "ナッツ"
# > "なつつつつココナッツ"

p ("な" << "つ") * 4 << "コ" * 2 << "ナッツ"
# > "なつなつなつなつココナッツ"
文字列の連結を使ってpaiza練習問題を解いてみる
文字列の連結 (paizaランク D 相当)

※ paiza レベルアップ問題集 文字列処理メニューより

問題:

与えられる文字列の数 N と、 N 個の文字列が与えられるので、それらを順に末尾に連結した文字列を出力してください。

例として、"abc", "def", "ghi" という順で文字列が与えられたとき、連結後の文字列は"abcdefghi" となります。

入力される値

N
S_1
...
S_N

  •  1 行目で与えられる文字列の数 N が与えられます。
  •  続く N 行で連結する文字列 S_i (1 ≦ i ≦ N) が与えられます。

期待する出力

N 個の文字列を順に後ろに連結した文字列を 1 行で出力してください。

条件

  • 1 ≦ N ≦ 100
  •  1 ≦ |S_i| ≦ 10000 ( |S_i| は、 S_i の文字数です。1 ≦ i ≦ N)

入力例1
2
pa
iza
出力例1
paiza

入力例2
30
q
w
e
r
t
y
u
i
o
p
l
k
j
h
g
f
d
s
a
z
x
c
v
b
n
m
l
o
l
w
出力例2
qwertyuioplkjhgfdsazxcvbnmlolw

入力例3
9
mo
ji
re
tu
no
re
n
ke
tu
出力例3
mojiretunorenketu

入力例4
13
p
ro
g
ra
m
ming
i
s
soooooooooooooooo
difficult
oh
my
god
出力例4
programmingissoooooooooooooooodifficultohmygod

解答例:

# [解答例1] getsを使った方法
# 最初にinput_strを空文字で初期化
input_str = ""
gets.to_i.times do
  # input_str の末尾に gets で入力された文字を追加していく
  input_str << gets.chomp
end
puts input_str

# [解答例2] STDIN.readを使った方法
# 改行で分割して1つ目の要素は破棄して、2つ目以降の要素を input_arr に代入する。
_, *input_arr = STDIN.read.split("\n")
# 配列の要素を連結して表示
puts input_arr.join

文字列の参照と書き換え

文字列の参照

文字列には前と後からのインデックス(添え字)が振られており、インデックスを指定すると、対応する文字を取得することが出来ます。
前からのインデックスは[0]からのスタート、後ろからのインデックスは[-1]からのスタートとなっており、 .. を使用すると範囲を表すことが出来ます。

文字列 Y a m a d a T a r o
前からのインデックス 0 1 2 3 4 5 6 7 8 9
後からのインデックス -10 -9 -8 -7 -6 -5 -4 -3 -2 -1
name = "YamadaTaro"

# 3番目の文字を参照する
p name[2]
# > "m"

# 3番目から6番目までの文字を参照する
p name[2..5]
# > "mada"

# 3番目から4文字を参照する
p name[2, 4]
# > "mada"

# 最初から6番目までの文字を参照する
p name[..5]
# > "Yamada"

# 7番目から最後までの文字を参照する
p name[6..]
# > "Taro"
文字列の参照を使ってpaiza練習問題を解いてみる
部分文字列 (paizaランク D 相当)

※ paiza レベルアップ問題集 文字列処理メニューより

問題:

文字列 S と整数 i , j が与えられるので、 S の i 文字目から j 文字目までの部分文字列を出力してください。

入力される値

S
i j

期待する出力

S の i 文字目から j 文字目までの部分文字列を 1 行で出力してください。

S_i ... S_j

条件

  • 1 ≦ |S| ≦ 10000 ( |S| は、 S の文字数です。)
  • 1 ≦ i ≦ j ≦ |S|

入力例1
paiza
1 3
出力例1
pai

入力例2
PAIZA
2 4
出力例2
AIZ

入力例3
ABCDEFGHIJKLMNO!QRSTUVW&XYZ
5 20
出力例3
EFGHIJKLMNO!QRST

入力例4
1234567890
9 9
出力例4
9

解答例:

# [解答例1] getsを使った方法
input_str = gets.chomp
i, j = gets.split.map do |str_num|
  # インデックスは [0] からスタートなので -1
  str_num.to_i - 1
end
puts input_str[i..j]

# [解答例2] STDIN.readを使った方法
input_str, tmp_line = STDIN.read.split("\n")
i, j = tmp_line.split.map do |str_num|
  # インデックスは [0] からスタートなので -1
  str_num.to_i - 1
end
puts input_str[i..j]
文字の書き換え

インデックスを指定して新たな文字を代入すると文字を上書きすることが出来ます。

name = "YamadaTaro"

# 1番目を上書きする
name[0] = "H"
p name
# > "HamadaTaro"

# 7番目から8番目を上書きする
name[6..7] = "Koji"
p name
# > "HamadaKojiro"

# 与えた文字を含むならその部分を書き換える
name["Hamada"] = "Sasaki"
p name
# > "SasakiKojiro"

# 与えた文字列が含まれない場合はエラーがでる
name["Yamada"] = "Suzuki"
# > IndexError(String not matched)

p name["Yamada"]
# > nil
# "Yamada"という文字は含まれていない
 
p name["Sasaki"]
# > "Sasaki"
# "Sasaki"という文字が含まれている
文字の書き換えを使ってpaiza練習問題を解いてみる
文字列の書き換え (paizaランク D 相当)

※ paiza レベルアップ問題集 文字列処理メニューより

問題:

文字列 S と整数 i と文字 c が与えられるので、S の i 文字目を c に書き換えたものを出力してください。

入力される値

S
i c

  •  1 行目では、文字列 S が与えられます。
  •  2 行目では、整数 i と、文字 c が与えられます。

期待する出力

S の i 文字目を c に書き換えたものを 1 行で出力してください。

条件

  • 1 ≦ i ≦ |S| ( |S| は、 S の文字数です。)
  • 1 ≦ |S| ≦ 100
  • c は 1 文字

入力例1
paiza
1 P
出力例1
Paiza

入力例2
PAIZA
5 a
出力例2
PAIZa

入力例3
ABCDEFGHIJKLMNOPQRSTUVW&XYZ
16 !
出力例3
ABCDEFGHIJKLMNO!QRSTUVW&XYZ

入力例4
1234567890
2 +
出力例4
1+34567890

解答例:

# [解答例1] getsを使った方法
input_str = gets.chomp
i, c = gets.split
# インデックスは [0] からスタートなので -1
i = i.to_i - 1
input_str[i] = c
puts input_str

# [解答例2] STDIN.readを使った方法
input_str, tmp_line = STDIN.read.split("\n")
i, c = tmp_line.split
# インデックスは [0] からスタートなので -1
i = i.to_i - 1
input_str[i] = c
puts input_str

今回のまとめ

  • 文字列のインデックスを指定すると、対応した文字が取り出せる
  • 文字列のインデックスを範囲で指定することも出来る
  • 文字列のインデックスを指定して新しい文字を代入すると上書きできる
  • 前からのインデックスは0から始まり、後ろからのインデックスは-1から始まる
今回は基本的な文字列の操作をご紹介しました。
文字列操作メソッドもいくつか覚えれば文字列操作系の問題が楽に解けると思いますので次回以降でご紹介致します。

【PR】Ruby学習でお世話になった本




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


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






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







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







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







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


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

© 2024 じゃいごテック