質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

2回答

1601閲覧

冒頭から繰り返しを含む文字列に対し、最長の繰り返し部分と余りを見つけるには?

manman

総合スコア233

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2015/04/18 05:52

編集2015/04/18 10:42

冒頭から繰り返しを含む文字列strに対し、
最長の繰り返し部分をstr_a、
繰り返しの回数をn(>1)、
余りをstr_bとします。
(すなわち、
str == str_a * n + str_b
が真になるstr_a, n, str_bのうち
str_aの長さが最も長くなる
str_a, n, str_b
を解とします。)

例1)
str = '123312330'
なら、
str_a = '1233',
n = 2
str_b = '0'
例2)
str = '1233123301233123301233'
なら、
str_a = '123312330',
n = 2
str_b = '1233'
例3)
str = '123312331233012331233123312331233'
なら、
str_a = '1233',
n = 3
str_b = '012331233123312331233'
例4)
str = '1233123312331233012331233123312331233'
なら、
str_a = '12331233',
n = 2
str_b = '012331233123312331233'

strが与えられたとき、
このようなstr_a, n, str_bを返すような
コードを書いていただけないでしょうか?
なお、メタ文字列の知識が少ない初心者(私を含める)
にとっても分かりやすい解説をつけていただければ
なお幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

riocampos

2015/04/18 07:47

n >= 2 という拘束条件はつけて良いでしょうか。n = 1 だと str_a と str_b が不定(というかかなり任意)になるので。
manman

2015/04/18 07:50

strが繰り返しを含んでいるとしておくべきでした。
riocampos

2015/04/18 08:07

もう一つ。文字列 str の冒頭から繰り返し文字列 str_a が始まる、という拘束条件は付けても良いでしょうか。
manman

2015/04/18 08:12

例3)を追加しました。
guest

回答2

0

ベストアンサー

lang

1DATA.each do |line| 2 line.chomp! 3 if /^((.+)\2+)(.*)$/ =~ line 4 puts "str_a = #{$2}, n = #{$1.size/$2.size}, str_b = #{$3}" 5 end 6end 7 8__END__ 9123312330 101233123301233123301233 11123312331233012331233123312331233 121233123312331233012331233123312331233

投稿2015/04/18 10:03

編集2015/04/18 10:08
otn

総合スコア84555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chokojori

2015/04/18 10:28

お、エレガントだ。どうも自分は、入れ子になったかっこを正規表現の中で使うのに躊躇するところがありますね。(最大一致がどのように解釈されるか、自信が持てなくて。)
manman

2015/04/18 11:15

((.+)\2+) が str_a * n、(.*) がstr_b ということで間違いないでしょうか?
otn

2015/04/18 12:40

はいそうです。
guest

0

これでどうですか。(例2の回答が2つできちゃいますが)

lang

1def find_repeat_and_rest(str) 2 len = 1 # 繰り返しの長さを1と仮定する。 3 while len < str.length 4 str_a = str[0, len] 5 if /^(#{str_a}){2,}(.+)$/ =~ str 6 puts "str_a = '#{str_a}'" 7 puts "n = #{(str.length - $2.length) / len}" 8 puts "str_b = '#{$2}'" 9 end 10 len += 1 11 end 12end

投稿2015/04/18 07:50

chokojori

総合スコア971

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

riocampos

2015/04/18 08:41

最大(というか最長)だそうなのでこんな感じですね。 def find_repeat_and_rest(str) len = str.length / 2 while len > 0 str_a = str[0, len] if /^(#{str_a}){2,}(.+)$/ =~ str puts "str_a = '#{str_a}'" puts "n = #{(str.length - $2.length) / len}" puts "str_b = '#{$2}'" break end len -= 1 end end 自分で書いた分はもっと下手だったので投稿しませんorz
riocampos

2015/04/18 08:41

ああインデント消えちゃうんだ>_<
manman

2015/04/18 09:22

すいません。以前も別の質問 (https://teratail.com/questions/8502) で似たようなことをおたずねしたのですが、 ifからbreakまでのコードの意味を教えていただけないでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問